How to Expose and Publish Docker Container Ports
In this tutorial, you'll learn about How to Expose and Publish Docker Container Ports. We cover key concepts, practical examples, and best practices.
The Problem
You start a container with docker run nginx and cannot access it at http://localhost:80. The service is running inside the container but not reachable from the host. Container ports are isolated by default — they exist only within the container's network namespace. You must explicitly publish them to make them accessible from the host or external clients. Without port publishing, even curl localhost:80 from the host machine will fail because Docker maps each container to an isolated network stack by default.
Quick Fix
1. Publish a port when running a container
docker run -d -p 8080:80 nginx:alpine
The syntax is host_port:container_port. This maps host port 8080 to container port 80. Access the app at http://localhost:8080.
Verify the mapping:
docker ps
Expected output:
CONTAINER ID IMAGE COMMAND PORTS NAMES
abc123def456 nginx:alpine "/docker-entrypoint.…" 0.0.0.0:8080->80/tcp silly_curie
2. Publish to a specific host IP
docker run -d -p 127.0.0.1:8080:80 nginx:alpine
This binds only to localhost, preventing external access. Useful for development services that should not be reachable from the network.
3. Publish all exposed ports randomly
docker run -d -P nginx:alpine
Docker assigns random host ports from the range 32768-60999. Check which ones with:
docker port <container-name>
Expected output:
80/tcp -> 0.0.0.0:32768
4. Use EXPOSE in a Dockerfile (documentation only)
FROM nginx:alpine
EXPOSE 80
EXPOSE 443
EXPOSE documents the port but does not publish it. You still need -p or -P at runtime. Think of it as a comment that tells users which ports the container listens on.
5. Port mapping in Docker Compose
services:
web:
image: nginx:alpine
ports:
- "8080:80"
- "443:8443"
You can also specify protocol:
ports:
- "8080:80/tcp"
- "5353:53/udp"
6. Map UDP ports
docker run -d -p 5353:53/udp my-dns-server
7. List port mappings for all containers
docker ps --format "table {{.Names}}\t{{.Ports}}"
Inspect Container Configuration
docker inspect <container-id> --format '{{json .Config}}' | python3 -m json.tool
# {
# "Hostname": "abc123",
# "Env": ["PATH=/usr/local/bin:..."],
# "Cmd": ["node", "app.js"]
# }
Use docker inspect to examine the full configuration of a container. This reveals misconfigurations in environment variables, command arguments, and network settings that may not appear in logs.
Prevention
- Use
docker psto verify port mappings after starting a container - Check for port conflicts with
ss -tlnpornetstat -tulnbefore starting a container - Never publish ports without specifying the host IP in production — bind to
127.0.0.1if only local access is needed - Use long-form syntax in Docker Compose for explicit port configurations:
ports: - published: 8080 target: 80 protocol: tcp
- Use Docker Compose for multi-container projects — it avoids the long
docker runargument list and makes port mappings explicit indocker-compose.yml
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro