Skip to content

Docker Networking

X4Applegate edited this page Sep 10, 2026 · 1 revision

Docker Networking

This trips up everyone running Caddy in Docker. You add a proxy host, the certificate issues, you open the URL and get 502 Bad Gateway. Caddy's log says:

dial tcp: lookup status-server on 127.0.0.11:53: server misbehaving
status: 502

That is Docker's embedded DNS (127.0.0.11) telling Caddy it has no idea what status-server is. Not TLS, not a Caddy bug: a Docker network problem.

The rule

Docker's DNS resolves container names only on the same user-defined network. If Caddy is on proxy-net and the upstream is on status-net (or on the default bridge, which has no name resolution at all), Caddy cannot resolve it. Full stop.

The fix: one shared network

Create one network and attach every container Caddy needs to reach:

services:
  caddy:
    image: caddy:latest
    networks: [caddy-net]
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data

  caddyui:
    image: applegater/caddyui:latest
    networks: [caddy-net]
    environment:
      CADDY_ADMIN_URL: http://caddy:2019
    volumes:
      - caddyui_data:/data

  status-server:
    image: louislam/uptime-kuma:1
    networks: [caddy-net]
    volumes:
      - kuma_data:/app/data

networks:
  caddy-net:
    driver: bridge

volumes:
  caddy_data:
  caddyui_data:
  kuma_data:

In the proxy host, Forward host is simply the service name (status-server) and Forward port the port the app listens on inside its container (3001 for Uptime Kuma), not a published host port.

Already-running containers

Make the Caddy network external and import it in the other stack:

In Caddy's compose file:

networks:
  caddy-net:
    name: caddy-net
    driver: bridge

In the other app's compose file:

services:
  status-server:
    # … existing config …
    networks:
      - default
      - caddy-net

networks:
  caddy-net:
    external: true

The upstream keeps its private network for its database and also joins caddy-net.

No recompose? Connect a live container

docker network connect caddy-net status-server

Immediate, no restart. Write it into the compose file too, or it will not survive the next docker compose up.

When the upstream is not in Docker

  • Same host (a systemd service, a bare-metal daemon): use host.docker.internal on Docker Desktop, or 172.17.0.1 / a host-gateway extra host on Linux.
  • Another machine: its LAN or VPN IP. Make sure the service listens on all interfaces, not only 127.0.0.1.

Quick diagnosis

# what networks is Caddy on?
docker inspect caddy --format '{{json .NetworkSettings.Networks}}' | jq 'keys'

# can Caddy resolve the upstream name?
docker exec caddy nslookup status-server
docker exec caddy wget -qO- http://status-server:3001

# list everything on a given network
docker network inspect caddy-net

If nslookup works but wget fails, DNS is fine and the port is wrong. If the CaddyUI upstream test passes but the browser still gets 502, check the Caddy container's own logs with Observe → Server Logs.

Rule of thumb: every new upstream must either share a network with Caddy or be reached by host or LAN IP. One caddy-net that every service joins saves a lot of debugging.

Clone this wiki locally