---
title: "Publish only the ports visitors use · Agent Wranglers"
url: https://agentwranglers.se/playbook/operations/containers/published-ports
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Publish only the ports visitors use

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/operations/rules.json) holds every rule of this playbook as JSON.

- Level: Required
- Chapter: [Containers](https://agentwranglers.se/playbook/operations/containers)
- Rule: Publish a container port on all host addresses only when visitors must reach it. Bind every other published port to 127.0.0.1.
- Risk: Data leaked or lost
- How: Docker publishes ports on every host address by default. Its own rules route that traffic before a host firewall such as ufw sees it. So a database port published for a quick test is open to the internet, whatever the host firewall says. Containers on a shared network reach each other without any published port. Write `127.0.0.1:5432:5432` when only the host needs the port. Run Docker Engine 28 or later, because older releases let machines on the same local network reach ports bound to localhost. Close the rest in the cloud firewall as [Deny all traffic unless a rule allows it](https://agentwranglers.se/playbook/infrastructure/networking-and-dns/deny-by-default-firewall) says.
- Check: `docker ps --format '{{.Names}} {{.Ports}}'` shows `0.0.0.0` or `[::]` only on the proxy's ports 80 and 443. A port scan from outside the host finds no other open port.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### YAML example

```yaml
services:
  proxy:
    ports: ["80:80", "443:443"]
  db:
    image: postgres:17.11-alpine
    ports: ["127.0.0.1:5432:5432"]
```

### Shell example

```sh
docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' shop
```

## Sources

- [Docker port publishing and mapping](https://docs.docker.com/engine/network/port-publishing/)
- [Docker packet filtering and firewalls](https://docs.docker.com/engine/network/packet-filtering-firewalls/)

## Related rules

- [Deny all traffic unless a rule allows it](https://agentwranglers.se/playbook/infrastructure/networking-and-dns/deny-by-default-firewall) in Infrastructure

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/operations/containers/published-ports">Agent Wranglers operations playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Run the same images locally with Compose](https://agentwranglers.se/playbook/operations/containers/compose-for-local)
- Next: [Put each container only on the networks it needs](https://agentwranglers.se/playbook/operations/containers/container-networks)
- [Containers](https://agentwranglers.se/playbook/operations/containers)
