mirror of https://github.com/docker/docs.git
Merge pull request #1940 from nathanleclaire/gh_api_rate_limit
Add --github-api-token flag and troubleshooting section
This commit is contained in:
commit
cc00ece828
72
README.md
72
README.md
|
@ -54,3 +54,75 @@ Full documentation [is available here](https://docs.docker.com/machine/).
|
||||||
|
|
||||||
Want to hack on Machine? Please start with the [Contributing Guide](https://github.com/docker/machine/blob/master/CONTRIBUTING.md).
|
Want to hack on Machine? Please start with the [Contributing Guide](https://github.com/docker/machine/blob/master/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
Docker Machine tries to do the right thing in a variety of scenarios but
|
||||||
|
sometimes things do not go according to plan. Here is a quick troubleshooting
|
||||||
|
guide which may help you to resolve of the issues you may be seeing.
|
||||||
|
|
||||||
|
Note that some of the suggested solutions are only available on the Docker
|
||||||
|
Machine master branch. If you need them, consider compiling Docker Machine from
|
||||||
|
source. There are also [unofficial pre-compiled master
|
||||||
|
binaries](https://docker-machine-builds.evanhazlett.com/latest) hosted by
|
||||||
|
[@ehazlett](https://github.com/ehazlett).
|
||||||
|
|
||||||
|
#### `docker-machine` hangs
|
||||||
|
|
||||||
|
A common issue with Docker Machine is that it will hang when attempting to start
|
||||||
|
up the virtual machine. Since starting the machine is part of the `create`
|
||||||
|
process, `create` is often where these types of errors show up.
|
||||||
|
|
||||||
|
A hang could be due to a variety of factors, but the most common suspect is
|
||||||
|
networking. Consider the following:
|
||||||
|
|
||||||
|
- Are you using a VPN? If so, try disconnecting and see if creation will
|
||||||
|
succeed without the VPN. Some VPN software aggressively controls routes and
|
||||||
|
you may need to [manually add the route](https://github.com/docker/machine/issues/1500#issuecomment-121134958).
|
||||||
|
- Are you connected to a proxy server, corporate or otherwise? If so, take a
|
||||||
|
look at the `--no-proxy` flag for `env` and at [setting environment variables
|
||||||
|
for the created Docker Engine](https://docs.docker.com/machine/reference/create/#specifying-configuration-options-for-the-created-docker-engine).
|
||||||
|
- Are there a lot of host-only interfaces listed by the command `VBoxManage list
|
||||||
|
hostonlyifs`? If so, this has sometimes been known to cause bugs. Consider
|
||||||
|
removing the ones you are not using (`VBoxManage hostonlyif remove name`) and
|
||||||
|
trying machine creation again.
|
||||||
|
|
||||||
|
We are keenly aware of this as an issue and working towards a set of solutions
|
||||||
|
which is robust for all users, so please give us feedback and/or report issues,
|
||||||
|
workarounds, and desired workflows as you discover them.
|
||||||
|
|
||||||
|
#### Machine creation errors out before finishing
|
||||||
|
|
||||||
|
If you see messages such as "exit status 1" creating machines with VirtualBox,
|
||||||
|
this frequently indicates that there is an issue with VirtualBox itself. Please
|
||||||
|
[file an issue](https://github.com/docker/machine/issues/new) and include a link
|
||||||
|
to a [Github Gist](https://gist.github.com/) with the output of the VirtualBox
|
||||||
|
log (usually located at
|
||||||
|
`$HOME/.docker/machine/machines/machinename/machinename/Logs/VBox.log`), as well
|
||||||
|
as the output of running the Docker Machine command which is failing with the
|
||||||
|
global `--debug` flag enabled. This will help us to track down which versions
|
||||||
|
of VirtualBox are failing where, and under which conditions.
|
||||||
|
|
||||||
|
If you see messages such as "exit status 255", this frequently indicates there
|
||||||
|
has been an issue with SSH. Please investigate your SSH configuration if you
|
||||||
|
have one, and/or [file an issue](https://github.com/docker/machine/issues).
|
||||||
|
|
||||||
|
#### "You may be getting rate limited by Github" error message
|
||||||
|
|
||||||
|
In order to `create` or `upgrade` virtual machines running Docker, Docker
|
||||||
|
Machine will check the Github API for the latest release of the [boot2docker
|
||||||
|
operating system](https://github.com/boot2docker/boot2docker). The Github API
|
||||||
|
allows for a small number of unauthenticated requests from a given client, but
|
||||||
|
if you share an IP address with many other users (e.g. in an office), you may
|
||||||
|
get rate limited by their API, and Docker Machine will error out with messages
|
||||||
|
indicating this.
|
||||||
|
|
||||||
|
In order to work around this issue, you can [generate a
|
||||||
|
token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/)
|
||||||
|
and pass it to Docker Machine using the global `--github-api-token` flag like
|
||||||
|
so:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker-machine --github-api-token=token create -d virtualbox newbox
|
||||||
|
```
|
||||||
|
|
||||||
|
This should eliminate any issues you've been experiencing with rate limiting.
|
||||||
|
|
|
@ -15,6 +15,10 @@ import (
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
GithubApiToken string
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
timeout = time.Second * 5
|
timeout = time.Second * 5
|
||||||
)
|
)
|
||||||
|
@ -70,15 +74,36 @@ func NewB2dUtils(githubApiBaseUrl, githubBaseUrl, storePath string) *B2dUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *B2dUtils) getReleasesRequest() (*http.Request, error) {
|
||||||
|
apiUrl := fmt.Sprintf("%s/repos/boot2docker/boot2docker/releases", b.githubApiBaseUrl)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", apiUrl, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if GithubApiToken != "" {
|
||||||
|
req.Header.Add("Authorization", fmt.Sprintf("token %s", GithubApiToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get the latest boot2docker release tag name (e.g. "v0.6.0").
|
// Get the latest boot2docker release tag name (e.g. "v0.6.0").
|
||||||
// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests
|
// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests
|
||||||
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL() (string, error) {
|
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL() (string, error) {
|
||||||
client := getClient()
|
client := getClient()
|
||||||
apiUrl := fmt.Sprintf("%s/repos/boot2docker/boot2docker/releases", b.githubApiBaseUrl)
|
|
||||||
rsp, err := client.Get(apiUrl)
|
req, err := b.getReleasesRequest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rsp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
defer rsp.Body.Close()
|
defer rsp.Body.Close()
|
||||||
|
|
||||||
var t []struct {
|
var t []struct {
|
||||||
|
|
|
@ -56,3 +56,31 @@ func TestDownloadIso(t *testing.T) {
|
||||||
t.Fatalf("expected data \"%s\"; received \"%s\"", testData, string(data))
|
t.Fatalf("expected data \"%s\"; received \"%s\"", testData, string(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetReleasesRequestNoToken(t *testing.T) {
|
||||||
|
GithubApiToken = ""
|
||||||
|
b2d := NewB2dUtils("", "", "/tmp/store")
|
||||||
|
req, err := b2d.getReleasesRequest()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Expected err to be nil, got ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Header.Get("Authorization") != "" {
|
||||||
|
t.Fatal("Expected not to get an 'Authorization' header, but got one: ", req.Header.Get("Authorization"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetReleasesRequest(t *testing.T) {
|
||||||
|
expectedToken := "CATBUG"
|
||||||
|
GithubApiToken = expectedToken
|
||||||
|
b2d := NewB2dUtils("", "", "/tmp/store")
|
||||||
|
|
||||||
|
req, err := b2d.getReleasesRequest()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Expected err to be nil, got ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Header.Get("Authorization") != fmt.Sprintf("token %s", expectedToken) {
|
||||||
|
t.Fatal("Header was not set as expected: ", req.Header.Get("Authorization"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
11
main.go
11
main.go
|
@ -7,10 +7,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
|
|
||||||
"github.com/docker/machine/commands"
|
"github.com/docker/machine/commands"
|
||||||
"github.com/docker/machine/commands/mcndirs"
|
"github.com/docker/machine/commands/mcndirs"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
|
"github.com/docker/machine/libmachine/mcnutils"
|
||||||
"github.com/docker/machine/libmachine/ssh"
|
"github.com/docker/machine/libmachine/ssh"
|
||||||
"github.com/docker/machine/version"
|
"github.com/docker/machine/version"
|
||||||
)
|
)
|
||||||
|
@ -75,9 +75,12 @@ func main() {
|
||||||
app.Author = "Docker Machine Contributors"
|
app.Author = "Docker Machine Contributors"
|
||||||
app.Email = "https://github.com/docker/machine"
|
app.Email = "https://github.com/docker/machine"
|
||||||
app.Before = func(c *cli.Context) error {
|
app.Before = func(c *cli.Context) error {
|
||||||
|
// TODO: Need better handling of config, everything is too
|
||||||
|
// complected together right now.
|
||||||
if c.GlobalBool("native-ssh") {
|
if c.GlobalBool("native-ssh") {
|
||||||
ssh.SetDefaultClient(ssh.Native)
|
ssh.SetDefaultClient(ssh.Native)
|
||||||
}
|
}
|
||||||
|
mcnutils.GithubApiToken = c.GlobalString("github-api-token")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
app.Commands = commands.Commands
|
app.Commands = commands.Commands
|
||||||
|
@ -120,6 +123,12 @@ func main() {
|
||||||
Usage: "Private key used in client TLS auth",
|
Usage: "Private key used in client TLS auth",
|
||||||
Value: "",
|
Value: "",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
EnvVar: "MACHINE_GITHUB_API_TOKEN",
|
||||||
|
Name: "github-api-token",
|
||||||
|
Usage: "Token to use for requests to the Github API",
|
||||||
|
Value: "",
|
||||||
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
EnvVar: "MACHINE_NATIVE_SSH",
|
EnvVar: "MACHINE_NATIVE_SSH",
|
||||||
Name: "native-ssh",
|
Name: "native-ssh",
|
||||||
|
|
Loading…
Reference in New Issue