shouldenough

DevOpsLearn Docker by Dockerizing Your App

Lesson 6 of 10

Lesson 06/14 minutes/2 graded

Run containers

Detached mode, port binding, container names, and why docker run keeps leaving containers behind on your machine.

Time to actually run something. I am using nginx for this, because it is a web server with a page you can open in a browser, so you get proof it worked instead of a log line you have to trust.

Start it in the foreground first

You pulled nginx:1.30.4-alpine last lesson. Run it:

docker run nginx:1.30.4-alpine

Your terminal fills with nginx starting up and then sits there. Those are the logs of the process inside the container, printed straight to your screen, and the last line will be about starting worker processes. The container is running, and your terminal is stuck.

Press Ctrl+C. The container stops, because you just killed the process it was running.

Then start it properly, in the background

Add -d, which stands for detached:

docker run -d nginx:1.30.4-alpine

This time you get one long line of letters and numbers back. That is the container id, and your prompt is free again. Check what is running:

docker ps

One row, with a short version of that id, the image it came from, when it started, and a name Docker made up for you, two random words joined together.

To see the logs you skipped by detaching, ask for them by id. The first few characters are enough:

docker logs a1b2c3

Two versions at the same time

Remember the promise from lesson one. Run a second, older nginx alongside the first:

docker run -d nginx:1.29-alpine

docker ps now shows two containers, one on 1.30.4 and one on 1.29.8, both running, neither bothered by the other. Two installs of nginx on my Fedora host would have been a fight over one config directory.

Reaching it from your browser

Open http://localhost:80 and there is nothing there. The container is running, but it is on Docker's own network, not yours.

Every service listens on a standard port inside its container. nginx uses 80, Redis uses 6379, Postgres uses 5432. The docker ps output shows you that port. What you need is to connect a port on your machine to that port inside the container, and that is called port binding. The flag is -p, and it takes your port first, then the container's:

docker stop a1b2c3
docker run -d -p 9000:80 nginx:1.30.4-alpine

Now open http://localhost:9000. You get the nginx welcome page, titled "Welcome to nginx!". Check that container's logs and your visit is in there: one line holding the address the request came from, the time, "GET / HTTP/1.1", and the status 200, followed by the name of your browser.

So the request went from your browser, through the port binding, into the container, and nginx answered. docker ps shows the binding too, so when you have five containers running you can look up which port each one is on instead of guessing.

Which port you pick on your side is up to you, but matching the container's port is the common habit. A MySQL container listening on 3306 gets bound to 3306 on the host. It saves you thinking about it later.

Names you chose yourself

Container ids are horrible to type and Docker's generated names are random. Give the container a name when you create it:

docker run -d -p 9000:80 --name web-app nginx:1.30.4-alpine

Every command that took an id takes the name instead:

~

Print the logs of the container you named web-app.

Stopping, and what stopping does not do

docker stop web-app stops it. docker ps shows nothing.

Here is the part that surprises people. Every docker run creates a brand new container, so if you have run that command five times, you now have five containers on your machine. Stopped ones are hidden from docker ps, but they are still there:

docker ps -a

The whole list shows up, with "Exited" and how long ago for the stopped ones. To start one of those again, you do not need run, which would build another one. Use its name or id:

docker start web-app

Your turn

Bind a container so you can reach it in the browser, in the background, with a name of your own.

~

Run nginx 1.30.4-alpine in the background, named web, reachable at localhost:9000.