diff --git a/opts/hosts.go b/opts/hosts.go index f0e392e1e5..de22161cbc 100644 --- a/opts/hosts.go +++ b/opts/hosts.go @@ -8,25 +8,25 @@ import ( "strings" ) -var ( - // DefaultHTTPPort Default HTTP Port used if only the protocol is provided to -H flag e.g. dockerd -H tcp:// +const ( + // defaultHTTPPort Default HTTP Port used if only the protocol is provided to -H flag e.g. dockerd -H tcp:// // These are the IANA registered port numbers for use with Docker // see http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker - DefaultHTTPPort = 2375 // Default HTTP Port - // DefaultTLSHTTPPort Default HTTP Port used when TLS enabled - DefaultTLSHTTPPort = 2376 // Default TLS encrypted HTTP Port - // DefaultUnixSocket Path for the unix socket. + defaultHTTPPort = "2375" // Default HTTP Port + // defaultTLSHTTPPort Default HTTP Port used when TLS enabled + defaultTLSHTTPPort = "2376" // Default TLS encrypted HTTP Port + // defaultUnixSocket Path for the unix socket. // Docker daemon by default always listens on the default unix socket - DefaultUnixSocket = "/var/run/docker.sock" - // DefaultTCPHost constant defines the default host string used by docker on Windows - DefaultTCPHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort) + defaultUnixSocket = "/var/run/docker.sock" + // defaultTCPHost constant defines the default host string used by docker on Windows + defaultTCPHost = "tcp://" + defaultHTTPHost + ":" + defaultHTTPPort // DefaultTLSHost constant defines the default host string used by docker for TLS sockets - DefaultTLSHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultTLSHTTPPort) + defaultTLSHost = "tcp://" + defaultHTTPHost + ":" + defaultTLSHTTPPort // DefaultNamedPipe defines the default named pipe used by docker on Windows - DefaultNamedPipe = `//./pipe/docker_engine` + defaultNamedPipe = `//./pipe/docker_engine` // hostGatewayName defines a special string which users can append to --add-host // to add an extra entry in /etc/hosts that maps host.docker.internal to the host IP - // TODO Consider moving the HostGatewayName constant defined in docker at + // TODO Consider moving the hostGatewayName constant defined in docker at // github.com/docker/docker/daemon/network/constants.go outside of the "daemon" // package, so that the CLI can consume it. hostGatewayName = "host-gateway" @@ -52,9 +52,9 @@ func ParseHost(defaultToTLS bool, val string) (string, error) { host := strings.TrimSpace(val) if host == "" { if defaultToTLS { - host = DefaultTLSHost + host = defaultTLSHost } else { - host = DefaultHost + host = defaultHost } } else { var err error @@ -76,11 +76,11 @@ func parseDockerDaemonHost(addr string) (string, error) { switch addrParts[0] { case "tcp": - return ParseTCPAddr(addrParts[1], DefaultTCPHost) + return ParseTCPAddr(addrParts[1], defaultTCPHost) case "unix": - return parseSimpleProtoAddr("unix", addrParts[1], DefaultUnixSocket) + return parseSimpleProtoAddr("unix", addrParts[1], defaultUnixSocket) case "npipe": - return parseSimpleProtoAddr("npipe", addrParts[1], DefaultNamedPipe) + return parseSimpleProtoAddr("npipe", addrParts[1], defaultNamedPipe) case "fd": return addr, nil case "ssh": diff --git a/opts/hosts_test.go b/opts/hosts_test.go index 3e6e49703f..aadd646aff 100644 --- a/opts/hosts_test.go +++ b/opts/hosts_test.go @@ -16,24 +16,24 @@ func TestParseHost(t *testing.T) { } valid := map[string]string{ - "": DefaultHost, - " ": DefaultHost, - " ": DefaultHost, + "": defaultHost, + " ": defaultHost, + " ": defaultHost, "fd://": "fd://", "fd://something": "fd://something", - "tcp://host:": fmt.Sprintf("tcp://host:%d", DefaultHTTPPort), - "tcp://": DefaultTCPHost, - "tcp://:2375": fmt.Sprintf("tcp://%s:2375", DefaultHTTPHost), - "tcp://:2376": fmt.Sprintf("tcp://%s:2376", DefaultHTTPHost), + "tcp://host:": fmt.Sprintf("tcp://host:%s", defaultHTTPPort), + "tcp://": defaultTCPHost, + "tcp://:2375": fmt.Sprintf("tcp://%s:%s", defaultHTTPHost, defaultHTTPPort), + "tcp://:2376": fmt.Sprintf("tcp://%s:%s", defaultHTTPHost, defaultTLSHTTPPort), "tcp://0.0.0.0:8080": "tcp://0.0.0.0:8080", "tcp://192.168.0.0:12000": "tcp://192.168.0.0:12000", "tcp://192.168:8080": "tcp://192.168:8080", "tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P - " tcp://:7777/path ": fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost), + " tcp://:7777/path ": fmt.Sprintf("tcp://%s:7777/path", defaultHTTPHost), "tcp://docker.com:2375": "tcp://docker.com:2375", - "unix://": "unix://" + DefaultUnixSocket, + "unix://": "unix://" + defaultUnixSocket, "unix://path/to/socket": "unix://path/to/socket", - "npipe://": "npipe://" + DefaultNamedPipe, + "npipe://": "npipe://" + defaultNamedPipe, "npipe:////./pipe/foo": "npipe:////./pipe/foo", } @@ -69,13 +69,13 @@ func TestParseDockerDaemonHost(t *testing.T) { "[::1]:5555/path": "tcp://[::1]:5555/path", "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2375", "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path", - ":6666": fmt.Sprintf("tcp://%s:6666", DefaultHTTPHost), - ":6666/path": fmt.Sprintf("tcp://%s:6666/path", DefaultHTTPHost), - "tcp://": DefaultTCPHost, - "tcp://:7777": fmt.Sprintf("tcp://%s:7777", DefaultHTTPHost), - "tcp://:7777/path": fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost), + ":6666": fmt.Sprintf("tcp://%s:6666", defaultHTTPHost), + ":6666/path": fmt.Sprintf("tcp://%s:6666/path", defaultHTTPHost), + "tcp://": defaultTCPHost, + "tcp://:7777": fmt.Sprintf("tcp://%s:7777", defaultHTTPHost), + "tcp://:7777/path": fmt.Sprintf("tcp://%s:7777/path", defaultHTTPHost), "unix:///run/docker.sock": "unix:///run/docker.sock", - "unix://": "unix://" + DefaultUnixSocket, + "unix://": "unix://" + defaultUnixSocket, "fd://": "fd://", "fd://something": "fd://something", "localhost:": "tcp://localhost:2375", diff --git a/opts/hosts_unix.go b/opts/hosts_unix.go index 611407a9d9..344b6c2e1b 100644 --- a/opts/hosts_unix.go +++ b/opts/hosts_unix.go @@ -2,7 +2,8 @@ package opts -import "fmt" +// defaultHost constant defines the default host string used by docker on other hosts than Windows +const defaultHost = "unix://" + defaultUnixSocket -// DefaultHost constant defines the default host string used by docker on other hosts than Windows -var DefaultHost = fmt.Sprintf("unix://%s", DefaultUnixSocket) +// defaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 +const defaultHTTPHost = "localhost" diff --git a/opts/hosts_windows.go b/opts/hosts_windows.go index 7c239e00f1..97c6d857c2 100644 --- a/opts/hosts_windows.go +++ b/opts/hosts_windows.go @@ -2,5 +2,60 @@ package opts -// DefaultHost constant defines the default host string used by docker on Windows -var DefaultHost = "npipe://" + DefaultNamedPipe +// defaultHost constant defines the default host string used by docker on Windows +const defaultHost = "npipe://" + defaultNamedPipe + +// TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5. +// @jhowardmsft, @swernli. +// +// On Windows, this mitigates a problem with the default options of running +// a docker client against a local docker daemon on TP5. +// +// What was found that if the default host is "localhost", even if the client +// (and daemon as this is local) is not physically on a network, and the DNS +// cache is flushed (ipconfig /flushdns), then the client will pause for +// exactly one second when connecting to the daemon for calls. For example +// using docker run windowsservercore cmd, the CLI will send a create followed +// by an attach. You see the delay between the attach finishing and the attach +// being seen by the daemon. +// +// Here's some daemon debug logs with additional debug spew put in. The +// AfterWriteJSON log is the very last thing the daemon does as part of the +// create call. The POST /attach is the second CLI call. Notice the second +// time gap. +// +// time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs" +// time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig" +// time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...." +// time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking.... +// time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...." +// time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...." +// time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func" +// time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create" +// time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2" +// time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate" +// time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON" +// ... 1 second gap here.... +// time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach" +// time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1" +// +// We suspect this is either a bug introduced in GOLang 1.5.1, or that a change +// in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory, +// the Windows networking stack is supposed to resolve "localhost" internally, +// without hitting DNS, or even reading the hosts file (which is why localhost +// is commented out in the hosts file on Windows). +// +// We have validated that working around this using the actual IPv4 localhost +// address does not cause the delay. +// +// This does not occur with the docker client built with 1.4.3 on the same +// Windows build, regardless of whether the daemon is built using 1.5.1 +// or 1.4.3. It does not occur on Linux. We also verified we see the same thing +// on a cross-compiled Windows binary (from Linux). +// +// Final note: This is a mitigation, not a 'real' fix. It is still susceptible +// to the delay if a user were to do 'docker run -H=tcp://localhost:2375...' +// explicitly. + +// defaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 +const defaultHTTPHost = "127.0.0.1" diff --git a/opts/opts_unix.go b/opts/opts_unix.go deleted file mode 100644 index 2766a43a08..0000000000 --- a/opts/opts_unix.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !windows - -package opts - -// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 -const DefaultHTTPHost = "localhost" diff --git a/opts/opts_windows.go b/opts/opts_windows.go deleted file mode 100644 index 98b7251a9e..0000000000 --- a/opts/opts_windows.go +++ /dev/null @@ -1,56 +0,0 @@ -package opts - -// TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5. -// @jhowardmsft, @swernli. -// -// On Windows, this mitigates a problem with the default options of running -// a docker client against a local docker daemon on TP5. -// -// What was found that if the default host is "localhost", even if the client -// (and daemon as this is local) is not physically on a network, and the DNS -// cache is flushed (ipconfig /flushdns), then the client will pause for -// exactly one second when connecting to the daemon for calls. For example -// using docker run windowsservercore cmd, the CLI will send a create followed -// by an attach. You see the delay between the attach finishing and the attach -// being seen by the daemon. -// -// Here's some daemon debug logs with additional debug spew put in. The -// AfterWriteJSON log is the very last thing the daemon does as part of the -// create call. The POST /attach is the second CLI call. Notice the second -// time gap. -// -// time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs" -// time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig" -// time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...." -// time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking.... -// time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...." -// time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...." -// time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func" -// time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create" -// time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2" -// time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate" -// time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON" -// ... 1 second gap here.... -// time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach" -// time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1" -// -// We suspect this is either a bug introduced in GOLang 1.5.1, or that a change -// in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory, -// the Windows networking stack is supposed to resolve "localhost" internally, -// without hitting DNS, or even reading the hosts file (which is why localhost -// is commented out in the hosts file on Windows). -// -// We have validated that working around this using the actual IPv4 localhost -// address does not cause the delay. -// -// This does not occur with the docker client built with 1.4.3 on the same -// Windows build, regardless of whether the daemon is built using 1.5.1 -// or 1.4.3. It does not occur on Linux. We also verified we see the same thing -// on a cross-compiled Windows binary (from Linux). -// -// Final note: This is a mitigation, not a 'real' fix. It is still susceptible -// to the delay if a user were to do 'docker run -H=tcp://localhost:2375...' -// explicitly. - -// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 -const DefaultHTTPHost = "127.0.0.1"