diff --git a/docs/containers.conf.5.md b/docs/containers.conf.5.md index 39aea67c0..207a11e4c 100644 --- a/docs/containers.conf.5.md +++ b/docs/containers.conf.5.md @@ -150,6 +150,16 @@ environment variables to the container. Pass all host environment variables into the container. +**host_containers_internal_ip**="" + +Set the ip for the host.containers.internal entry in the containers /etc/hosts +file. This can be set to "none" to disable adding this entry. By default it +will automatically choose the host ip. + +NOTE: When using podman machine this entry will never be added to the containers +hosts file instead the gvproxy dns resolver will resolve this hostname. Therefore +it is not possible to disable the entry in this case. + **http_proxy**=true Default proxy environment variables will be passed into the container. diff --git a/libnetwork/etchosts/ip.go b/libnetwork/etchosts/ip.go new file mode 100644 index 000000000..4a7dcc49d --- /dev/null +++ b/libnetwork/etchosts/ip.go @@ -0,0 +1,66 @@ +package etchosts + +import ( + "net" + + "github.com/containers/common/libnetwork/types" + "github.com/containers/common/libnetwork/util" + "github.com/containers/common/pkg/config" +) + +// GetHostContainersInternalIP return the host.containers.internal ip +// if netStatus is not nil then networkInterface also must be non nil otherwise this function panics +func GetHostContainersInternalIP(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork) string { + switch conf.Containers.HostContainersInternalIP { + case "": + // if empty we will automatically choose one below + case "none": + return "" + default: + return conf.Containers.HostContainersInternalIP + } + ip := "" + for net, status := range netStatus { + network, err := networkInterface.NetworkInspect(net) + // only add the host entry for bridge networks + // ip/macvlan gateway is normally not on the host + if err != nil || network.Driver != types.BridgeNetworkDriver { + continue + } + for _, netInt := range status.Interfaces { + for _, netAddress := range netInt.Subnets { + if netAddress.Gateway != nil { + if util.IsIPv4(netAddress.Gateway) { + return netAddress.Gateway.String() + } + // ipv6 address but keep looking since we prefer to use ipv4 + ip = netAddress.Gateway.String() + } + } + } + } + if ip != "" { + return ip + } + return getLocalIP() +} + +// getLocalIP returns the non loopback local IP of the host +func getLocalIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + return "" + } + ip := "" + for _, address := range addrs { + // check the address type and if it is not a loopback the display it + if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { + if util.IsIPv4(ipnet.IP) { + return ipnet.IP.String() + } + // if ipv6 we keep looking for an ipv4 address + ip = ipnet.IP.String() + } + } + return ip +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 5c3ec8ffd..e18dfdd8c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -141,6 +141,9 @@ type ContainersConfig struct { // EnvHost Pass all host environment variables into the container. EnvHost bool `toml:"env_host,omitempty"` + // HostContainersInternalIP is used to set a specific host.containers.internal ip. + HostContainersInternalIP string `toml:"host_containers_internal_ip,omitempty"` + // HTTPProxy is the proxy environment variable list to apply to container process HTTPProxy bool `toml:"http_proxy,omitempty"` diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 0c1004f2b..85bc5a927 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -364,6 +364,7 @@ image_copy_tmp_dir="storage"` gomega.Expect(config.Containers.ApparmorProfile).To(gomega.Equal("container-default")) gomega.Expect(config.Containers.PidsLimit).To(gomega.BeEquivalentTo(2048)) gomega.Expect(config.Containers.BaseHostsFile).To(gomega.BeEquivalentTo("/etc/hosts2")) + gomega.Expect(config.Containers.HostContainersInternalIP).To(gomega.BeEquivalentTo("1.2.3.4")) }) It("contents of passed-in file should override others", func() { diff --git a/pkg/config/containers.conf b/pkg/config/containers.conf index aeddca787..978d2bf2a 100644 --- a/pkg/config/containers.conf +++ b/pkg/config/containers.conf @@ -121,6 +121,16 @@ default_sysctls = [ # #env_host = false +#Set the ip for the host.containers.internal entry in the containers /etc/hosts +#file. This can be set to "none" to disable adding this entry. By default it +#will automatically choose the host ip. +# +#NOTE: When using podman machine this entry will never be added to the containers +#hosts file instead the gvproxy dns resolver will resolve this hostname. Therefore +#it is not possible to disable the entry in this case. +# +#host_containers_internal_ip = "" + # Default proxy environment variables passed into the container. # The environment variables passed in include: # http_proxy, https_proxy, ftp_proxy, no_proxy, and the upper case versions of diff --git a/pkg/config/testdata/containers_default.conf b/pkg/config/testdata/containers_default.conf index e7eb9b6be..ca4948c2f 100644 --- a/pkg/config/testdata/containers_default.conf +++ b/pkg/config/testdata/containers_default.conf @@ -63,6 +63,8 @@ env = [ # Run an init inside the container that forwards signals and reaps processes. init = false +host_containers_internal_ip = "1.2.3.4" + # proxy environment variables are passed into the container http_proxy = false