Containers and Docker Basics
What containers are, images vs containers and the core commands.
What you will learn
- Explain image vs container
- Run and stop containers
- Map ports and mount volumes
"It works on my machine" is one of software's oldest problems. Docker solves it by packaging an application together with everything it needs (runtime, libraries, system tools, configuration) into a standard unit called a container. That container runs the same way on your laptop, a teammate's machine and a production server.
Images and containers
- An image is a read-only template: the packaged filesystem and default command. Think of it as a recipe or a class.
- A container is a running instance of an image, an isolated process. Think of it as a dish or an object. You can start many containers from one image.
- A registry (Docker Hub, GitHub Container Registry) stores and shares images.
Containers differ from virtual machines: they share the host's kernel rather than booting a full operating system, so they start in about a second and use far less memory.
docker --version
docker run hello-worldDocker looked for the image locally, pulled it from Docker Hub because it was missing, created a container and ran it. Now something more useful, a web server:
docker run -d --name web -p 8080:80 nginx-d: run in the background (detached).--name web: give the container a friendly name.-p 8080:80: map port 8080 on your machine to port 80 in the container. Visithttp://localhost:8080.
docker ps # running containers (add -a for all)
docker logs -f web # follow logs
docker exec -it web sh # open a shell inside
docker stop web # stop
docker start web # start again
docker rm web # delete the container
docker images # local images
docker rmi nginx # delete an image
docker system prune # clean unused dataEnvironment variables and volumes
A container's filesystem is temporary: delete the container and its data is gone. To keep data, mount a volume or a folder from your machine. Pass configuration through environment variables.
docker run -d --name db \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 postgres:16
# mount the current folder into a container (handy in development)
docker run --rm -it -v "$PWD":/app -w /app python:3.12 python script.pypostgres:16 pins a version. Without a tag you get latest, which changes over time and can break your builds. Always pin versions for anything that matters.
Try it yourself
Run a Redis container in the background on port 6379, connect to it with docker exec and redis-cli, set a key, then stop and remove the container.
Show solution
docker run -d --name cache -p 6379:6379 redis:7
docker exec -it cache redis-cli
# 127.0.0.1:6379> SET greeting hello
# 127.0.0.1:6379> GET greeting
docker stop cache && docker rm cache