Docker Hosts File Sync
A PHP CLI tool to automatically sync your hosts file with running Docker containers.
Docker Hosts File Sync
Automatically sync your /etc/hosts file with running Docker containers. Each container gets hostnames for every network it's connected to.
Inspired by docker-hostmanager
Features
- Listens to Docker events in real-time (start, stop, restart)
- Generates hostnames based on container name and network
- Supports reverse proxy setups (nginx-proxy, Traefik, etc.)
- Reads hostnames from
DOMAIN_NAMEandVIRTUAL_HOSTenvironment variables - Works with Docker and Podman
Quick Start
Using Docker (Recommended)
docker run -d \
--name docker-hostfile-sync \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/hosts:/app/hosts \
ghcr.io/webproject-xyz/docker-hosts-file-sync:latestUsing Docker Compose
services:
docker-hostfile-sync:
image: ghcr.io/webproject-xyz/docker-hosts-file-sync:latest
container_name: docker-hostfile-sync
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/hosts:/app/hostsdocker compose up -dConfiguration
Command Line Options
| Option | Short | Description | Default |
|---|---|---|---|
--hosts_file |
-f |
Path to hosts file | ./tmp-hosts |
--tld |
-t |
TLD suffix for hostnames | .docker |
--reverse-proxy-host-ip |
-r |
IP address of your reverse proxy | - |
Environment Variables
You can also configure via environment variables:
| Variable | Description |
|---|---|
HOSTS_FILE |
Path to hosts file |
TLD |
TLD suffix for hostnames |
Examples
Example 1: Basic Setup
A simple web application with a database:
# docker-compose.yml
services:
docker-hostfile-sync:
image: ghcr.io/webproject-xyz/docker-hosts-file-sync:latest
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/hosts:/app/hosts
webapp:
image: nginx:alpine
container_name: webapp
database:
image: mysql:8
container_name: databaseGenerated hosts entries:
## docker-hostsfile-sync
172.20.0.2 webapp.docker webapp.myproject_default
172.20.0.3 database.docker database.myproject_default
## docker-hostsfile-sync-endNow you can access your services:
http://webapp.docker→ nginx containermysql -h database.docker→ MySQL container
Example 2: Multiple Networks
When containers are connected to multiple networks, each network gets its own hostname:
# docker-compose.yml
services:
docker-hostfile-sync:
image: ghcr.io/webproject-xyz/docker-hosts-file-sync:latest
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/hosts:/app/hosts
webapp:
image: nginx:alpine
container_name: webapp
networks:
- frontend
- backend
api:
image: node:alpine
container_name: api
networks:
- backend
database:
image: postgres:16
container_name: database
networks:
- backend
networks:
frontend:
backend:Generated hosts entries:
## docker-hostsfile-sync
172.21.0.2 webapp.docker webapp.frontend
172.22.0.2 webapp.backend
172.22.0.3 api.docker api.backend
172.22.0.4 database.docker database.backend
## docker-hostsfile-sync-endThis allows:
- Frontend services reach
webappviawebapp.frontend - Backend services communicate via
*.backendhostnames - Your host machine can reach any container directly
Example 3: With Reverse Proxy (nginx-proxy)
For production-like setups with a reverse proxy, use the --reverse-proxy-host-ip option. This routes URL-like hostnames (containing dots) to your proxy:
# docker-compose.yml
services:
docker-hostfile-sync:
image: ghcr.io/webproject-xyz/docker-hosts-file-sync:latest
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/hosts:/app/hosts
command: --reverse-proxy-host-ip=172.16.238.100
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
proxy:
ipv4_address: 172.16.238.100
webapp:
image: nginx:alpine
container_name: webapp
environment:
- VIRTUAL_HOST=webapp.local,www.webapp.local
networks:
- proxy
- default
api:
image: node:alpine
container_name: api
environment:
- DOMAIN_NAME=api.local
networks:
proxy:
aliases:
- api.dev.local
default:
networks:
proxy:
ipam:
config:
- subnet: 172.16.238.0/24Generated hosts entries:
## docker-hostsfile-sync
# nginx-proxy container
172.16.238.100 nginx-proxy.docker nginx-proxy.proxy
# webapp container - direct access via container IP
172.20.0.2 webapp.docker webapp.myproject_default
172.16.238.2 webapp.proxy
# webapp container - reverse proxy routes (from VIRTUAL_HOST env var)
172.16.238.100 webapp.local www.webapp.local
# api container - direct access
172.20.0.3 api.docker api.myproject_default
172.16.238.3 api.proxy
# api container - reverse proxy routes (from DOMAIN_NAME env var and network alias)
172.16.238.100 api.dev.local api.local
## docker-hostsfile-sync-endNow you can:
- Access
http://webapp.local→ routed through nginx-proxy to webapp - Access
http://api.local→ routed through nginx-proxy to api - Access
http://webapp.proxy→ direct to webapp container (bypassing proxy) - Debug with
http://api.docker→ direct container access
Example 4: Network Aliases
Network aliases let you give containers additional hostnames. Aliases containing a dot (.) are treated as URLs and routed to the reverse proxy:
services:
docker-hostfile-sync:
image: ghcr.io/webproject-xyz/docker-hosts-file-sync:latest
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/hosts:/app/hosts
command: --reverse-proxy-host-ip=172.16.238.100
webapp:
image: nginx:alpine
container_name: webapp
networks:
default:
aliases:
- frontend # Simple alias → webapp IP
- app.example.com # URL-like alias → reverse proxy IPGenerated hosts entries:
## docker-hostsfile-sync
172.20.0.2 webapp.docker frontend.default webapp.default
172.16.238.100 app.example.com
## docker-hostsfile-sync-endHow It Works
The tool manages a section in your hosts file between these markers:
## docker-hostsfile-sync
...entries managed automatically...
## docker-hostsfile-sync-endEverything outside these markers is left untouched.
Hostname Generation Rules
| Source | Example | Generated Hostname | Target IP |
|---|---|---|---|
| Container name | webapp |
webapp.networkname |
Container IP |
| Simple network alias | frontend |
frontend.networkname |
Container IP |
| URL-like network alias | app.example.com |
app.example.com |
Reverse proxy IP |
DOMAIN_NAME env var |
api.local |
api.local |
Reverse proxy IP |
VIRTUAL_HOST env var |
www.app.local |
www.app.local |
Reverse proxy IP |
URL-like aliases (containing a .) are assumed to be real domain names that should route through your reverse proxy. Simple aliases (no .) are combined with the network name.
Running Locally (Development)
# Install dependencies
composer install
# Run (outputs to ./tmp-hosts for testing)
php bin/docker-api synchronize-hosts -v
# Run with reverse proxy support
php bin/docker-api synchronize-hosts -v --reverse-proxy-host-ip=172.16.238.100
# Run targeting /etc/hosts (requires sudo)
sudo php bin/docker-api synchronize-hosts --hosts_file=/etc/hosts -v
# View logs
docker compose logs -f docker-hostfile-syncTroubleshooting
Hosts file not updating
Check the container has write access to the hosts file:
docker exec docker-hostfile-sync ls -la /app/hostsCheck logs for errors:
docker logs docker-hostfile-sync
Container not appearing in hosts file
Containers must be "exposed" (have at least one network with an IP address). Check your container:
docker inspect <container_name> --format '{{json .NetworkSettings.Networks}}'License
MIT