Docker
Containers
Networking
Ports
DevOps

How to list exposed port of all containers?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

When you run multiple Docker containers on a single host, keeping track of which ports each container exposes and publishes becomes critical for debugging connectivity issues and avoiding port conflicts. Docker provides several built-in commands and formatting options that make this information easy to extract. This guide walks through the most practical approaches, from quick one-liners to reusable shell scripts.

How Docker Ports Work

A container can declare ports in two ways. The EXPOSE instruction in a Dockerfile documents which ports the application listens on, but it does not actually publish them to the host. The -p (or --publish) flag at runtime creates a mapping from a host port to a container port, making the service reachable from outside the Docker network. When you list ports, you typically care about the published mappings because those are the ones accepting external traffic.

Using docker ps --format

The simplest way to see ports for every running container is the built-in docker ps command with a Go template.

bash
# Show container name and its port mappings
docker ps --format "table {{.Names}}\t{{.Ports}}"

Sample output:

 
1NAMES               PORTS
2web-app             0.0.0.0:8080->80/tcp
3redis-cache         6379/tcp
4postgres-db         0.0.0.0:5432->5432/tcp

Entries without the 0.0.0.0: prefix (like 6379/tcp above) are exposed but not published, meaning they are only reachable from other containers on the same Docker network.

Using docker inspect with Go Templates

docker inspect returns the full JSON configuration of a container. You can extract port bindings with a Go template to get machine-readable output.

bash
# Inspect a single container
docker inspect --format '{{.Name}}: {{range $p, $conf := .NetworkSettings.Ports}}{{$p}} -> {{$conf}} {{end}}' web-app

To iterate over all running containers at once, combine this with docker ps -q, which outputs only container IDs.

bash
docker ps -q | xargs -I {} docker inspect \
  --format '{{.Name}}: {{range $p, $conf := .NetworkSettings.Ports}}{{$p}}->{{if $conf}}{{(index $conf 0).HostPort}}{{end}} {{end}}' {}

Sample output:

 
/web-app: 80/tcp->8080
/redis-cache: 6379/tcp->
/postgres-db: 5432/tcp->5432

An empty value after the arrow means the port is exposed but not published to the host.

Using docker-compose ps

If your containers are managed by Docker Compose, the docker-compose ps command already groups output by service name and shows port mappings.

bash
docker-compose ps

Sample output:

 
1      Name                    Command              State           Ports
2--------------------------------------------------------------------------------
3myapp_web_1        nginx -g daemon off;           Up      0.0.0.0:8080->80/tcp
4myapp_redis_1      redis-server                   Up      6379/tcp
5myapp_db_1         docker-entrypoint.sh postgres  Up      0.0.0.0:5432->5432/tcp

For JSON output you can use the newer docker compose ps --format json (note: no hyphen in the v2 CLI plugin).

bash
docker compose ps --format json | jq '.[].Ports'

Shell Script for All Containers

When you need a portable solution that works in CI pipelines or monitoring scripts, a small shell loop does the job.

bash
1#!/usr/bin/env bash
2# list_ports.sh - List published ports for every running container
3
4printf "%-25s %-30s\n" "CONTAINER" "PUBLISHED PORTS"
5printf "%-25s %-30s\n" "---------" "---------------"
6
7for cid in $(docker ps -q); do
8  name=$(docker inspect --format '{{.Name}}' "$cid" | sed 's/^\///')
9  ports=$(docker port "$cid" 2>/dev/null)
10  if [ -z "$ports" ]; then
11    ports="(none)"
12  fi
13  printf "%-25s %-30s\n" "$name" "$ports"
14done

The docker port command used here only returns published ports, so containers that merely expose a port without publishing it will show (none).

Make the script executable and run it:

bash
chmod +x list_ports.sh
./list_ports.sh

Common Pitfalls

  • Confusing EXPOSE with -p: EXPOSE in a Dockerfile is documentation only. Without -p at runtime, the port is not reachable from the host. Many beginners assume EXPOSE alone is sufficient.
  • Forgetting stopped containers: docker ps only shows running containers by default. Add the -a flag if you also need to see port configurations of stopped containers.
  • IPv6 bindings hiding IPv4: On some Docker versions, publishing a port binds to both 0.0.0.0 and [::]. Filtering output by 0.0.0.0 alone can cause you to miss the IPv6 binding or vice versa.
  • Port conflicts across containers: Two containers cannot publish to the same host port. If you start a second container on an already-taken port, Docker returns an error, but the message can be cryptic if you do not know which container already holds the port.
  • docker-compose ps version mismatch: The standalone docker-compose (v1, Python-based) and the plugin docker compose (v2, Go-based) have slightly different output formats. Scripts that parse the text output may break when switching between versions.

Summary

  • Use docker ps --format "table {{.Names}}\t{{.Ports}}" for a quick overview of all running containers and their port mappings.
  • Use docker inspect with Go templates when you need machine-parseable output or want to distinguish exposed-only ports from published ones.
  • Use docker-compose ps (or docker compose ps) when your stack is Compose-managed, and pipe through jq for JSON processing.
  • Use a shell script with docker port for automation in CI pipelines or monitoring dashboards.
  • Always remember that EXPOSE alone does not publish a port; the -p flag at runtime is what creates the host-to-container mapping.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.