Appearance
Get a Docker container's public IP
Ask from inside: docker exec <container> curl -s ipconfig.io — and on any normal setup the answer is your host's public IP, because containers don't have one of their own: they egress through the host's connection via NAT. The 172.17.x.x address everyone finds first in docker inspect is real but internal — a bridge-network address that never leaves the machine. This guide sorts the three address layers and the cases where the inside-view answer genuinely differs.
Maintained by the ipconfig.io team · Reviewed 1 July 2026
The one-liners
bash
# From inside a running container:
docker exec mycontainer curl -s ipconfig.io
# As a one-off probe:
docker run --rm curlimages/curl -s ipconfig.io
# The full record — whose network, which country:
docker exec mycontainer curl -s ipconfig.io/jsonCompare with curl -s ipconfig.io on the host itself. Matching answers (the overwhelmingly common case) confirm the container rides the host's egress.
Three layers, three addresses
| Layer | Example | Scope |
|---|---|---|
Container on the bridge (docker inspect) | 172.17.0.2 | This host only — Docker's own private network |
| Host on the LAN | 192.168.1.23 | Your local network |
Public egress (curl ipconfig.io from inside) | 203.0.113.42 | What every server sees |
Docker's bridge is NAT all the way down: outbound container traffic is rewritten to the host's address (then possibly rewritten again by your router — NAT twice before breakfast). Which explains both classic confusions: inspect shows an address the internet has never heard of, and inbound traffic needs -p port publishing for exactly the reason port forwarding exists at the router — unsolicited connections match nothing in a NAT table. (-p 8080:80 binds on all host interfaces; -p 127.0.0.1:8080:80 keeps it localhost-only.)
When inside ≠ outside
If the container's answer differs from the host's, something is deliberately (or accidentally) routing them apart — and the asn_org field usually names it:
- A VPN on the host that containers bypass, or (with some clients' split tunneling) the reverse — one of the two is leaking around the tunnel.
- An outbound proxy configured in the container (
HTTP_PROXYenv) but not the host — proxy rules apply. - Orchestrator egress — Kubernetes pods behind a cloud NAT gateway or egress IP will report the gateway's address, which is the number you actually need for allowlisting (same story as CI runners).
--network hostremoves Docker's layer entirely — the container is the host, network-wise; answers can't differ.
The two-curl comparison — inside vs host — is the whole diagnostic. Whichever address surprised you, its ASN tells you whose network took over.
Frequently asked questions
Container's public IP?docker exec <c> curl -s ipconfig.io — normally the host's public address.
Why is inspect showing 172.17.x? That's the internal bridge address. The public one exists only outside the machine.
Do containers get their own public IP? Not by default — shared host egress. Macvlan/host networking and cloud egress gateways are the deliberate exceptions.
Inside differs from host? VPN, proxy env vars, or orchestrator egress — read asn_org from both and compare.
Next steps
- What is NAT? — the translation stack containers sit at the bottom of.
- What is localhost? — binding and publishing ports to the right audience.
- Get the public IP of a GitHub Actions runner — the same question in CI.