1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #40007 from arkodg/add-host-docker-internal

Support host.docker.internal in dockerd on Linux
This commit is contained in:
Sebastiaan van Stijn 2020-01-27 13:42:26 +01:00 committed by GitHub
commit ca20bc4214
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 5 deletions

View file

@ -64,6 +64,7 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
flags.Var(opts.NewListOptsRef(&conf.DNS, opts.ValidateIPAddress), "dns", "DNS server to use")
flags.Var(opts.NewNamedListOptsRef("dns-opts", &conf.DNSOptions, nil), "dns-opt", "DNS options to use")
flags.Var(opts.NewListOptsRef(&conf.DNSSearch, opts.ValidateDNSSearch), "dns-search", "DNS search domains to use")
flags.Var(opts.NewIPOpt(&conf.HostGatewayIP, ""), "host-gateway-ip", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the default bridge")
flags.Var(opts.NewNamedListOptsRef("labels", &conf.Labels, opts.ValidateLabel), "label", "Set key=value labels to the daemon")
flags.StringVar(&conf.LogConfig.Type, "log-driver", "json-file", "Default driver for container logs")
flags.Var(opts.NewNamedMapOpts("log-opts", conf.LogConfig.Config, nil), "log-opt", "Default log driver options for containers")

View file

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"os"
"reflect"
"strings"
@ -118,6 +119,7 @@ type DNSConfig struct {
DNS []string `json:"dns,omitempty"`
DNSOptions []string `json:"dns-opts,omitempty"`
DNSSearch []string `json:"dns-search,omitempty"`
HostGatewayIP net.IP `json:"host-gateway-ip,omitempty"`
}
// CommonConfig defines the configuration of a docker daemon which is

View file

@ -115,6 +115,16 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]lib
return nil, err
}
parts := strings.SplitN(extraHost, ":", 2)
// If the IP Address is a string called "host-gateway", replace this
// value with the IP address stored in the daemon level HostGatewayIP
// config variable
if parts[1] == network.HostGatewayName {
gateway := daemon.configStore.HostGatewayIP.String()
if gateway == "" {
return nil, fmt.Errorf("unable to derive the IP value for host-gateway")
}
parts[1] = gateway
}
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
}

View file

@ -932,6 +932,19 @@ func (daemon *Daemon) initNetworkController(config *config.Config, activeSandbox
removeDefaultBridgeInterface()
}
// Set HostGatewayIP to the default bridge's IP if it is empty
if daemon.configStore.HostGatewayIP == nil && controller != nil {
if n, err := controller.NetworkByName("bridge"); err == nil {
v4Info, v6Info := n.Info().IpamInfo()
var gateway net.IP
if len(v4Info) > 0 {
gateway = v4Info[0].Gateway.IP
} else if len(v6Info) > 0 {
gateway = v6Info[0].Gateway.IP
}
daemon.configStore.HostGatewayIP = gateway
}
}
return controller, nil
}

View file

@ -0,0 +1,8 @@
package network
const (
// HostGatewayName is the string value that can be passed
// to the IPAddr section in --add-host that is replaced by
// the value of HostGatewayIP daemon config value
HostGatewayName = "host-gateway"
)

View file

@ -120,3 +120,47 @@ func TestDaemonRestartIpcMode(t *testing.T) {
assert.NilError(t, err)
assert.Check(t, is.Equal(string(inspect.HostConfig.IpcMode), "shareable"))
}
// TestDaemonHostGatewayIP verifies that when a magic string "host-gateway" is passed
// to ExtraHosts (--add-host) instead of an IP address, its value is set to
// 1. Daemon config flag value specified by host-gateway-ip or
// 2. IP of the default bridge network
// and is added to the /etc/hosts file
func TestDaemonHostGatewayIP(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon)
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
t.Parallel()
// Verify the IP in /etc/hosts is same as host-gateway-ip
d := daemon.New(t)
// Verify the IP in /etc/hosts is same as the default bridge's IP
d.StartWithBusybox(t)
c := d.NewClientT(t)
ctx := context.Background()
cID := container.Run(ctx, t, c,
container.WithExtraHost("host.docker.internal:host-gateway"),
)
res, err := container.Exec(ctx, c, cID, []string{"cat", "/etc/hosts"})
assert.NilError(t, err)
assert.Assert(t, is.Len(res.Stderr(), 0))
assert.Equal(t, 0, res.ExitCode)
inspect, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{})
assert.NilError(t, err)
assert.Check(t, is.Contains(res.Stdout(), inspect.IPAM.Config[0].Gateway))
c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
d.Stop(t)
// Verify the IP in /etc/hosts is same as host-gateway-ip
d.StartWithBusybox(t, "--host-gateway-ip=6.7.8.9")
cID = container.Run(ctx, t, c,
container.WithExtraHost("host.docker.internal:host-gateway"),
)
res, err = container.Exec(ctx, c, cID, []string{"cat", "/etc/hosts"})
assert.NilError(t, err)
assert.Assert(t, is.Len(res.Stderr(), 0))
assert.Equal(t, 0, res.ExitCode)
assert.Check(t, is.Contains(res.Stdout(), "6.7.8.9"))
c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
d.Stop(t)
}

View file

@ -180,3 +180,11 @@ func WithCgroupnsMode(mode string) func(*TestContainerConfig) {
c.HostConfig.CgroupnsMode = containertypes.CgroupnsMode(mode)
}
}
// WithExtraHost sets the user defined IP:Host mappings in the container's
// /etc/hosts file
func WithExtraHost(extraHost string) func(*TestContainerConfig) {
return func(c *TestContainerConfig) {
c.HostConfig.ExtraHosts = append(c.HostConfig.ExtraHosts, extraHost)
}
}

View file

@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"github.com/docker/docker/daemon/network"
"github.com/docker/docker/pkg/homedir"
)
@ -169,8 +170,11 @@ func ValidateExtraHost(val string) (string, error) {
if len(arr) != 2 || len(arr[0]) == 0 {
return "", fmt.Errorf("bad format for add-host: %q", val)
}
// Skip IPaddr validation for special "host-gateway" string
if arr[1] != network.HostGatewayName {
if _, err := ValidateIPAddress(arr[1]); err != nil {
return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1])
}
}
return val, nil
}