summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/shared/create.go5
-rw-r--r--completions/bash/podman1
-rw-r--r--docs/podman-create.1.md10
-rw-r--r--docs/podman-run.1.md10
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/container_internal_linux.go85
-rw-r--r--libpod/options.go52
-rw-r--r--pkg/spec/createconfig.go12
-rw-r--r--test/e2e/run_test.go10
10 files changed, 157 insertions, 40 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 771738302..167b3e845 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -389,6 +389,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"Connect a container to a network",
)
createFlags.Bool(
+ "no-hosts", false,
+ "Do not create /etc/hosts within the container, instead use the version from the image",
+ )
+ createFlags.Bool(
"oom-kill-disable", false,
"Disable OOM Killer",
)
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 5ce0b8865..5f7263cb6 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -357,6 +357,10 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
}
+ if c.Bool("no-hosts") && c.Flag("add-host").Changed {
+ return nil, errors.Errorf("--no-hosts and --add-host cannot be set together")
+ }
+
// EXPOSED PORTS
var portBindings map[nat.Port][]nat.PortBinding
if data != nil {
@@ -646,6 +650,7 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
GroupAdd: c.StringSlice("group-add"),
Hostname: c.String("hostname"),
HostAdd: c.StringSlice("add-host"),
+ NoHosts: c.Bool("no-hosts"),
IDMappings: idmappings,
Image: imageName,
ImageID: imageID,
diff --git a/completions/bash/podman b/completions/bash/podman
index dfa673481..798d49ceb 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1727,6 +1727,7 @@ _podman_container_run() {
--memory-reservation
--name
--network
+ --no-hosts
--oom-score-adj
--pid
--pids-limit
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 2e176db76..f61deebd2 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -204,6 +204,9 @@ configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
is the case the **--dns** flags is necessary for every run.
+The special value **none** can be specified to disable creation of **/etc/resolv.conf** in the container by Podman.
+The **/etc/resolv.conf** file in the image will be used without changes.
+
**--dns-option**=[]
Set custom DNS options
@@ -457,6 +460,13 @@ Set the Network mode for the container
Not implemented
+**--no-hosts**=*true*|*false*
+
+Do not create /etc/hosts for the container.
+By default, Podman will manage /etc/hosts, adding the container's own IP address and any hosts from **--add-host**.
+**--no-hosts** disables this, and the image's **/etc/host** will be preserved unmodified.
+This option conflicts with **--add-host**.
+
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index b8b3d51f0..5a311980f 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -210,6 +210,9 @@ configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
is the case the **--dns** flags is necessary for every run.
+The special value **none** can be specified to disable creation of **/etc/resolv.conf** in the container by Podman.
+The **/etc/resolv.conf** file in the image will be used without changes.
+
**--dns-option**=[]
Set custom DNS options
@@ -441,6 +444,13 @@ Set the Network mode for the container:
Not implemented
+**--no-hosts**=*true*|*false*
+
+Do not create /etc/hosts for the container.
+By default, Podman will manage /etc/hosts, adding the container's own IP address and any hosts from **--add-host**.
+**--no-hosts** disables this, and the image's **/etc/host** will be preserved unmodified.
+This option conflicts with **--add-host**.
+
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.
diff --git a/libpod/container.go b/libpod/container.go
index ec4e31026..806e75c63 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -293,6 +293,10 @@ type ContainerConfig struct {
// namespace
// These are not used unless CreateNetNS is true
PortMappings []ocicni.PortMapping `json:"portMappings,omitempty"`
+ // UseImageResolvConf indicates that resolv.conf should not be
+ // bind-mounted inside the container.
+ // Conflicts with DNSServer, DNSSearch, DNSOption.
+ UseImageResolvConf bool
// DNS servers to use in container resolv.conf
// Will override servers in host resolv if set
DNSServer []net.IP `json:"dnsServer,omitempty"`
@@ -302,6 +306,10 @@ type ContainerConfig struct {
// DNS options to be set in container resolv.conf
// With override options in host resolv if set
DNSOption []string `json:"dnsOption,omitempty"`
+ // UseImageHosts indicates that /etc/hosts should not be
+ // bind-mounted inside the container.
+ // Conflicts with HostAdd.
+ UseImageHosts bool
// Hosts to add in container
// Will be appended to host's host file
HostAdd []string `json:"hostsAdd,omitempty"`
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index c6c9ceb0c..02f8d6aa4 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -703,10 +703,11 @@ func (c *Container) makeBindMounts() error {
}
}
- if c.config.NetNsCtr != "" {
- // We share a net namespace
+ if c.config.NetNsCtr != "" && (!c.config.UseImageResolvConf || !c.config.UseImageHosts) {
+ // We share a net namespace.
// We want /etc/resolv.conf and /etc/hosts from the
- // other container
+ // other container. Unless we're not creating both of
+ // them.
depCtr, err := c.runtime.state.Container(c.config.NetNsCtr)
if err != nil {
return errors.Wrapf(err, "error fetching dependency %s of container %s", c.config.NetNsCtr, c.ID())
@@ -718,53 +719,65 @@ func (c *Container) makeBindMounts() error {
return errors.Wrapf(err, "error fetching bind mounts from dependency %s of container %s", depCtr.ID(), c.ID())
}
- // The other container may not have a resolv.conf or /etc/hosts
- // If it doesn't, don't copy them
- resolvPath, exists := bindMounts["/etc/resolv.conf"]
- if exists {
- c.state.BindMounts["/etc/resolv.conf"] = resolvPath
+ if !c.config.UseImageResolvConf {
+ // The other container may not have a resolv.conf or /etc/hosts
+ // If it doesn't, don't copy them
+ resolvPath, exists := bindMounts["/etc/resolv.conf"]
+ if exists {
+ c.state.BindMounts["/etc/resolv.conf"] = resolvPath
+ }
}
- // check if dependency container has an /etc/hosts file
- hostsPath, exists := bindMounts["/etc/hosts"]
- if !exists {
- return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
- }
+ if !c.config.UseImageHosts {
+ // check if dependency container has an /etc/hosts file
+ hostsPath, exists := bindMounts["/etc/hosts"]
+ if !exists {
+ return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
+ }
- depCtr.lock.Lock()
- // generate a hosts file for the dependency container,
- // based on either its old hosts file, or the default,
- // and add the relevant information from the new container (hosts and IP)
- hostsPath, err = depCtr.appendHosts(hostsPath, c)
+ depCtr.lock.Lock()
+ // generate a hosts file for the dependency container,
+ // based on either its old hosts file, or the default,
+ // and add the relevant information from the new container (hosts and IP)
+ hostsPath, err = depCtr.appendHosts(hostsPath, c)
- if err != nil {
+ if err != nil {
+ depCtr.lock.Unlock()
+ return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
+ }
depCtr.lock.Unlock()
- return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
- }
- depCtr.lock.Unlock()
- // finally, save it in the new container
- c.state.BindMounts["/etc/hosts"] = hostsPath
+ // finally, save it in the new container
+ c.state.BindMounts["/etc/hosts"] = hostsPath
+ }
} else {
- newResolv, err := c.generateResolvConf()
- if err != nil {
- return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
+ if !c.config.UseImageResolvConf {
+ newResolv, err := c.generateResolvConf()
+ if err != nil {
+ return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
+ }
+ c.state.BindMounts["/etc/resolv.conf"] = newResolv
}
- c.state.BindMounts["/etc/resolv.conf"] = newResolv
- newHosts, err := c.generateHosts("/etc/hosts")
- if err != nil {
- return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
+ if !c.config.UseImageHosts {
+ newHosts, err := c.generateHosts("/etc/hosts")
+ if err != nil {
+ return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
+ }
+ c.state.BindMounts["/etc/hosts"] = newHosts
}
- c.state.BindMounts["/etc/hosts"] = newHosts
}
- if err := label.Relabel(c.state.BindMounts["/etc/hosts"], c.config.MountLabel, true); err != nil {
- return err
+ if c.state.BindMounts["/etc/hosts"] != "" {
+ if err := label.Relabel(c.state.BindMounts["/etc/hosts"], c.config.MountLabel, true); err != nil {
+ return err
+ }
}
- if err := label.Relabel(c.state.BindMounts["/etc/resolv.conf"], c.config.MountLabel, true); err != nil {
- return err
+ if c.state.BindMounts["/etc/resolv.conf"] != "" {
+ if err := label.Relabel(c.state.BindMounts["/etc/resolv.conf"], c.config.MountLabel, true); err != nil {
+ return err
+ }
}
}
diff --git a/libpod/options.go b/libpod/options.go
index 1bf3ff9e6..3ca80e96c 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -997,6 +997,9 @@ func WithDNSSearch(searchDomains []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
+ if ctr.config.UseImageResolvConf {
+ return errors.Wrapf(ErrInvalidArg, "cannot add DNS search domains if container will not create /etc/resolv.conf")
+ }
ctr.config.DNSSearch = searchDomains
return nil
}
@@ -1008,6 +1011,9 @@ func WithDNS(dnsServers []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
+ if ctr.config.UseImageResolvConf {
+ return errors.Wrapf(ErrInvalidArg, "cannot add DNS servers if container will not create /etc/resolv.conf")
+ }
var dns []net.IP
for _, i := range dnsServers {
result := net.ParseIP(i)
@@ -1027,6 +1033,9 @@ func WithDNSOption(dnsOptions []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
+ if ctr.config.UseImageResolvConf {
+ return errors.Wrapf(ErrInvalidArg, "cannot add DNS options if container will not create /etc/resolv.conf")
+ }
ctr.config.DNSOption = dnsOptions
return nil
}
@@ -1038,6 +1047,11 @@ func WithHosts(hosts []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
+
+ if ctr.config.UseImageHosts {
+ return errors.Wrapf(ErrInvalidArg, "cannot add hosts if container will not create /etc/hosts")
+ }
+
ctr.config.HostAdd = hosts
return nil
}
@@ -1184,6 +1198,44 @@ func WithCtrNamespace(ns string) CtrCreateOption {
}
}
+// WithUseImageResolvConf tells the container not to bind-mount resolv.conf in.
+// This conflicts with other DNS-related options.
+func WithUseImageResolvConf() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return ErrCtrFinalized
+ }
+
+ if len(ctr.config.DNSServer) != 0 ||
+ len(ctr.config.DNSSearch) != 0 ||
+ len(ctr.config.DNSOption) != 0 {
+ return errors.Wrapf(ErrInvalidArg, "not creating resolv.conf conflicts with DNS options")
+ }
+
+ ctr.config.UseImageResolvConf = true
+
+ return nil
+ }
+}
+
+// WithUseImageHosts tells the container not to bind-mount /etc/hosts in.
+// This conflicts with WithHosts().
+func WithUseImageHosts() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return ErrCtrFinalized
+ }
+
+ if len(ctr.config.HostAdd) != 0 {
+ return errors.Wrapf(ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
+ }
+
+ ctr.config.UseImageHosts = true
+
+ return nil
+ }
+}
+
// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden
// and expected to be the first container in the pod.
func withIsInfra() CtrCreateOption {
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 118fbad72..79a318771 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -88,6 +88,7 @@ type CreateConfig struct {
ExposedPorts map[nat.Port]struct{}
GroupAdd []string // group-add
HealthCheck *manifest.Schema2HealthConfig
+ NoHosts bool
HostAdd []string //add-host
Hostname string //hostname
Image string
@@ -505,12 +506,19 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l
options = append(options, libpod.WithDNSSearch(c.DNSSearch))
}
if len(c.DNSServers) > 0 {
- options = append(options, libpod.WithDNS(c.DNSServers))
+ if len(c.DNSServers) == 1 && strings.ToLower(c.DNSServers[0]) == "none" {
+ options = append(options, libpod.WithUseImageResolvConf())
+ } else {
+ options = append(options, libpod.WithDNS(c.DNSServers))
+ }
}
if len(c.DNSOpt) > 0 {
options = append(options, libpod.WithDNSOption(c.DNSOpt))
}
- if len(c.HostAdd) > 0 {
+ if c.NoHosts {
+ options = append(options, libpod.WithUseImageHosts())
+ }
+ if len(c.HostAdd) > 0 && !c.NoHosts {
options = append(options, libpod.WithHosts(c.HostAdd))
}
logPath := getLoggingPath(c.LogDriverOpt)
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index b0dc66707..2daf2fe5b 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -749,13 +749,19 @@ USER mail`
It("podman run with bad healthcheck timeout", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-timeout", "0s", ALPINE, "top"})
- session.Wait()
+ session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).ToNot(Equal(0))
})
It("podman run with bad healthcheck start-period", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-start-period", "-1s", ALPINE, "top"})
- session.Wait()
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).ToNot(Equal(0))
+ })
+
+ It("podman run with --add-host and --no-hosts fails", func() {
+ session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).ToNot(Equal(0))
})
})