Skip to main content

Command Palette

Search for a command to run...

How to Expose Docker Containers to External Users

Updated
7 min readView as Markdown

We know that an application runs inside a Docker container or Kubernetes Pod. But how can a user outside the container or cluster access that application?

For example: User │ │ http://20.10.10.5:8080 ▼ ??? │ ▼ Application running inside container

docker run -p 8080:80 nginx

-p HOST_PORT:CONTAINER_PORT

 8080 : 80
   │     │
   │     └── Container port
   │
   └──────── Host port

Traffic:

External User │ │ http://HOST\_IP:8080 ▼ Docker Host :8080 │ │ Docker port mapping ▼ Container :80 │ ▼ Nginx

Container Port vs Host Port:

docker run -p 8080:80 nginx

Port Meaning 8080 Host port 80 Container port

What happens without -p?

This is an important comparison.

docker run nginx

versus:

docker run -p 8080:80 nginx Without publishing User X │ Docker Host │ Container :80 With publishing User │ ▼ Host :8080 │ ▼ Container :80 │ ▼ Nginx

Explain:

The -p option publishes a container port on the Docker host, allowing traffic to reach the container through the host's network interface.

  1. Docker Port Publishing with Different Ports

Use:

docker run -p 9090:80 nginx

Then:

User │ │ :9090 ▼ Docker Host │ │ mapping ▼ Container :80 │ ▼ Nginx

The user connects to:

http://HOST\_IP:9090

while Nginx remains on:

:80

This is a great example because it reinforces the concept from your previous article.

  1. Now introduce Kubernetes

This is where the article becomes very useful for DevOps.

Start with:

Docker Container ↓ -p 8080:80 ↓ External User

But Kubernetes is different.

A Pod has an IP address, but you generally should not expose applications directly through Pod IPs.

Why?

Because Pods are:

Temporary Recreated Scaled Replaced Assigned changing IP addresses

Therefore Kubernetes provides Services.

  1. Kubernetes Pod

Example:

apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80

Visual:

Kubernetes Cluster

┌─────────────────────────┐ │ Node │ │ │ │ ┌─────────────────┐ │ │ │ Pod │ │ │ │ │ │ │ │ Nginx :80 │ │ │ └─────────────────┘ │ │ │ └─────────────────────────┘

Then explain:

containerPort: 80 documents the port the container is expected to listen on. By itself, it does not make the Pod externally accessible.

This is a very important point.

  1. Kubernetes Service

Now introduce:

Pod ↓ Service ↓ External access

A Service provides a stable endpoint for Pods.

Example:

apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - port: 80 targetPort: 80

Visual:

             Kubernetes Cluster

   ┌─────────────────────────────┐
   │                             │
   │       Service :80           │
   │             │               │
   │       ┌─────┴─────┐         │
   │       ↓           ↓         │
   │    Pod :80     Pod :80      │
   │                             │
   └─────────────────────────────┘

Explain:

Service port → 80 Target port → 80

The Service forwards traffic to matching Pods.

  1. How does an external user access Kubernetes?

This is where you introduce Service types.

The main ones you should cover are:

ClusterIP NodePort LoadBalancer

And later:

Ingress 10. ClusterIP

Default Service type:

type: ClusterIP

Traffic:

Pod ↑ │ Service :80 ↑ │ Internal clients

ClusterIP is generally internal to the cluster.

So:

External Internet X │ ▼ ClusterIP Service │ ▼ Pod

Use it for communication between applications inside Kubernetes.

Example:

frontend │ ▼ backend-service │ ▼ backend Pod 11. NodePort

Now expose it externally.

type: NodePort

Example:

Service Port: 80 NodePort: 30080

Traffic:

External User │ │ :30080 ▼ Kubernetes Node │ │ ▼ Service :80 │ ▼ Pod :80

User accesses:

http://NODE\_IP:30080

This is very important to understand.

  1. LoadBalancer

For cloud Kubernetes such as AKS, this is one of the most important concepts.

Example:

type: LoadBalancer

Traffic:

                Internet
                   │
                   ▼
           Public IP Address
                   │
                   ▼
          Cloud Load Balancer
                   │
                   ▼
            Kubernetes Service
                   │
                   ▼
                Pod :80

