Docker for People Who Just Want It to Work

Docker tutorials love to explain Linux namespaces, cgroups, and container internals.

You don't care about that. You just want your application to run the same way everywhere—on your machine, on your colleague's machine, in production.

Here's Docker for people who want to use it, not understand its implementation.

The Core Idea

Without Docker: "Works on my machine" is a problem. Different operating systems, different versions of dependencies, different configurations. Getting the same environment everywhere is painful.

With Docker: You describe your environment in a file. Docker builds that environment into a container. The container runs identically everywhere Docker runs.

That's it. That's the value proposition.

The Basic Vocabulary

Image: A snapshot of an environment—operating system, dependencies, your code, configuration. Like a VM template, but lighter.

Container: A running instance of an image. Like a VM, but it shares the host's kernel so it's faster and smaller.

Dockerfile: A text file describing how to build an image. Recipe for your environment.

Registry: Where images are stored and shared. Docker Hub is the default public one.

Your First Dockerfile

Let's say you have a Node.js application.

# Start from an official Node image
FROM node:18

# Set working directory inside the container
WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm install

# Copy the rest of your code
COPY . .

# Tell Docker what command to run
CMD ["npm", "start"]

That's a complete Dockerfile. Each line does something:

  • FROM node:18 - Start with an image that has Node 18 installed
  • WORKDIR /app - Work in the /app directory
  • COPY package*.json ./ - Copy package files first
  • RUN npm install - Install dependencies
  • COPY . . - Copy everything else
  • CMD ["npm", "start"] - Run this when the container starts

Building and Running

Build an image from your Dockerfile:

docker build -t myapp .

-t myapp names the image "myapp". The . means "use the Dockerfile in this directory."

Run a container from that image:

docker run myapp

Your app is now running in a container.

Useful Run Options

Port Mapping

Your app listens on port 3000 inside the container. To access it from outside:

docker run -p 8080:3000 myapp

Now localhost:8080 on your machine reaches port 3000 in the container.

Environment Variables

docker run -e DATABASE_URL=postgres://... myapp

Pass configuration without baking it into the image.

Interactive Mode

docker run -it myapp bash

Drop into a shell inside the container. Useful for debugging.

Detached Mode

docker run -d myapp

Run in the background. Get your terminal back.

Naming Containers

docker run --name my-container myapp

Easier to reference than random IDs.

Managing Containers

See running containers:

docker ps

See all containers (including stopped):

docker ps -a

Stop a container:

docker stop my-container

Remove a container:

docker rm my-container

View logs:

docker logs my-container

Managing Images

See images you have locally:

docker images

Remove an image:

docker rmi myapp

Pull an image from a registry:

docker pull postgres:14

Docker Compose: Multiple Containers

Real applications have multiple services—app, database, cache.

Docker Compose lets you define all of them in one file.

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://postgres:password@db:5432/myapp
    depends_on:
      - db

  db:
    image: postgres:14
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Start everything:

docker-compose up

Stop everything:

docker-compose down

That's it—your entire application stack from one command.

Volumes: Persisting Data

Containers are ephemeral. When they stop, changes inside them are lost.

Volumes let data persist:

docker run -v my-data:/app/data myapp

my-data is a named volume. It persists even when containers stop.

For development, mount your local code:

docker run -v $(pwd):/app myapp

Changes to your local files appear inside the container.

Common Patterns

Development Environment

services:
  app:
    build: .
    volumes:
      - .:/app  # Mount local code
      - /app/node_modules  # But don't overwrite node_modules
    ports:
      - "3000:3000"
    command: npm run dev  # Override CMD for development

Local code changes reflect immediately. No rebuild needed.

Production Build

# Multi-stage build
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

First stage builds. Second stage has only what's needed to run. Smaller image.

Database for Local Development

services:
  db:
    image: postgres:14
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=localdev
    volumes:
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql  # Run on first start

Spin up a database without installing Postgres locally.

Troubleshooting

"Cannot connect to Docker daemon"

Docker Desktop isn't running. Start it.

Build is slow

Docker caches layers. Order Dockerfile commands from least to most frequently changing. Dependencies before code.

Container exits immediately

Check logs: docker logs container-name. Usually a startup error.

"Port already in use"

Something else is using that port. Change the external port: -p 8081:3000.

Changes not appearing

If using volumes, make sure paths are correct. If not using volumes, you need to rebuild the image.

The 80/20

80% of Docker usage is:

  1. Write a Dockerfile
  2. Build an image
  3. Run containers
  4. Use Docker Compose for multiple services
  5. Use volumes for persistence and development

That's enough for most developers. The advanced stuff is there when you need it.

FAQ

Q: Do I need Docker for development?

A: No, but it helps. Consistent environments, easy database setup, and "it works in the container" saves debugging time.

Q: Docker vs VMs?

A: Containers share the host kernel, so they're lighter and faster. VMs are fully isolated. For most development and deployment, containers are sufficient.

Q: Should I learn Kubernetes?

A: Not until you need it. Docker Compose handles most multi-container scenarios. Kubernetes is for orchestrating many containers at scale.

What Docker patterns have helped you most? Share your tips.

docker #devops #containers #programming #development

Read more and discuss: https://professionalsite.me/track?article=docker-for-people-who-just-want-it-to-work&source=reddit

Questions or want a deeper breakdown? Reply here!

This article was refined with the help of AI tools to improve clarity and readability.

Posted Feb 27, 2026, 12:01 PM UTC

10
Loading comments…