Docker Networking
Exposing Containers to the Outside World — Port Mapping and Reverse Proxies
Configuring port translations and routing ingress via Nginx/Traefik.
Interview: Highly relevant for platform engineers. You must explain how external client traffic enters a host network card and reaches private container ports, including the role of iptables.
Introduction
By default, containers running on bridge networks are locked behind a private subnet. While they can make outbound connections to the internet, external clients cannot access them directly.
To make a container service accessible to developers or clients outside the host machine, you must configure **Port Mapping** or deploy a **Reverse Ingress Proxy**.
Why It Matters
Exposing ports opens firewall security channels. Improperly mapping database ports (like exposing port 3306 or 5432 to 0.0.0.0) exposes your internal data to global brute-force attacks.
Port Mapping Mechanics (-p)
When you use the command docker run -p 8080:80 nginx, Docker performs port translation:
• **The Mapping:** Host port 8080 is linked to the container's private port 80.
• **The Route (iptables):** Behind the scenes, the Docker daemon modifies the host machine's **iptables NAT rules**. Any packet arriving at the host's network interface card on port 8080 is automatically forwarded to the container's private IP address on port 80.
Binding to Specific Interfaces
By default, port mapping binds to 0.0.0.0 (all host interfaces):
-p 8080:80 (Publicly accessible).
To restrict access to the local machine or private networks, bind to specific IP interfaces:
• -p 127.0.0.1:8080:80 (Loopback only - reachable only from local host).
• -p 10.0.0.5:8080:80 (Private subnet NIC only).
Practical Example
Let's run Nginx, map it to port 9000 locally, and inspect the iptables rules to see the packet routing:
What just happened? We verified that the packet was intercepted by iptables, which translated the destination address (DNAT) from host port 9000 to the container's private IP address on port 80.
Quick Quiz
Q1: If you run "docker run -p 8080:80 my-app" on a server, what happens if another process tries to bind to port 8080 on the host?
A) Docker relocates the container to another port automatically.
B) The command fails with an error: "port is already allocated".
C) Both share the port using virtual host interfaces.
D) The server firewall is disabled.
Answer: B — Docker cannot map to a host port that is already in use by another local process or container.
Scenario-Based Challenge
Production Scenario:
You run 5 different web applications inside containers on a single host. You want all of them to be accessible on public port 80, routed based on their domain names (e.g., api.example.com, admin.example.com). Since you cannot map port 80 multiple times, how do you architect this?
To host multiple websites on a single port:
1. Deploy an **Ingress Reverse Proxy** container (like Nginx, Traefik, or Caddy) and map it to the host's port 80:
docker run -p 80:80 --name proxy --network web-net nginx
2. Keep your 5 web application containers isolated on the same network without mapping their ports to the host (meaning no -p options).
3. Configure the reverse proxy proxy rules (e.g., Nginx server blocks) to inspect incoming HTTP host headers:
• If host is api.example.com, proxy pass to http://api-container:3000.
• If host is admin.example.com, proxy pass to http://admin-container:8000.
This routes all incoming external requests through a single gateway container, maintaining host port security.
Interview Questions
1. What is the security implication of exposing a port to 0.0.0.0?
It maps the container port to all active network adapters on the host machine. If the server has a public IP address, the container becomes accessible to the entire internet, bypassing local firewalls unless explicitly blocked in iptables.
2. What is EXPOSE in a Dockerfile, and does it publish ports?
EXPOSE is a metadata declaration inside a Dockerfile indicating which ports the application listens on. It does **not** map or publish any ports to the host filesystem. You must still use the -p flag at runtime.
Production Considerations
Docker bypasses standard system firewalls like UFW (Uncomplicated Firewall) on Ubuntu. Because Docker writes routing rules directly to iptables rules *before* UFW rules are evaluated, exposing a port with -p 8080:80 publishes it publicly even if UFW has a default deny-all-ingress rule. Always use explicit IP bindings (like -p 127.0.0.1:8080:80) to prevent accidental public exposures.