How to Use host.docker.internal in Docker Compose Configuration

How to Use host.docker.internal in Docker Compose Configuration






Containers require reliable communication with host services during development. Docker 20.10 introduced the host-gateway capability, enabling consistent cross-platform connectivity through host.docker.internal. This hostname resolves automatically on macOS and Windows, while Linux systems gained support through the extra_hosts directive in Docker Compose configurations.

Understanding host.docker.internal for Container Networking

The host.docker.internal hostname provides containers with a standardized method to reach services on the local machine. Prior to Docker 20.10, Linux development environments required manual IP configuration for container-to-host communication.

Docker now resolves this through the host-gateway value, which automatically identifies the bridge network gateway address. This eliminates hardcoded IP addresses and maintains portability across different development environments.

macOS
Native Support

Windows
Native Support

Linux
Requires host-gateway

Docker Compose Configuration with host.docker.internal

The extra_hosts directive in Docker Compose maps host.docker.internal to the gateway address. This configuration writes the appropriate entry to the container’s /etc/hosts file.

version: '3.9'

services:
  postgres:
    image: postgres:14.1-bullseye
    environment:
      POSTGRES_PASSWORD: yourpassword
    ports:
      - "5433:5432"
    extra_hosts:
      - "host.docker.internal:host-gateway"

Docker processes this configuration and locates the bridge network gateway, typically 172.17.0.1 on default installations. Applications inside the container resolve host.docker.internal to this address without additional network configuration.

Command Line Implementation for host.docker.internal

The add-host flag provides equivalent functionality when running containers directly through the Docker CLI. Similar to managing Linux containers on Chromebooks, this approach maintains isolation while enabling host access.

docker run 
  --rm 
  --name postgres 
  -p "5433:5432" 
  -e POSTGRES_PASSWORD=yourpassword 
  --add-host=host.docker.internal:host-gateway 
  -d postgres:14.1-bullseye

The configuration creates a temporary container that removes itself after stopping. Port mapping exposes the database on port 5433, while the add-host parameter establishes the hostname resolution.

When to Use host.docker.internal in Docker Projects

Host connectivity proves necessary when containers must reach services that cannot run in Docker. Database servers on the local machine represent the primary use case.

API endpoints bound to localhost also require this configuration. Projects that integrate multiple development tools benefit from maintaining network isolation without using network_mode:host, which reduces security.

When all services exist within Docker, standard container names provide sufficient networking. The host-gateway parameter becomes unnecessary for purely containerized architectures.

Testing host.docker.internal Container Access

Verification requires a service running on the host machine. A Python HTTP server provides a simple test endpoint.

python3 -m http.server 8000

Create a test configuration that attempts to connect from inside a container.

version: '3.9'
services:
  curl:
    image: curlimages/curl
    command: ["curl", "http://host.docker.internal:8000"]
    extra_hosts:
      - "host.docker.internal:host-gateway"

Running docker-compose up displays the HTML response from the local server. Exit code 0 confirms successful connectivity. Similar testing approaches work for cloud development environments using containerized workflows.

Docker Compose host.docker.internal Troubleshooting

Connection failures typically stem from three sources. Docker versions below 20.10 do not recognize the host-gateway value and return invalid IP address errors.

Issue Cause Resolution
Invalid IP address error Docker version below 20.10 Update Docker to 20.10 or later
Connection refused Service bound to 127.0.0.1 only Bind service to 0.0.0.0 interface
Timeout errors Firewall blocking container traffic Configure firewall for bridge network
DNS resolution failure Missing extra_hosts configuration Add host.docker.internal mapping

Services bound only to 127.0.0.1 cannot accept connections from containers. Binding to 0.0.0.0 allows the service to receive traffic from the Docker bridge network.

Firewall rules may block traffic between containers and the host. Configuring the firewall to permit connections from the Docker bridge network range resolves timeout errors.

Docker Compose extra_hosts Alternative Approaches

Network mode host provides an alternative that removes network isolation entirely. Containers share the host network stack, eliminating the need for port mapping or hostname resolution.

services:
  app:
    image: myapp
    network_mode: host

This configuration reduces security by exposing all container network activity to the host. The approach suits specific scenarios but sacrifices the isolation benefits of containerization.

Using host.docker.internal with extra_hosts maintains network boundaries while providing selective host access. This balance proves more appropriate for most development workflows, including those using developer tools on resource-constrained systems.

host.docker.internal Cross-Platform Compatibility

Developers working across macOS, Windows, and Linux environments benefit from standardized configuration. The same Docker Compose file functions identically on all platforms when using host-gateway.

Projects shared between team members maintain consistency regardless of operating system. Build processes and integration tests produce identical results across different development machines.

Container images remain portable without platform-specific modifications. This approach supports continuous integration pipelines that may run on various operating systems, similar to how Project Crostini enables Linux applications across different hardware configurations.

FAQs

How does host.docker.internal work in Docker Compose?

Docker Compose resolves host.docker.internal to the bridge network gateway IP address when extra_hosts is configured with host-gateway. This creates an /etc/hosts entry inside containers pointing to the host machine.

Why does host.docker.internal fail on Linux without configuration?

Linux does not provide automatic resolution for host.docker.internal. Docker 20.10 added host-gateway support to enable this functionality through explicit configuration in Docker Compose or command-line flags.

Can I use host.docker.internal with Docker networks other than bridge?

The host-gateway value works with custom bridge networks. User-defined networks require the same extra_hosts configuration. Host and none network modes do not support this feature as they lack gateway addresses.

What port should I use when connecting to host.docker.internal?

Use the actual port your service listens on at the host machine. For example, if PostgreSQL runs on port 5432 locally, connect to host.docker.internal:5432 from the container.

Does host.docker.internal work with Docker Swarm deployments?

Docker Swarm does not support host.docker.internal or the host-gateway value. Swarm mode requires different networking approaches such as overlay networks or explicit host IP addresses for cross-node communication.