arrow_backBack to field notes
DEVOPS Published 9 Aug 2026

What Is Docker and Why Should Developers Learn It?

A practical breakdown of Docker for developers: containers vs VMs, core commands, Dockerfiles, and how to start using it in real projects.

Docker keeps coming up in job postings and setup guides, and if you've never touched containers it can feel like a wall you have to climb before you're allowed to write real code. It's not that complicated once you get past the vocabulary.

What a container actually is

A container packages your application with everything it needs to run: the code, runtime, system libraries, and config files. It's not a virtual machine. A VM virtualizes an entire operating system, kernel included, which means booting one can take a minute and eat a few gigabytes of RAM. A container shares the host machine's kernel and only isolates the process, so it starts in under a second and typically uses tens of megabytes instead of gigabytes.

That difference is why Docker took over local development and CI pipelines so fast. You can spin up a Postgres database, a Redis cache, and your app server on one laptop without installing any of them directly on your OS.

The core pieces you need to know

There are four terms that cover most of what you'll deal with day to day:

  • Image: a read-only template built from a Dockerfile. Think of it as a snapshot of a filesystem plus metadata about how to run it.
  • Container: a running instance of an image. You can start, stop, and delete containers without touching the image they came from.
  • Dockerfile: a text file with instructions for building an image, line by line.
  • Registry: where images are stored and pulled from, most commonly Docker Hub.

A minimal Dockerfile for a Node.js app looks like this:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Build it with docker build -t my-app . and run it with docker run -p 3000:3000 my-app. The -p flag maps a port on your machine to a port inside the container, which is how you actually reach the app from your browser.

Commands you'll use constantly

A handful of commands cover most daily work:

  • docker ps — list running containers
  • docker ps -a — list all containers, including stopped ones
  • docker images — list images on your machine
  • docker logs <container> — check output from a running or crashed container
  • docker exec -it <container> sh — open a shell inside a running container
  • docker rm / docker rmi — clean up containers and images you no longer need

That last pair matters more than people expect. Docker will happily let disk space disappear into old images and stopped containers. Running docker system prune occasionally reclaims a surprising amount of space.

Why docker-compose changes the workflow

Most real projects need more than one container: an app server, a database, maybe a cache. Writing out docker run commands for each one gets old fast. docker-compose.yml lets you define the whole stack in one file:

services:
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: devpassword
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Run docker compose up and both services start together, networked so web can reach db by service name. This is the setup you'll see in almost every open-source repo's README, and understanding it means you can clone a project and have it running in minutes instead of manually installing Postgres, Redis, and whatever else the app needs.

Where people get tripped up early on

Volumes confuse almost everyone at first. Without a volume, anything written inside a container disappears when the container is removed, which is a problem for databases. The volumes section in the compose file above maps a named volume to a path inside the container so data survives restarts.

Another common mistake is copying node_modules or .git into the image because there's no .dockerignore file. Add one just like a .gitignore:

node_modules
.git
.env

That keeps builds faster and images smaller, which matters once you're pushing images to a registry or deploying to Kubernetes.

Where to go after the basics

Once building and running containers feels normal, the next useful skills are multi-stage builds for smaller production images, understanding Docker networking modes, and reading a docker inspect output when something isn't connecting right. None of it is hard, it's just unfamiliar the first time through.

For more on containerizing real applications and connecting them to cloud deployment pipelines, check out the DevOps and Cloud segments on Korra Studio.

Written with AI assistance, reviewed and published by Michal Pilch (CISSP), Korra Studio.

Ready to go further?

This is one note from the Korra Studio knowledge base — the platform pairs every topic with 1-to-1 mentoring.

Get started freearrow_forward