Docker Basics for Beginners: Containers, Images, and Commands Explained
Docker has become a must-know tool for developers, DevOps engineers, and anyone working in modern software. If you have been putting off learning Docker because it seems complicated β this guide will change that.
We will cover everything from the core concepts to real commands you will use every day.
Why Docker?
Before Docker, deploying software meant dealing with the classic problem: "It works on my machine." Different operating systems, library versions, and environment configs caused endless headaches.
Docker solves this by packaging your application and everything it needs β runtime, libraries, config β into a single portable unit called a container.
The key promise: If it runs in Docker on your laptop, it runs the same way in production.
Containers vs Virtual Machines
A common misconception is that containers are just lightweight VMs. They are different in a fundamental way:
| Virtual Machine | Docker Container | |
|---|---|---|
| Includes | Full OS + app | App + dependencies only |
| Startup time | Minutes | Seconds |
| Size | GBs | MBs |
| Isolation | Full hardware | Process-level |
| Performance | Overhead | Near-native |
VMs virtualize hardware. Containers virtualize the operating system. Containers share the host OS kernel, which makes them much faster and lighter.
Core Concepts
Images
A Docker image is a read-only blueprint for creating containers. Think of it like a class in object-oriented programming.
Images are built in layers. Each instruction in a Dockerfile adds a layer. Layers are cached, so rebuilds are fast when only your code changes.
Containers
A container is a running instance of an image β like an object instantiated from a class. You can run many containers from the same image simultaneously.
Containers are:
- Isolated β they cannot see each other's processes by default
- Ephemeral β stopping a container does not save changes (unless you use volumes)
- Lightweight β start in milliseconds
Registry
A registry is where images are stored and shared. Docker Hub is the default public registry. Companies often run private registries (AWS ECR, GitHub Container Registry, etc.).
Essential Docker Commands
Working with images
bash# Pull an image from Docker Hub docker pull nginx # List downloaded images docker images # Remove an image docker rmi nginx # Search Docker Hub docker search postgres
Running containers
bash# Run a container (downloads image if not local) docker run nginx # Run in detached mode (background) docker run -d nginx # Run with a name docker run -d --name my-nginx nginx # Run with port mapping (host:container) docker run -d -p 8080:80 nginx # Run interactively with a shell docker run -it ubuntu bash # Run and remove container when it exits docker run --rm ubuntu echo "hello"
Managing containers
bash# List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-nginx # Start a stopped container docker start my-nginx # Remove a container docker rm my-nginx # View logs docker logs my-nginx # Follow logs in real time docker logs -f my-nginx # Execute a command in a running container docker exec -it my-nginx bash
Cleanup
bash# Remove all stopped containers docker container prune # Remove unused images docker image prune # Remove everything unused docker system prune
Writing a Dockerfile
A Dockerfile is a text file with instructions to build a custom image. Here is a real-world example for a Node.js app:
dockerfile# Start from official Node image FROM node:20-alpine # Set working directory inside container WORKDIR /app # Copy package files first (layer caching optimization) COPY package*.json ./ # Install dependencies RUN npm ci --only=production # Copy the rest of the source code COPY . . # Expose the port the app listens on EXPOSE 3000 # Command to run when container starts CMD ["node", "server.js"]
Build and run your image
bash# Build image from Dockerfile in current directory docker build -t my-app:1.0 . # Run your custom image docker run -d -p 3000:3000 my-app:1.0
Dockerfile best practices
- Use specific base image tags β
node:20-alpinenotnode:latest - Copy package files before source code β maximizes layer cache hits
- Use
.dockerignoreβ excludenode_modules,.git, logs from the build context - Use multi-stage builds β keep production images small
dockerfile# Multi-stage build example FROM node:20-alpine AS builder WORKDIR /app COPY . . RUN npm ci && npm run build FROM node:20-alpine AS production WORKDIR /app COPY /app/dist ./dist COPY package*.json ./ RUN npm ci --only=production CMD ["node", "dist/server.js"]
Volumes: Persisting Data
By default, data inside a container disappears when the container is removed. Volumes solve this.
bash# Create a named volume docker volume create my-data # Mount a volume when running a container docker run -d \ -v my-data:/var/lib/postgresql/data \ postgres:16 # Bind mount β great for development docker run -d \ -v $(pwd):/app \ -p 3000:3000 \ my-app
Docker Compose
Managing multiple containers (app + database + cache) manually gets messy fast. Docker Compose lets you define your entire stack in one YAML file.
yamlservices: app: build: . ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16 environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - postgres-data:/var/lib/postgresql/data volumes: postgres-data:
bash# Start all services docker compose up -d # Stop all services docker compose down # View logs for all services docker compose logs -f # Rebuild and restart docker compose up -d --build
Common Docker Interview Questions
Q: What is the difference between CMD and ENTRYPOINT?
CMDprovides default arguments that can be overridden at runtimeENTRYPOINTsets the executable that always runs; CMD provides default args to it
Q: How do containers communicate with each other?
Via Docker networks. Containers on the same network can reach each other by service name. By default, containers are isolated from one another.
Q: What is a dangling image?
An image with no tag, usually left over after rebuilding. Find and remove them with docker image prune.
Q: What is the difference between COPY and ADD in a Dockerfile?
COPY copies files from the build context. ADD does the same but also supports URLs and automatically extracts .tar archives. Prefer COPY unless you specifically need the extra features.
Practice Docker on Froquiz
Knowing Docker concepts is one thing β being tested on them is another. Try our Docker quiz on Froquiz to check your understanding across beginner, intermediate, and advanced levels.
Summary
- Images are blueprints; containers are running instances
- Containers are faster and lighter than VMs
docker run,docker ps,docker logs,docker execare your daily commands- Dockerfile defines how to build a custom image
- Volumes persist data beyond a container's lifecycle
- Docker Compose orchestrates multi-container applications
Docker is one of those tools that feels abstract until you start using it β then you cannot imagine working without it.