Skip to content

How to Expose and Publish Docker Container Ports

DodaTech 2 min read

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 ps to verify port mappings after starting a container
  • Check for port conflicts with ss -tlnp or netstat -tuln before starting a container
  • Never publish ports without specifying the host IP in production — bind to 127.0.0.1 if 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 run argument list and makes port mappings explicit in docker-compose.yml

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro