Blog about Web Programming and Electronics
💬 👤
back Back to blog
Programming

How Docker Works: Everything You Need to Know About Containers

Docker is a tool that revolutionized the way developers build, package, and run applications. Instead of worrying whether an application will work on one computer or another, Docker ensures it runs identically everywhere - in a "container" that holds everything needed: code, libraries, dependencies, and configuration.

What is Docker?

Docker is a platform for developing, shipping, and running applications in containers. A container is a lightweight, standalone executable unit that contains everything an application needs to run. Unlike traditional virtual machines (VMs), containers don't need their own operating system - they share the kernel with the host system, making them much lighter and faster.

Virtual Machine vs. Container

This is a crucial question we need to answer to understand why Docker is so popular:

Feature Virtual Machine (VM) Docker Container
Operating System Own guest OS Shares kernel with host
Size Several GB A few MB
Startup Time Minutes Seconds
Resource Usage High Low
Isolation Complete (own OS) Process isolation

Key Docker Concepts

  1. Image: A template containing the application and all dependencies - immutable, read-only
  2. Container: A running instance of an image - the application actually executing
  3. Dockerfile: A text file with instructions for building an image
  4. Registry: An online repository for images (Docker Hub, GitHub Container Registry)
  5. Volume: Persistent data storage outside the container
  6. Network: A network connecting containers to each other

Dockerfile Example

The best way to understand Docker is through an example. Let's say we have a simple Node.js application:

# Dockerfile for Node.js application

# 1. Use the official Node.js image as base
FROM node:20-alpine

# 2. Set working directory inside the container
WORKDIR /app

# 3. Copy package.json and package-lock.json
COPY package*.json ./

# 4. Install dependencies
RUN npm install

# 5. Copy the rest of the application code
COPY . .

# 6. Set the default command to run
CMD ["node", "server.js"]

It's also very important to have a .dockerignore file in the directory, which prevents unnecessary files from being copied into the container:

# .dockerignore
node_modules
npm-debug.log
.git
.env
*.md

Basic Commands

Here's an overview of the most commonly used Docker commands:

Command Description Example
docker build Build an image from a Dockerfile docker build -t my-app .
docker run Run a container from an image docker run -p 3000:3000 my-app
docker ps List running containers docker ps -a
docker stop Stop a running container docker stop <container_id>
docker rm Remove a container docker rm <container_id>
docker images List local images docker images
docker logs View container logs docker logs <container_id>

Docker Compose

When an application grows and needs multiple services (e.g., app + database + cache), running individual containers becomes tedious. This is where Docker Compose comes in, allowing you to define all services in a single file:

# docker-compose.yml

version: "3.8"

services:
  app:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - database
    environment:
      - DB_HOST=database
      - DB_PORT=5432

  database:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret123
      - POSTGRES_DB=myapp

volumes:
  db_data:

Starting the entire environment is then simple:

# Start all services
docker compose up -d

# Stop and remove everything
docker compose down

# View logs
docker compose logs -f

Pros and Cons

Advantages Disadvantages
"Works on my machine" - and everywhere else Additional layer of complexity
Fast startup and shutdown (seconds) Learning curve for beginners
Consistent environment: development = production Data persistence requires extra planning (volumes)
Easy scaling and deployment Security considerations with kernel sharing
Rich ecosystem of images (Docker Hub) Limitations on Windows and macOS (requires WSL2/HyperKit)

Why Use Docker?

If you're a developer working on different projects with different technologies - Node.js, PHP, Python, Arduino SDK - Docker enables you to keep each environment separate and clean. No more conflicts between library versions, no more "it works on my machine".

For self-hosted servers and standalone projects, Docker is especially useful - instead of installing Node.js, PHP, PostgreSQL, and Nginx directly on the system, you can run each service in its own container. This means a clean system, easy updates, and security isolation between services.

Getting started is simple - install Docker, write your first Dockerfile, and run your application. Everything else comes with practice.

back Back to blog