For Azure AKS, the external user can ultimately access something like:

http://PUBLIC\_IP:80

The exact public IP is assigned by the cloud infrastructure.

  1. Compare Docker vs Kubernetes

This should be one of the strongest sections of the article.

Docker Kubernetes Container Pod Container port Container port -p Service Host port NodePort / LoadBalancer Docker host IP Node/external endpoint Docker port publishing Kubernetes Service exposure

Conceptually:

DOCKER

User ↓ Host :8080 ↓ Container :80 ↓ Application

versus:

KUBERNETES

User ↓ LoadBalancer :80 ↓ Service :80 ↓ Pod :80 ↓ Application 14. The most important Kubernetes port concepts

I strongly recommend having a dedicated section for this because these names confuse almost everyone initially.

containerPort ↓ targetPort ↓ port ↓ nodePort

But don't imply these always form one direct sequential chain.

Explain each separately:

containerPort

Port on which the application inside the container listens.

Pod └── Container :8080 targetPort

Port on the Pod/container that the Service forwards traffic to.

Service │ │ targetPort: 8080 ▼ Pod :8080 port

Port exposed by the Kubernetes Service.

Service :80 │ ▼ Pod :8080

Example:

ports:

  • port: 80 targetPort: 8080

Traffic:

Client ↓ Service :80 ↓ Pod :8080 ↓ Application nodePort

Port exposed on Kubernetes nodes.

Node :30080 ↓ Service :80 ↓ Pod :8080 15. Complete Kubernetes example

This would be an excellent practical exercise.

Deployment apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 Service apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: LoadBalancer selector: app: nginx ports: - port: 80 targetPort: 80

Then:

                External User
                      │
                      │ HTTP :80
                      ▼
            ┌──────────────────┐
            │ Public IP        │
            │ Load Balancer    │
            └────────┬─────────┘
                     │
                     ▼
            ┌──────────────────┐
            │ Service :80      │
            └────────┬─────────┘
                     │
              ┌──────┴──────┐
              ▼             ▼
         Pod :80        Pod :80
         Nginx           Nginx

This also demonstrates why a Service is useful when you have multiple replicas.

  1. Troubleshooting section

Definitely add this.

Docker

If:

docker run nginx

doesn't work externally, check:

Is container running? ↓ Is application listening? ↓ Was the port published? ↓ Is Docker mapping correct? ↓ Is host firewall allowing the port? ↓ Is cloud NSG/security rule allowing it?

Commands:

docker ps docker port Kubernetes

If your Pod is running but you can't access it:

Pod running? ↓ Application listening? ↓ Service exists? ↓ Service selector matches Pod labels? ↓ Correct targetPort? ↓ Correct Service type? ↓ NodePort / LoadBalancer configured? ↓ Cloud firewall / NSG?

Useful commands:

kubectl get pods kubectl get svc kubectl describe svc nginx-service kubectl get endpoints

And:

kubectl logs 17. Final mental model

End the article with one diagram readers can remember:

                EXTERNAL USER
                      │
                      ▼
             ┌─────────────────┐
             │ External Access │
             │                 │
             │ Docker → Host   │
             │ K8s → LB/Ingress│
             └────────┬────────┘
                      │
                      ▼
                SERVICE/PORT
                      │
                      ▼
                CONTAINER/POD
                      │
                      ▼
                 APPLICATION

Then summarize:

Docker uses port publishing (-p) to expose a container through the Docker host. Kubernetes uses Services to provide stable access to Pods, with NodePort and LoadBalancer commonly used for external access.

Recommended article title

I would use:

How to Expose Docker Containers and Kubernetes Pods to External Users

And your article series becomes:

  1. What is a Port? ↓

  2. How to Expose Docker Containers and Kubernetes Pods ↓

  3. Docker Networking Explained ↓

  4. Docker Bridge vs Host vs None Networks ↓

  5. Kubernetes Networking Explained ↓

  6. Kubernetes Services: ClusterIP, NodePort & LoadBalancer ↓

  7. Kubernetes Ingress Explained ↓

  8. Azure AKS Networking

This is a very good progression for your DevOps blog, because each article builds on the previous one instead of teaching isolated concepts.