example-projects/reference/docker/03_running_containers.md

4.3 KiB

Lesson 03: Running Containers (and Pretending You're on a Different OS)

Now we run something with substance. This lesson is mostly about feeling, in your hands, what container isolation actually means.

Step into Ubuntu — even if you're on a Mac or Windows

docker run -it ubuntu bash

The new flags:

  • -i — keep STDIN open so you can type into the container.
  • -t — allocate a pseudo-TTY so the terminal behaves like a real shell.
  • (-it is just -i and -t stuck together — you'll see this everywhere.)

ubuntu is the image name. bash is the command to run inside, overriding the image's default.

After a brief download, your prompt changes to something like:

root@a1b2c3d4e5f6:/#

You are now in a shell inside an Ubuntu container. Try a few commands:

cat /etc/os-release       # confirm it really is Ubuntu
ls /                      # the container's root filesystem
whoami                    # root, by default, inside a container
apt-get update            # this Ubuntu's package manager (works even on a Mac)
apt-get install -y cowsay # install something
/usr/games/cowsay "I am running inside Docker"

You just installed cowsay into an Ubuntu system on your machine without touching your real machine at all. To leave:

exit

You're back on your real machine. None of those packages are installed on your host. The container is still around (stopped, but present) — we'll clean it up in the next lesson.

Now try Alpine — a totally different distro

docker run -it alpine sh

Alpine is a tiny Linux distro often used for containers (the image is around 5MB). It uses sh instead of bash and apk instead of apt-get:

cat /etc/os-release       # now it's Alpine
apk add --no-cache cowsay
cowsay "Different OS, same laptop"
exit

Two completely different Linux distributions, one after the other, on the same physical machine, neither one leaving a trace once it stops.

Now Python, with no Python installed on your host

docker run -it python:3.12 python

You're dropped into a Python 3.12 REPL — running inside a container that has Python 3.12 installed, even if your real machine has Python 3.10, Python 2, or no Python at all. Type:

import sys
sys.version
exit()

You just used Python 3.12 without installing it.

The :tag part

Notice python:3.12. The part after the colon is the tag, usually a version. If you leave it off (python), Docker assumes :latest which is whatever the maintainers most recently published. You should usually pin a version explicitly so your work is reproducible.

Some examples of tags you'll see:

  • python:3.12 — Python 3.12 on a default base.
  • python:3.12-slim — same Python, on a much smaller Debian base. Faster to download, smaller disk footprint.
  • python:3.12-alpine — same Python, on the tiny Alpine base. Even smaller. Occasionally causes issues with packages that expect a glibc-based system.
  • ubuntu:22.04, ubuntu:24.04, ubuntu:latest — Ubuntu by version number.
  • postgres:16, redis:7, nginx:1.27 — pick the major version you want.

When in doubt, look up the image on Docker Hub (https://hub.docker.com/) and read its tag list.

Run a container in the background

Some containers (web servers, databases) are meant to keep running. Use -d (detached) to start one in the background:

docker run -d --name webserver nginx

--name webserver gives the container a memorable name instead of a random one like peaceful_einstein. Visit http://localhost … wait, you can't yet. We haven't told Docker to expose its port. That's lesson 07. For now, just check it's running:

docker ps

You should see one running container. Stop it:

docker stop webserver

Try it yourself

  1. Run an Ubuntu container and a Debian container side-by-side in two terminal windows. Note that cat /etc/os-release shows different distros in each, even though they share your machine.
  2. Run docker run -it python:3.11 python and then docker run -it python:3.12 python. Two different Python versions, on the same laptop, in the same minute, without installing anything.
  3. Move on to 04_images_vs_containers.md — by now you've created several containers and you may be wondering where they all went.