Docker Tutorial for Beginners From Images to Compose

Stackademic

Learn Docker with a practical path: images, containers, Dockerfile builds, compose stacks, and the workflow developers use in real projects.

Learning Docker is less about memorizing commands and more about understanding how applications are packaged, shipped, and run the same way on your laptop, in CI, and in production. If you searched for a docker tutorial because tutorials you tried skipped the mental model, this guide walks from first container to a repeatable workflow you can extend.

What Docker solves

Before containers, “it works on my machine” was a scheduling problem. Teams shipped source code plus a README of system dependencies. Versions drifted. CI used different libraries than staging. Docker does not replace virtual machines entirely, but for most application workloads it gives you a filesystem snapshot (an image) and a running instance (a container) that shares the host kernel.

You get:

  • Isolation without booting a full OS per app
  • Reproducible builds via a Dockerfile checked into git
  • Portable artifacts you can push to a registry and pull anywhere

That portability is why docker tutorials show up in cloud, DevOps, and backend learning paths alike.

Core vocabulary

TermMeaning
ImageRead-only template with app + dependencies
ContainerRunning (or stopped) process from an image
DockerfileRecipe that builds an image
RegistryStorage for images (Docker Hub, ECR, GHCR)
VolumePersistent storage outside the container layer
NetworkHow containers reach each other and the host

If you remember only one idea: images are immutable layers; containers are disposable.

Install and verify

Install Docker Desktop (macOS/Windows) or the engine packages on Linux. Verify:

docker version
docker run hello-world

hello-world downloads a tiny image, runs it, prints a message, and exits. You have just completed the full pull-run lifecycle.

Your first interactive container

Run an Ubuntu shell you can type into:

docker run -it --rm ubuntu:24.04 bash

Inside the container, cat /etc/os-release shows Ubuntu even if your host is different. Exit with exit; --rm deletes the container automatically.

Flags explained briefly:

  • -it attaches a terminal for interactive programs
  • --rm removes the container on exit (great for experiments)
  • ubuntu:24.04 is repository:tag

Building a real image

Suppose you have a small Node API in ./app. A minimal Dockerfile:

FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "server.js"]

Build and run:

docker build -t my-api:local .
docker run --rm -p 3000:3000 my-api:local

-p 3000:3000 maps host port 3000 to the container. Visit http://localhost:3000.

Layer caching matters

Docker caches each Dockerfile step. Copy dependency manifests before application source so npm ci reruns only when package.json changes. This single ordering trick speeds daily builds more than almost any other beginner tweak.

docker compose for multi-service apps

Most tutorials stop at one container. Real stacks need a database, cache, or worker. Docker Compose describes multiple services in YAML.

Example compose.yaml:

services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/app
    depends_on:
      - db
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Start everything:

docker compose up --build

Compose creates a private network; the API reaches Postgres at hostname db. Volumes keep database files when containers restart.

Everyday commands you will actually use

docker ps              # running containers
docker ps -a           # all containers
docker images          # local images
docker logs <id>       # stdout/stderr
docker exec -it <id> sh  # shell into running container
docker stop <id>
docker rm <id>
docker rmi <image>
docker system prune    # cleanup unused objects (careful in shared machines)

Learn docker compose logs -f api early—it saves hours when something fails on boot.

Development workflow patterns

Bind mounts let you edit code on the host while a container runs dependencies:

services:
  api:
    build: .
    volumes:
      - .:/app
    command: npm run dev

The container sees live file changes. Pair this with a .dockerignore so you do not copy node_modules from the host into the build context.

For production, stop bind-mounting source. Build an image in CI, scan it, push to a registry, deploy by digest—not :latest tags you cannot reproduce.

Security and hygiene basics

Containers are not automatic security. Treat them like processes:

  • Do not run as root when you can add a USER line in the Dockerfile
  • Pin base image tags (node:22-alpine, not node:latest)
  • Scan images in CI for known CVEs
  • Never bake secrets into images; inject via environment or a secrets manager at runtime

Where learners get stuck

  1. Confusing images and containers — You can have many containers from one image.
  2. Huge build contexts — Add .dockerignore for node_modules, .git, and build artifacts.
  3. Publishing ports — The app must listen on 0.0.0.0, not only 127.0.0.1, inside the container.
  4. File permissions on volumes — Linux bind mounts may create root-owned files; plan UIDs or named volumes.

Next steps after this tutorial

  • Push images to a registry and deploy on AWS ECS, Fly.io, or a Kubernetes cluster
  • Add health checks (HEALTHCHECK in Dockerfile or compose)
  • Learn multi-stage builds to keep production images small
  • Read official docs on BuildKit cache mounts when builds slow down

Docker becomes intuitive once you treat containers as cattle (replaceable) and images as golden templates. Run them often, delete them freely, and let your Dockerfile be the contract your team agrees on.

FAQ

Do I still need to learn Kubernetes? Not on day one. Compose covers local and small deployments. Learn orchestration when you need rolling updates across many nodes.

Is Docker free? The engine is open source. Docker Desktop licensing applies to larger enterprises; Linux engine installs are commonly used without Desktop.

How is Docker different from a VM? VMs virtualize hardware and boot full operating systems. Containers share the host kernel and isolate processes with namespaces and cgroups—lighter and faster to start.

Can I run Docker in CI? Yes. Most pipelines use Docker or BuildKit to build images, run tests in containers, and push artifacts before deploy.