Installing Docker and Running Your First Container
The two previous articles explained how Docker works. From this one on we go hands-on. The goal: install Docker, run your first container, and master a container's lifecycle — create, run, view, stop, remove.
Installing Docker
How to install depends on your operating system. Always get the latest version from the official site:
- macOS / Windows: install Docker Desktop (download from docker.com's Get Docker page). Remember from Article 1: on macOS/Windows, Docker Desktop runs a Linux VM underneath, and the daemon lives in it.
- Linux: install Docker Engine following the guide for your distro (Ubuntu, Debian, Fedora...). On Linux there's no VM because the Linux kernel is already there.
After installing, check:
docker version
If you see both the Client and Server blocks (as mentioned in Article 1), the client can reach the daemon. If it reports "Cannot connect to the Docker daemon," the daemon isn't running (open Docker Desktop, or on Linux run sudo systemctl start docker).
On Linux, if you have to type
sudobefore every docker command, add your user to thedockergroup:sudo usermod -aG docker $USERthen log back in. The reason relates to permission on the/var/run/docker.socksocket discussed in Article 1.
Run a test container (this image just prints a greeting and exits):
docker run hello-world
If you see the line "Hello from Docker!", everything is ready.
Running a proper first container
hello-world runs and exits immediately. Now run something "live" — an nginx web server:
docker run -d --name web -p 8080:80 nginx:alpine
Three important flags here:
-d(detached): run in the background, returning the terminal to you. Without-d, the container runs in the foreground and occupies the terminal until it stops.--name web: give the container a name. Without it, Docker generates a random name (likenostalgic_curie).-p 8080:80: map a port. Port80inside the container (where nginx listens) is "published" to port8080on your machine. The syntax is-p <host>:<container>. Article 7 explains the mechanism underneath.
Open a browser to http://localhost:8080 and you'll see the nginx welcome page. It's being served from the container you just created.
A container's lifecycle
A container goes through the following states:
docker run
│
▼
[Created] ──► [Running] ──stop──► [Exited]
▲ │
└──── start ────────┘
│
rm
▼
[Removed]
A common confusion: stop is not rm. A stopped container still exists (along with its writable layer), it's just not running. Only rm removes it for good.
View running containers:
docker ps
NAMES STATUS PORTS
web Up 2 seconds 0.0.0.0:8080->80/tcp
Add -a to view stopped containers too:
docker ps -a
Interacting with a running container
View logs (most useful when debugging):
docker logs web
Add -f to follow new logs in real time (like tail -f); Ctrl+C to exit:
docker logs -f web
Run a command inside a running container with exec:
docker exec web hostname
Open an interactive shell inside the container to look around (the -it flags = interactive + allocate a terminal):
docker exec -it web sh
Now you're inside the container. Try ls, cat /etc/nginx/nginx.conf, ps. Remember from Article 2: ps only sees the container's processes, and the hostname is the container id. Type exit to leave.
Distinguishing
runandexec:runcreates a new container from an image;execruns a command in an already-running container. Beginners often mistakenly userunwhen they actually wantexec.
Stop, restart, remove
docker stop web # send a stop signal, the container goes to Exited
docker start web # restart a stopped container (keeps its writable layer)
docker restart web # stop then start
Remove a container (must stop it first, or use -f to force):
docker stop web
docker rm web
A handy trick when experimenting: --rm makes the container delete itself as soon as it stops, so you don't have to clean up by hand:
docker run --rm -d --name tmp -p 8081:80 nginx:alpine
# when this container stops, it disappears on its own
🧹 Cleanup
Containers and images pile up and take disk space. At the end of each article we clean up what we just created.
Stop and remove this article's containers:
docker rm -f web tmp 2>/dev/null
See what containers remain:
docker ps -a
Remove the pulled images if you don't need to keep them:
docker rmi nginx:alpine hello-world
Or sweep up everything unused (stopped containers, images not tied to any container, leftover networks, build cache) with one command:
docker system prune
This command asks for confirmation before deleting. To see in advance how much Docker is using:
docker system df
Wrap-up
You've installed Docker, run a web server in a container, and gone through the full lifecycle: run (create + run), ps (view), logs/exec (interact), stop/start (off/on), rm (remove). The rules to burn in: stop ≠ rm, and run (new container) ≠ exec (into an existing container).
In Article 4 we explore the image — the thing docker run relies on: where it comes from (registry/Docker Hub), what layers it's made of (continuing from Article 2), and how to manage images on your machine.