Docker Compose: Equivalent of --add-host=host.docker.internal:host-gateway
Problem Statement
When working with Docker containers, you may need containers to access services running on your host machine. Docker provides a convenient solution with the --add-host=host.docker.internal:host-gateway
flag when using docker run
. This creates a host entry that resolves host.docker.internal
to your host machine's IP address, allowing containers to connect back to services running on the Docker host.
However, when using Docker Compose, the equivalent approach isn't immediately obvious. Many users struggle to achieve the same connectivity between containers and the host within a Compose setup.
Solution
The Docker Compose equivalent uses the extra_hosts
parameter with the same host.docker.internal:host-gateway
syntax:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
extra_hosts:
- "host.docker.internal:host-gateway"
Verification
To verify the configuration works:
docker-compose up -d
docker-compose exec postgres bash
Then inside the container:
apt update && apt -y install netcat
nc -vz host.docker.internal 80
You should see output similar to:
Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
Network Configuration Considerations
When using Docker Compose, the container typically joins a network created specifically for that compose project, which may have a different gateway IP (e.g., 172.22.0.1
) instead of the default docker0
interface IP (172.17.0.1
).
This can cause issues if you have firewall rules or service configurations that only allow connections from the default gateway IP.
Advanced Network Configuration
For more control over networking, you can define a custom network with a specific gateway:
version: '3.9'
networks:
network1:
name: my-network
attachable: true
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
ip_range: 172.18.5.0/24
gateway: 172.18.0.1
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
networks:
- network1
Verify the gateway with:
docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
Alternative Approach: Joining the Default Bridge Network
You can also configure your service to join the default bridge network:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
network_mode: bridge
extra_hosts:
- "host.docker.internal:host-gateway"
Security Consideration
Joining the default bridge network allows your container to communicate with all other containers on that network. If you need isolation between containers, use custom networks instead.
Troubleshooting
If you encounter network errors like:
Creating tmp_postgres_1 ... error
ERROR: for tmp_postgres_1 Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network [hash] does not exist
Try restarting the Docker service:
sudo service docker restart
Summary
The extra_hosts
parameter in Docker Compose provides the equivalent functionality to --add-host=host.docker.internal:host-gateway
. For most use cases, this simple approach works well. For advanced networking requirements with specific IP addressing needs, consider defining custom networks in your Compose file.
Remember to adjust firewall rules and service configurations on your host machine to accept connections from the appropriate gateway IP addresses used by your Docker networks.