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