|
@@ -391,13 +391,65 @@ func serviceDiscoveryOnDefaultNetwork() bool {
|
|
|
func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error {
|
|
|
var err error
|
|
|
|
|
|
- if container.HostConfig.NetworkMode.IsHost() {
|
|
|
- // Point to the host files, so that will be copied into the container running in host mode
|
|
|
- *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
|
|
|
- }
|
|
|
+ // Set the correct paths for /etc/hosts and /etc/resolv.conf, based on the
|
|
|
+ // networking-mode of the container. Note that containers with "container"
|
|
|
+ // networking are already handled in "initializeNetworking()" before we reach
|
|
|
+ // this function, so do not have to be accounted for here.
|
|
|
+ switch {
|
|
|
+ case container.HostConfig.NetworkMode.IsHost():
|
|
|
+ // In host-mode networking, the container does not have its own networking
|
|
|
+ // namespace, so both `/etc/hosts` and `/etc/resolv.conf` should be the same
|
|
|
+ // as on the host itself. The container gets a copy of these files, but they
|
|
|
+ // may be symlinked, so resolve the original path first.
|
|
|
+ etcHosts, err := filepath.EvalSymlinks("/etc/hosts")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ resolvConf, err := filepath.EvalSymlinks("/etc/resolv.conf")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- // Copy the host's resolv.conf for the container (/etc/resolv.conf or /run/systemd/resolve/resolv.conf)
|
|
|
- *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath(daemon.configStore.GetResolvConf()))
|
|
|
+ *sboxOptions = append(
|
|
|
+ *sboxOptions,
|
|
|
+ libnetwork.OptionOriginHostsPath(etcHosts),
|
|
|
+ libnetwork.OptionOriginResolvConfPath(resolvConf),
|
|
|
+ )
|
|
|
+ case container.HostConfig.NetworkMode.IsUserDefined():
|
|
|
+ // The container uses a user-defined network. We use the embedded DNS
|
|
|
+ // server for container name resolution and to act as a DNS forwarder
|
|
|
+ // for external DNS resolution.
|
|
|
+ // We parse the DNS server(s) that are defined in /etc/resolv.conf on
|
|
|
+ // the host, which may be a local DNS server (for example, if DNSMasq or
|
|
|
+ // systemd-resolvd are in use). The embedded DNS server forwards DNS
|
|
|
+ // resolution to the DNS server configured on the host, which in itself
|
|
|
+ // may act as a forwarder for external DNS servers.
|
|
|
+ // If systemd-resolvd is used, the "upstream" DNS servers can be found in
|
|
|
+ // /run/systemd/resolve/resolv.conf. We do not query those DNS servers
|
|
|
+ // directly, as they can be dynamically reconfigured.
|
|
|
+ resolvConf, err := filepath.EvalSymlinks("/etc/resolv.conf")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath(resolvConf))
|
|
|
+ default:
|
|
|
+ // For other situations, such as the default bridge network, container
|
|
|
+ // discovery / name resolution is handled through /etc/hosts, and no
|
|
|
+ // embedded DNS server is available. Without the embedded DNS, we
|
|
|
+ // cannot use local DNS servers on the host (for example, if DNSMasq or
|
|
|
+ // systemd-resolvd is used). If systemd-resolvd is used, we try to
|
|
|
+ // determine the external DNS servers that are used on the host.
|
|
|
+ // This situation is not ideal, because DNS servers configured in the
|
|
|
+ // container are not updated after the container is created, but the
|
|
|
+ // DNS servers on the host can be dynamically updated.
|
|
|
+ //
|
|
|
+ // Copy the host's resolv.conf for the container (/run/systemd/resolve/resolv.conf or /etc/resolv.conf)
|
|
|
+ resolvConf, err := filepath.EvalSymlinks(daemon.configStore.GetResolvConf())
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath(resolvConf))
|
|
|
+ }
|
|
|
|
|
|
container.HostsPath, err = container.GetRootResourcePath("hosts")
|
|
|
if err != nil {
|