Skip to content

Run an Nginx Docker Container on Port 8080

In the hello-world lab the container printed a message and stopped. Real applications are different: a web server must keep running and must be reachable from your browser. In this lab you'll run the Nginx web server in a container, publish it on port 8080, and open http://localhost:8080.

You'll learn the three docker run options you'll use almost every day: -d, --name and -p. All outputs are from a real run on Docker Engine 29.

Run the container

docker run -d --name my-nginx -p 8080:80 nginx
Output (first run, last lines)
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
...
Digest: sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
Status: Downloaded newer image for nginx:latest

Docker pulled the image (seven layers this time, much bigger than hello-world), created the container, started it, and printed the new container's 64-character ID. Then it returned your prompt immediately, because of -d.

PartMeaning
-dDetached: run in the background and give the terminal back. Without it, the terminal stays attached to Nginx's log output until you press Ctrl+C (which also stops the container).
--name my-nginxA name you choose, so later commands can say my-nginx instead of an ID or a random name.
-p 8080:80Publish a port: HOST_PORT:CONTAINER_PORT. Traffic to port 8080 on your computer is forwarded to port 80 inside the container.
nginxThe image, meaning nginx:latest from Docker Hub.

Check that it is running

docker ps
Output
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                     NAMES
ec8160a79506   nginx     "/docker-entrypoint.…"   8 minutes ago   Up 8 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   my-nginx
  • STATUS is Up: unlike hello-world, Nginx keeps running, because its main process is a server that waits for requests.
  • PORTS 0.0.0.0:8080->80/tcp: port 8080 on all of the host's IPv4 addresses forwards to port 80 in the container. [::]:8080 is the same for IPv6.
  • COMMAND is the image's start-up command. Nginx starts with /docker-entrypoint.sh, which then runs nginx -g "daemon off;". "daemon off" keeps Nginx in the foreground, which is exactly what keeps the container alive.

You can also ask Docker for just the port mapping:

docker port my-nginx
Output
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080

Open localhost:8080

Open http://localhost:8080 in your browser. You'll see the "Welcome to nginx!" page. The same request from the command line (curl -i http://localhost:8080) shows the response headers too:

Output
HTTP/1.1 200 OK
Server: nginx/1.31.8
Content-Type: text/html
Content-Length: 896
...

<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
Further configuration is required for the web server, reverse proxy,
API gateway, load balancer, content cache, or other features.</p>

The Server: nginx/1.31.8 header proves the page came from the Nginx inside the container. You never installed Nginx on Windows.

How the request reaches the container

Browser ---> localhost:8080 (your computer)
                 |
                 |  Docker's port forwarding (-p 8080:80)
                 v
             container my-nginx, port 80 ---> Nginx ---> /usr/share/nginx/html/index.html

A container has its own network namespace, with its own private IP address on Docker's internal bridge network. Nothing outside can reach it until you publish a port. The Nginx image documents that it listens on port 80 (EXPOSE 80 in its Dockerfile), but EXPOSE is only documentation. It's the -p option that actually opens the port on your machine.

Remember the order: host port first, container port second. -p 8080:80 means "my 8080 to the container's 80". Writing -p 80:8080 would forward host port 80 to port 8080 in the container, where nothing is listening.

Error: port is already allocated

A host port can be used by only one container (or program) at a time. Try to start a second Nginx on the same host port:

docker run -d --name my-nginx-2 -p 8080:80 nginx
Output
docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint my-nginx-2 (9705abf9...): Bind for 0.0.0.0:8080 failed: port is already allocated

Run 'docker run --help' for more information

The container was created but couldn't start. Remove it, and pick a different host port. The container port stays 80, because every Nginx container listens on its own port 80 in its own network namespace:

docker rm my-nginx-2
docker run -d --name my-nginx-2 -p 8081:80 nginx

Now http://localhost:8080 and http://localhost:8081 both returned HTTP 200: two independent web servers, from one image, on one computer. Remove the second one when you're done:

docker rm -f my-nginx-2

The same error appears if a non-Docker program (IIS, a local dev server, Skype in older days) already uses the port. Find out what is using it on Windows with netstat -ano | findstr :8080.

Stop and start: the page goes away and comes back

docker stop my-nginx

Refresh localhost:8080: the browser can no longer connect, because the process behind the port has stopped. The container still exists (docker ps -a shows it as Exited). Start it again:

docker start my-nginx

The page loads again (HTTP 200), with the same name, port mapping and settings. You don't repeat the -p option, because it was saved when the container was created. The full set of lifecycle commands is the subject of the next lab.

Common mistakes

SymptomCause and fix
Container is running but localhost:8080 doesn't openYou forgot -p. Ports can't be added to an existing container: remove it and run again with -p 8080:80.
port is already allocatedAnother container or program uses that host port. Use another host port or stop the other one.
Conflict. The container name "/my-nginx" is already in useNames are unique. Remove the old container (docker rm -f my-nginx) or choose another name.
Terminal is "stuck" showing logsYou ran without -d. Press Ctrl+C (stops the container) and run again with -d.

Interview questions

What does -p 8080:80 mean?

It publishes container port 80 on host port 8080: requests to port 8080 of the host are forwarded to port 80 inside the container. The format is host:container.

What is the difference between EXPOSE and -p?

EXPOSE in a Dockerfile only documents which port the application listens on. -p (or -P, which publishes all exposed ports to random host ports) actually opens the port on the host.

Why does the Nginx container keep running while hello-world stops?

A container lives as long as its main process. Nginx runs in the foreground (daemon off) waiting for requests; hello-world's program finishes immediately.

Summary

  • docker run -d --name my-nginx -p 8080:80 nginx runs Nginx in the background on host port 8080.
  • Port publishing is host:container; without -p the container isn't reachable from your browser.
  • One host port can be used by only one container; container ports don't conflict.
  • Stopping a container closes its port; starting it again restores everything, including the mapping.

Next lab: Practise the container lifecycle: create, stop, start, restart and remove.