00 /What You Will Learn
- Say in one sentence what Docker is and why teams use it.
- Tell an image from a container, and a container from a virtual machine.
- Build your own image from a 4 line
Dockerfileand start a container from it. - Open a port, read logs, and step inside a running container.
- Explain why data disappears when a container is removed, and keep it with a volume.
Before you start
You need a laptop and Docker Desktop. That is all. On Windows, Docker Desktop also needs WSL2 (a small Linux that runs inside Windows), and the installer offers to set it up for you. After installing, open Docker Desktop and wait until it says it is running.
Check that it works. Open a terminal and type:
docker versionYou should see two parts, Client and Server. If the Server part says it cannot connect, Docker Desktop is not running yet. Start it, wait a minute, and try again.
Use PowerShell, or Git Bash. In Git Bash a path such as /app inside a docker command can get rewritten to C:/Program Files/Git/app. If you see that, put MSYS_NO_PATHCONV=1 in front of the command, or switch to PowerShell.
01 /Why It Matters
Every developer has said it: "but it works on my machine". Your laptop has Python 3.11, your friend has 3.9, the server has 3.8, and the app breaks in a different way on each one. A new joiner loses two days just installing the right versions of the right tools.
Think of the Mumbai dabbawalas. They carry thousands of tiffin boxes every day and they never open one. The box is sealed, labelled and standard, so the dal, the rice and the sabzi inside do not matter to the carrier. Docker does the same for software. You pack your app and everything it needs into one sealed box. Any machine with Docker can carry that box and open it, and the app inside behaves the same way.
Docker lets you ship an app together with the exact things it needs to run, so it behaves the same on your laptop, your friend's laptop and the production server.
Docker is not a virtual machine
A virtual machine (VM) is a full pretend computer with its own operating system. It is heavy: gigabytes of disk, a minute to start. A container shares your computer's operating system core and carries only your app and its libraries. That is why a container is small (this one is about 90 MB) and starts in about a second.
| Virtual machine | Container | |
|---|---|---|
| What it carries | A whole operating system plus your app | Only your app and its libraries |
| Size | Gigabytes | Tens of megabytes |
| Start time | About a minute | About a second |
| Isolation | Very strong | Good, but shares the host's core |
02 /What We Are Building
One tiny web app. It says hello and counts how many times you visited. It saves the count in a file. The count is the whole point: it shows what survives when a container is deleted and what does not.
The parts
app/server.py: the web app (about 50 lines of Python, no extra libraries).Dockerfile: the recipe that turns the app into an image.- Container
basics-web: a running copy of that image. - Port 18110 on your laptop is connected to port 8080 inside the container.
- Volume
basics-data: a Docker-managed folder outside the container, mounted at/data. Added in the last steps.
03 /Words You Need
Read this table once. Every word comes back in the steps, and by the end it will feel natural.
| Word | Plain meaning | Tiffin box example |
|---|---|---|
| Image | A frozen, ready-to-run package: your app, its libraries and settings. You cannot change it while it runs. | The sealed, packed tiffin |
| Container | A running copy of an image. You can start many from one image. | The tiffin on your desk, open |
| Dockerfile | A short text recipe that says how to build an image. | The recipe card |
| Registry (Docker Hub) | A website that stores images, so you can download them. | The central kitchen |
| Tag | A label on an image, like python:3.11.17-alpine3.24 (name, colon, version). | The sticker with the date |
| Port mapping | Connects a port on your laptop to a port inside the container. | The delivery window |
| Volume | A folder kept outside the container, so data survives when the container goes. | Home kitchen, where the food really lives |
| Docker Engine | The program that builds images and runs containers. Docker Desktop installs it for you. | The dabbawala system |
| Isolation | How well one running thing is kept apart from the others. Containers are well isolated, virtual machines even more. | Separate tiffins in one bag |
04 /Predict Before You Run
Guess first, then open the answer. Guessing wrong is useful: it shows you what to look for.
Question 1: You start two containers from the same image. Do they share anything?
No. Each container gets its own private files and its own running process. The image is shared and read-only. Think of two cooks using the same recipe card in two kitchens.
Question 2: You visit the app 3 times, then delete the container and start a new one from the same image. What does the counter show?
It shows 1. The count was saved in a file inside the old container, and deleting a container deletes its files. Only a volume survives. You will see this happen in step 5.
Question 3: You try to start a second container on the same laptop port 18110 while the first is running. What happens?
Docker refuses with "port is already allocated". One port can have only one owner at a time. This is the most common Docker error you will ever see.
05 /Step by Step
Step 0: Get the lab
Download the zip with the button at the top of this page. Unzip it into a new folder and open a terminal inside that folder. Every command below runs from there.
mkdir docker-basics && cd docker-basics
unzip ~/Downloads/docker-basics.zipmkdir docker-basics; cd docker-basics
Expand-Archive -Path "$HOME/Downloads/docker-basics.zip" -DestinationPath .Unzip the lab into a new folder and open a terminal in it. If you only want to watch it run with checks at the end of each step, run ./test-basics.sh (Mac, Linux, Git Bash) or .\test-basics.ps1 (PowerShell). To learn, type the steps yourself.
Step 1: Build the image
docker build -t desi-basics:1 .
docker images desi-basicsdocker build -t desi-basics:1 .
docker images desi-basicsWhat each part does
docker build
Reads the Dockerfile in this folder and makes an image from it.
-t desi-basics:1
Gives the image a name (desi-basics) and a version tag (1).
. (the dot)
Means "use the files in this folder".
You should see: the build steps finish, then docker images lists desi-basics with tag 1 and a size of about 90 MB.
Step 2: Run a container
docker run -d --name basics-web -p 127.0.0.1:18110:8080 desi-basics:1
curl http://127.0.0.1:18110docker run -d --name basics-web -p 127.0.0.1:18110:8080 desi-basics:1
curl.exe http://127.0.0.1:18110What each part does
docker run
Makes a container from an image and starts it.
-d
Runs it in the background (detached), so your terminal stays free.
--name basics-web
A name you can type later instead of a long random ID.
-p 127.0.0.1:18110:8080
Connects port 18110 on your laptop to port 8080 inside the container. The 127.0.0.1 means only your own laptop can reach it.
You should see: a small JSON answer with "visits": 1 and a container_id. Run curl again and it becomes 2. On Windows, type curl.exe and not curl. PowerShell has its own command called curl that behaves differently.
Step 3: Look around
docker ps
docker logs basics-web
docker exec basics-web ls /appdocker ps
docker logs basics-web
docker exec basics-web ls /appdocker pslists running containers. You should seebasics-weband the port mapping.docker logsshows what the app printed. You should seeserver starting on port 8080and arequest:line for every visit.docker execruns one command inside the running container. You should seeserver.py.
Want to walk inside? docker exec -it basics-web sh opens a shell. Type ls, look around, and type exit to come out. You will notice it is a tiny Linux with almost nothing in it.
Step 4: Break it, part 1. Take the same port twice
docker run -d --name basics-web-2 -p 127.0.0.1:18110:8080 desi-basics:1You should see: an error ending in port is already allocated. Clean up the failed container with docker rm -f basics-web-2.
Step 5: Break it, part 2. Delete the container, lose the data
docker rm -f basics-web
docker run -d --name basics-web -p 127.0.0.1:18110:8080 desi-basics:1
curl http://127.0.0.1:18110docker rm -f basics-web
docker run -d --name basics-web -p 127.0.0.1:18110:8080 desi-basics:1
curl.exe http://127.0.0.1:18110You should see: "visits": 1 again. The old count lived inside the old container, and it went when the container went.
Step 6: Fix it with a volume
docker rm -f basics-web
docker run -d --name basics-web -p 127.0.0.1:18110:8080 -v basics-data:/data desi-basics:1
curl http://127.0.0.1:18110
curl http://127.0.0.1:18110docker rm -f basics-web
docker run -d --name basics-web -p 127.0.0.1:18110:8080 -v basics-data:/data desi-basics:1
curl.exe http://127.0.0.1:18110
curl.exe http://127.0.0.1:18110-v basics-data:/data mounts a Docker-managed volume at /data, the folder where the app saves its count. Now delete the container again and start a new one with the same -v option. You should see: the count continues instead of starting from 1. The data lives in the volume, so it outlives any container.
Anything a container must remember (a database, uploads, logs you need) goes in a volume. Anything else is disposable. This one rule prevents most "we lost our data after a redeploy" stories.
06 /What You Should See
This is the real output of the automated version of the lab (test-basics), recorded on a real run. Your numbers will differ in small ways, such as the exact counter values. Every line starting with [OK] is a check that passed.
The numbers above come from one run on one laptop with Docker Desktop. Your machine will show different timings and counters. What must match is the shape of the result, the [OK] lines.
07 /Look Inside
Docker keeps records of everything it does. These commands let you see them. Try them while the container from step 6 is still running.
1. See every container, even stopped ones
Run: docker ps -a
You should see: a table with the container name, its image, how long it has been up, and its ports.
It means: a container that stopped still exists until you remove it. docker rm is what deletes it.
2. See the volume
Run: docker volume ls and then docker volume inspect basics-data
You should see: a volume named basics-data, with a Mountpoint on Docker's own storage.
It means: the volume is an object by itself. Containers come and go, and it stays until you run docker volume rm.
3. See the layers of an image
Run: docker history desi-basics:1
You should see: one line for each instruction of the Dockerfile, with sizes.
It means: an image is a stack of layers. Docker reuses layers it already has, which is why a second build is much faster.
08 /Break It, Then Fix It
Predict: if you change the left number in -p 127.0.0.1:18110:8080 to 18111, which URL works now, and does the app inside need any change?
Try it:
docker rm -f basics-web
docker run -d --name basics-web -p 127.0.0.1:18111:8080 desi-basics:1
curl http://127.0.0.1:18111What happened: the app listens on 8080 inside the container, always. The left number is only the door on your laptop. You can choose any free door without touching the app. That is the point of port mapping.
Stretch: edit the greeting in app/server.py, build the image again as desi-basics:2, and run it. Does the old desi-basics:1 still exist? (Yes: images are separate versions.)
09 /What Changes in Real Projects
- Images come from a registry. You build once in CI and push to a registry. Servers pull the same image. Nobody builds on the production machine.
- Pin the version.
python:3.11.17-alpine3.24is good. Floating tags likelatestor3.11change under you when base images rebuild upstream. - Run as a non-root user. Containers default to root. If an attacker escapes your app, they have root capabilities on the container filesystem. Use
USER 10001in your Dockerfile. To verify who your container runs as, checkdocker exec <container> id -u; it must not print 0. - Add a .dockerignore file. Without
.dockerignore,docker buildsends your whole folder, including.git,.envfiles, temporary build files and secrets, into the build context. That slows builds down and risks leaking secrets into layers. - Scan images for vulnerabilities. Tools like
docker scout quickview <image>(an optional feature in Docker Desktop, not run in CI here) check image packages against CVE databases before shipping. - Secrets handling. Passwords written in Compose files are for this lab only. Real systems read secrets from a secret manager or injected files, never from the repo.
- Data goes in volumes or managed databases. A container is cattle, not a pet. If you cannot delete and recreate it without fear, something is stored in the wrong place.
- One job per container. One container for the web app, another for the database, as you will do in the next lab.
- Many containers on many machines are managed by Kubernetes or a similar system. Everything you learned here still applies inside it.
You gained a box that runs the same everywhere. You gave up some simplicity: one more tool to learn, images that take disk space, and a new family of errors (ports, names, paths) that did not exist before. For one app on one laptop that is a small price. It pays back the first time a teammate runs your project in two minutes instead of two days.
10 /Interview Corner
Simple questions, and what a good answer sounds like.
- What is the difference between an image and a container? An image is the frozen package, a container is a running copy of it. One image can start many containers, like one recipe cooked in many kitchens.
- Why does data disappear when I remove a container? The container's files live in a writable layer that belongs to that container. Removing the container removes the layer. To keep data, store it in a volume or outside Docker.
- How is a container different from a virtual machine? A VM carries a full operating system. A container shares the host's operating system core and carries only the app, so it is smaller and starts faster. The price is weaker isolation.
Follow-up questions the interviewer will ask
- What happens to a container's files when it restarts, and when it is removed?
- Why do we map a port, and what would happen without
-p? - What is the danger of using the
latesttag in production?
11 /Clean Up
docker rm -f basics-web
docker volume rm basics-data
docker rmi desi-basics:1docker rm -f basics-web
docker volume rm basics-data
docker rmi desi-basics:1The automated script cleans up after itself. Next: Lab 01, Docker Compose Basics, where one file starts two containers that talk to each other.