DNS and /etc/resolv.conf
bootc does not configure networking or select a DNS resolver. The operating
system in the container image must provide a coherent networking and DNS
policy, just as it must provide a kernel and an init system. Usually that
policy is owned by the distribution or base image.
The recommended approach is to configure DNS through the network management
and resolver services selected by the base image. Do not treat
/etc/resolv.conf as a file that should be copied from the container build
environment into the booted system.
Build-time and boot-time resolver configuration
When an image is built, the container runtime normally provides temporary
/etc/hostname, /etc/hosts, and /etc/resolv.conf files so that RUN
instructions have working networking. These files describe the build
environment. They are not the DNS configuration of the machine that will boot
the image.
When the image is installed and booted, there is no outer Podman or other container runtime to recreate these files. The network stack included in the image is responsible for generating the booted host's resolver configuration. See Container runtime vs bootc runtime for more about this distinction.
In particular:
- Do not copy the build host's
/etc/resolv.confinto an image. - Do not rely on the
/etc/resolv.confvisible in a networkedRUNinstruction. It may be a bind mount owned by Podman or Buildah. - Do not use an empty regular
/etc/resolv.confas a placeholder.bootcremoves it when importing the image (see below). - Do not add files below
/runto an image./runis runtime state and is recreated on every boot.
The one thing bootc does with these files: when importing an image (with the
ostree backend today), it removes /etc/resolv.conf and /etc/hostname if
they are zero-length regular files, because that is what a container runtime
leaves behind after bind-mounting its own copies during the build (see
buildah#4242,
bootc #1096 and
#1167). Apart from that,
bootc never reads or writes /etc/resolv.conf.
If a Containerfile step must intentionally replace /etc/resolv.conf, run the
step with networking disabled, for example with RUN --network=none. This
avoids modifying a container-runtime bind mount. It should only be necessary
when deliberately changing the resolver policy inherited from the base image.
Follow the base image's resolver policy
A derived image should normally retain its base image's DNS implementation.
Configure DNS servers, search domains, and per-interface behavior through that
implementation rather than replacing /etc/resolv.conf.
Common policies include:
- NetworkManager supplies per-link DNS configuration to
systemd-resolved, and/etc/resolv.confpoints to the local resolver stub. - NetworkManager writes a regular
/etc/resolv.confdirectly. - Another network manager or resolver owns the file under a distribution-specific policy.
NetworkManager and systemd-resolved are not alternatives with the same role.
NetworkManager configures network interfaces and may use systemd-resolved as
its DNS backend. The base image must ensure that its selected services, the
type and target of /etc/resolv.conf, and its service enablement agree. For
anything beyond that, follow your distribution's networking documentation and
the references in Further reading.
Environment-specific DNS configuration should generally be supplied when a
machine is provisioned. If DNS configuration is intentionally lifecycle-bound
to an image, include NetworkManager connection profiles or resolver drop-ins
in the image rather than including a generated /etc/resolv.conf. This keeps
the configuration declarative and makes its owner clear.
Base images using systemd-resolved
A base image using systemd-resolved should ensure that:
systemd-resolvedis installed and enabled.- NetworkManager or the selected network manager is configured to supply DNS information to it.
/etc/resolv.confis a symlink to a resolver file generated below/run/systemd/resolve, normally../run/systemd/resolve/stub-resolv.conf.
The upstream systemd-resolved package supplies a
systemd-tmpfiles
rule that creates the symlink at boot, so it does not need to exist in the
image:
L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf
It does not contain DNS server
addresses; systemd-resolved creates the target under /run from runtime
network configuration. Base image authors should normally use the rule
provided by the systemd-resolved package. A custom distribution integration
can ship an equivalent vendor rule in /usr/lib/tmpfiles.d.
Do not disable systemd-resolved while retaining this rule and symlink. That
leaves /etc/resolv.conf pointing to a runtime file that no enabled service
creates.
Fedora CoreOS example
Fedora CoreOS uses NetworkManager with systemd-resolved. It retains the
resolver stub symlink and configures DNS through NetworkManager connection
profiles. For example, its Butane configuration examples write NetworkManager
keyfiles under /etc/NetworkManager/system-connections/ and set the dns and
dns-search properties there.
See the Fedora CoreOS documentation for
host network configuration
and Fedora's description of its
systemd-resolved integration.
Fedora CoreOS also has an integration
test for its resolver policy.
This is an example of a complete base-image policy, not a requirement that all
bootc images use systemd-resolved.
Base images using a regular /etc/resolv.conf
A base image may instead have NetworkManager or another service write a
regular /etc/resolv.conf at runtime, on the booted host; nothing in the
container build produces that file. In that case it should ensure that:
systemd-resolvedis not enabled.- No tmpfiles rule recreates the
systemd-resolvedsymlink. /etc/resolv.confis absent or is a regular file that the selected service is configured to manage.
For Fedora-derived images, removing the systemd-resolved package is generally
clearer than only disabling its service: the package also owns the tmpfiles
rule that creates the symlink. Do the removal in a RUN --network=none step:
with networking enabled, /etc/resolv.conf is the container runtime's bind
mount and the package's uninstall scriptlet fails when it tries to handle it
(package removal needs no network). The inherited stub symlink is left behind
by the removal; remove it in the same step:
RUN --network=none dnf -y remove systemd-resolved && rm -f /etc/resolv.conf
If the package must remain installed, mask its tmpfiles rule with a symlink to
/dev/null at /etc/tmpfiles.d/systemd-resolve.conf and disable the service.
Any Containerfile operation that removes the inherited resolver symlink should
use RUN --network=none, because a networked build step sees a bind mount at
/etc/resolv.conf instead of the image's file.
/etc/resolv.conf is a symlink, managed by tmpfiles.d
Content that the image provides for /etc/resolv.conf should reach it
through a symlink created by a systemd-tmpfiles rule, not as a regular file
in the image: /etc is three-way merged across upgrades, and once a regular
file there has been modified locally a later image default no longer takes
effect (see Filesystem: /etc). The target depends on
the policy:
- a file under
/runwhen the resolver is dynamic -- this is what thesystemd-resolvedrule above does; - a file under
/usrwhen the configuration is truly static (below).
A regular file that a service such as NetworkManager generates at runtime is a different matter: the service owns it and rewrites it on every boot, so it does not carry image content and the merge behavior does not apply to it.
Static resolver configuration
Static DNS is configured through the network stack, like any other DNS setting, and that is the preferred mechanism even when the values never change:
- NetworkManager: set
ipv4.dns/ipv6.dnson the connection profile (withipv4.ignore-auto-dns yesif DHCP must not add servers), typically together with a static address. systemd-resolved: drop-ins in/etc/systemd/resolved.conf.d/.
Baking DNS server addresses into the image as a resolv.conf file is
discouraged: they are machine or environment configuration, and the file
bypasses whatever the network stack would otherwise manage. If an image must
ship one anyway, put the content under /usr, for example
/usr/lib/resolv.conf, and point the symlink at it with a rule mirroring the
systemd-resolved one:
L /etc/resolv.conf - - - - ../usr/lib/resolv.conf
Then mask the vendor systemd-resolved rule for the same path (a symlink to
/dev/null at /etc/tmpfiles.d/systemd-resolve.conf; two rules for one path
are an error in tmpfiles.d), configure the network stack not to manage the
file (dns=none in the [main] section of NetworkManager.conf; do not
enable systemd-resolved), and use RUN --network=none for the build step
that removes an inherited symlink.
Further reading
Behavior such as ndots, timeouts, retries, caching, and split DNS is defined
by the resolver the base image selected, not by bootc. See the
systemd-resolved documentation
and NetworkManager's documentation for
NetworkManager.conf
and
connection settings.
Application containers
Application containers and bootc hosts have different runtime behavior. By
default, Podman creates /etc/hosts, /etc/hostname, and /etc/resolv.conf
for each application container. Runtime options such as podman run --dns
control that generated file, and --dns=none requests use of the image's file.
The DNS options to podman build apply to networked RUN instructions; they
do not define the DNS policy of a host booted from the completed image. See the
Podman documentation for
podman run and
podman build.
The Linux Foundation® (TLF) has registered trademarks and uses trademarks. For a list of TLF trademarks, see Trademark Usage.