How to Persist /etc/hosts Modifications in Docker Containers: Solving the RUN Command Issue


2 views

Many Docker users encounter this frustrating scenario: you add host entries in your Dockerfile using RUN echo "ip hostname" >> /etc/hosts, the build succeeds, but the modifications vanish when you run the container. Let's examine why this happens and explore robust solutions.

The fundamental issue stems from how Docker handles the /etc/hosts file. During container startup, Docker dynamically generates this file, overwriting any manual changes made during the build phase. This behavior persists across all recent Docker versions.

1. Using --add-host in docker run

The most reliable approach is to specify host entries when running the container:

docker run --add-host www.hahaha.com:192.92.13.243 your-image

2. Custom Entrypoint Script

For more complex scenarios, create an entrypoint script:

#!/bin/bash
echo "192.92.13.243 www.hahaha.com" >> /etc/hosts
exec "$@"

In your Dockerfile:

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

3. Docker Compose Solution

For compose files, use the extra_hosts directive:

services:
  your-service:
    extra_hosts:
      - "www.hahaha.com:192.92.13.243"

If you absolutely need the hosts during build (not runtime), you can:

RUN echo "192.92.13.243 www.hahaha.com" >> /etc/hosts && \
    ./your-build-script-that-needs-the-host

Remember these changes won't persist to the runtime container.

For development environments, consider network aliases in Docker networks:

docker network create mynet
docker run --network mynet --network-alias www.hahaha.com your-image
  • Docker intentionally overwrites /etc/hosts at runtime
  • Use runtime solutions (--add-host, entrypoint scripts) for persistent changes
  • Build-time modifications are only effective during the build process
  • Consider network aliases for service discovery

Many developers encounter this frustrating scenario: you add host entries in your Dockerfile using RUN echo "127.0.0.1 example.com" >> /etc/hosts, the build succeeds, but the changes mysteriously disappear when you run the container. This happens because Docker dynamically manages the /etc/hosts file at container startup, overwriting any manual modifications.

The root cause lies in Docker's architecture. The daemon automatically generates the hosts file when a container launches, merging:

  • Default localhost entries
  • Container hostname
  • Linked container hostnames
  • User-defined extra hosts

This regeneration overwrites any changes made during image build, making RUN commands ineffective for permanent host modifications.

1. Using docker run --add-host

The most reliable method is specifying hosts at runtime:

docker run --add-host example.com:127.0.0.1 your-image

2. Docker Compose Approach

For compose files, use the extra_hosts directive:

services:
  app:
    image: your-image
    extra_hosts:
      - "example.com:127.0.0.1"

3. Entrypoint Script Workaround

Create an entrypoint script that modifies hosts on container start:

#!/bin/sh
echo "127.0.0.1 example.com" >> /etc/hosts
exec "$@"

Then in your Dockerfile:

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["your-main-command"]

Remember that:

  • Hosts added via --add-host persist through container restarts
  • The entrypoint method works but may cause issues in orchestrated environments
  • For Kubernetes, use hostAliases in pod specifications instead

Always verify your host entries with:

docker exec -it your-container cat /etc/hosts

Or interactively:

docker run -it --add-host test.com:127.0.0.1 alpine cat /etc/hosts