Skip to content

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:

yaml
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:

bash
docker-compose up -d
docker-compose exec postgres bash

Then inside the container:

bash
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:

yaml
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:

bash
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:

yaml
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:

bash
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.