4.5.11Software Engineering

Docker — images, containers, Dockerfile, docker-compose

2,173 words10 min readdifficulty · medium

WHY does Docker exist?

WHY not just use Virtual Machines (VMs)? A VM virtualizes the entire hardware + a full guest OS (gigabytes, slow boot). A container shares the host's Linux kernel and virtualizes only the userspace (megabytes, boots in milliseconds). You get isolation at a fraction of the cost.

Figure — Docker — images, containers, Dockerfile, docker-compose

WHAT are the core objects?


HOW does the layer system work (and why it's clever)

Images are built bottom-up. Imagine each instruction adding a transparent sheet on a stack:

[ writable container layer ]   ← only this is read/write, per container
---------------------------
[ layer 4: COPY app code   ]
[ layer 3: pip install deps]   ← read-only, SHARED between containers/images
[ layer 2: apt-get python  ]
[ layer 1: FROM ubuntu     ]   ← base

A real Dockerfile, line by line

FROM python:3.12-slim          # base image (a small Debian + Python)
WORKDIR /app                   # cd into /app (created if absent)
COPY requirements.txt .        # copy manifest ONLY (cache-friendly)
RUN pip install -r requirements.txt   # install deps -> cached layer
COPY . .                       # now copy source code
EXPOSE 8000                    # documents the port (does NOT publish it)
CMD ["python", "app.py"]       # default process run when container starts

Essential commands (HOW you actually drive it)

docker build -t myapp:1.0 .      # build image from Dockerfile in '.'
docker run -d -p 8080:8000 myapp:1.0   # -d detached, map host:container port
docker ps                        # list running containers
docker exec -it <id> bash        # open a shell inside a running container
docker logs <id>                 # view container stdout/stderr
docker stop <id> && docker rm <id>     # stop then remove
docker images                    # list images
docker volume create data        # persistent storage

docker-compose: orchestrating multiple containers

# docker-compose.yml
services:
  web:
    build: .                 # build from local Dockerfile
    ports:
      - "8080:8000"
    depends_on:
      - db                   # start db first
    environment:
      - DATABASE_URL=postgres://db:5432/mydb
  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data   # persist DB across restarts
volumes:
  pgdata:                    # named volume survives container deletion

Recall Feynman: explain to a 12-year-old

Imagine you bake a cake using a recipe card. The recipe card is the image — it never changes and you can copy it to a friend. When you actually bake and the cake exists on the table, that's the container — you can eat it (use it) and even mess it up. The Dockerfile is you writing the recipe step by step. docker-compose is a party menu: it says "make the cake, the juice, and the pizza together, and put them on the same table so they can pass things to each other." If you throw away the cake, the recipe card is still safe — so you can always bake another identical one.


Flashcards

What is the difference between a Docker image and a container?
An image is an immutable read-only template (layers); a container is a running instance of that image with an added thin writable layer.
Why does Docker use the host kernel instead of a guest OS like a VM?
To stay lightweight — containers virtualize only userspace via namespaces/cgroups, so they're MBs and boot in milliseconds vs GBs and slow boot for VMs.
In -p 8080:8000, which number is the host and which is the container?
Host:Container → 8080 is the host port, 8000 is the container port.
Why copy requirements.txt and install deps BEFORE COPY . .?
To keep the expensive dependency-install layer cached; copying code first would invalidate that cache on every code change.
Difference between RUN and CMD in a Dockerfile?
RUN executes at build time and bakes into the image; CMD sets the default command run at container start.
Difference between CMD and ENTRYPOINT?
ENTRYPOINT is the fixed executable; CMD provides default arguments that the user can override at docker run.
How does the web service reach the db service in docker-compose?
Compose creates a shared network and registers each service name as a DNS hostname, so web connects to db by name.
What happens to data written inside a container's filesystem when the container is deleted?
It is lost, because it lives in the ephemeral writable layer; use a volume to persist data.
What does EXPOSE 8000 actually do?
It only documents the port; it does NOT publish it — you still need -p at run time to reach it.
Image is to container as ___ is to ___ in OOP?
Class is to object (blueprint vs instance).

Connections

  • Virtual Machines vs Containers
  • Linux Namespaces and cgroups
  • CI-CD Pipelines — images are the build artifact that gets deployed
  • Kubernetes — orchestrates containers at scale (compose is the single-host cousin)
  • Microservices Architecture — each service in its own container
  • Environment Variables and 12-Factor App
  • Volumes and Persistent Storage

Concept Map

solves

lighter than

shares

isolated by

runs full

read-only template of

instantiated as

adds

lost unless

each instruction builds

enables

orchestrates many

is like a

Docker

Works on my machine problem

Virtual Machine

Container

Host Linux kernel

Namespaces + cgroups

Guest OS on hypervisor

Image

Stacked layers

Writable top layer

Volume

Dockerfile

Caching + sharing

docker-compose.yml

Class blueprint

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Socho tumhare paas ek app hai jo tumhare laptop pe perfectly chal raha hai, lekin dost ke system pe error de raha hai — kyunki uske paas alag Python version ya missing library hai. Docker exactly yahi problem solve karta hai: woh tumhari app ko uske poore environment ke saath ek box me pack kar deta hai. Us box ki "recipe" ko image kehte hain (read-only, fixed), aur jab woh box actually chalta hai to use container bolte hain (running instance). Image is to container, bilkul jaise class is to object.

Dockerfile ek simple text file hai jisme step-by-step likhte ho: kaunsa base lo (FROM), code copy karo (COPY), dependencies install karo (RUN), aur start hote hi kya chalana hai (CMD). Har instruction ek layer banata hai, aur Docker un layers ko cache karta hai — isiliye requirements.txt pehle copy karke install karte hain, taaki code badalne par bhi install dobara na ho. Yeh chhota sa trick build ko bahut fast bana deta hai.

docker-compose tab kaam aata hai jab app me ek se zyada container ho — jaise web server plus database. Ek YAML file me saari services likho aur docker compose up se poora stack ek saath chal jaata hai. Compose ek shared network banata hai jisme har service apne naam se (jaise db) doosre ko dhoond leti hai, IP address yaad rakhne ki zaroorat nahi. Aur dhyan rakho: container ka data delete hone par ud jaata hai, isliye database ke liye hamesha volume use karo taaki data safe rahe.

Why it matters? Aaj har company — startups se lekin big tech tak — Docker use karti hai deployment, CI/CD aur microservices ke liye. Agar tum Docker comfortably samajh lo to "works on my machine" wali tension khatam, aur tum industry-ready ho jaate ho.

Go deeper — visual, from zero

Test yourself — Software Engineering

Connections