Core Concepts
Understanding Docker's core concepts is essential for working effectively with containerized applications. This guide covers the fundamental building blocks: Images, Containers, Registries, and Dockerfiles.
Images
A Docker image is a read-only template that contains a set of instructions for creating a container. An image typically includes an operating system, application code, runtime, libraries, environment variables, and configuration files.
Image Layers
Docker images are built in layers. Each instruction in a Dockerfile creates a new layer:
┌─────────────────────────────┐
│ Application Code │ ← Layer 4 (COPY)
├─────────────────────────────┤
│ Dependencies (npm, pip) │ ← Layer 3 (RUN)
├─────────────────────────────┤
│ Runtime (Node, Python) │ ← Layer 2 (RUN)
├─────────────────────────────┤
│ Base OS (Alpine, Ubuntu) │ ← Layer 1 (FROM)
└─────────────────────────────┘Each layer is cached independently. When you rebuild an image, only the layers that have changed (and subsequent layers) are rebuilt.
Image Tags
Images are referenced using a tag system:
# Format: registry/repository:tag
docker.io/library/nginx:1.25
docker.io/myuser/myapp:latest
docker.io/myuser/myapp:v2.1.0
# Short forms
nginx:1.25 # defaults to docker.io/library/
myapp:latest # defaults to docker.io/library/
myapp # defaults to :latest tagListing and Managing Images
# List all local images
docker images
docker image ls
# Pull an image from a registry
docker pull nginx:1.25
# Remove an image
docker rmi nginx:1.25
docker image rm nginx:1.25
# Remove unused images
docker image prune
# Inspect image details
docker image inspect nginx:1.25
# View image history (layers)
docker image history nginx:1.25Image Tag Table
| Tag Pattern | Example | Use Case |
|---|---|---|
latest | nginx:latest | Default tag, mutable |
| Semantic version | nginx:1.25.3 | Specific immutable version |
| Major version | nginx:1 | Latest patch of major version |
| SHA digest | nginx@sha256:abc123... | Guaranteed immutability |
| Custom label | myapp:staging | Environment-specific build |
Containers
A container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI. A container is defined by its image as well as any configuration options you provide when you create or start it.
Container Lifecycle
create start (running) stop remove
─────────▶ ┌──────────▶ ┌─────────────┐ ──────────▶ ┌──────────▶
│ Created │ Running │ Stopped │ Removed
└───────────┘ └─────────────┘
│ ▲
pause│ │unpause
▼ │
┌─────────────┐
│ Paused │
└─────────────┘Basic Container Operations
# Run a container (create + start)
docker run nginx:1.25
# Run in detached mode (background)
docker run -d --name my-nginx nginx:1.25
# Run with port mapping
docker run -d -p 8080:80 nginx:1.25
# Run with environment variables
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql:8
# Run interactively with a shell
docker run -it ubuntu:22.04 /bin/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
# Force remove a running container
docker rm -f my-nginx
# View container logs
docker logs my-nginx
docker logs -f my-nginx # follow log output
# Execute a command in a running container
docker exec -it my-nginx /bin/bash
# Inspect container details
docker inspect my-nginx
# View container resource usage
docker statsContainer Resource Limits
# Limit memory
docker run -d --memory="512m" nginx
# Limit CPU
docker run -d --cpus="1.5" nginx
# Limit both
docker run -d --memory="512m" --cpus="1.5" nginx
# Set restart policy
docker run -d --restart=unless-stopped nginxRestart Policies
| Policy | Description |
|---|---|
no | Do not automatically restart (default) |
on-failure | Restart only if container exits with non-zero code |
on-failure:N | Restart up to N times on failure |
always | Always restart regardless of exit code |
unless-stopped | Always restart unless explicitly stopped |
Registries
A Docker registry is a storage and distribution system for Docker images. The most commonly used registry is Docker Hub, but you can also run your own private registry.
Working with Registries
# Log in to Docker Hub
docker login
# Log in to a private registry
docker login registry.example.com
# Push an image to a registry
docker tag myapp:latest myuser/myapp:v1.0
docker push myuser/myapp:v1.0
# Pull an image from a registry
docker pull myuser/myapp:v1.0
# Search for images
docker search nginxPopular Container Registries
| Registry | URL | Description |
|---|---|---|
| Docker Hub | hub.docker.com | Default public registry |
| GitHub Container Registry | ghcr.io | GitHub's container registry |
| Amazon ECR | *.dkr.ecr.*.amazonaws.com | AWS container registry |
| Google Artifact Registry | *.pkg.dev | GCP container registry |
| Azure Container Registry | *.azurecr.io | Azure container registry |
| Harbor | Self-hosted | Open-source private registry |
Dockerfile
A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build, users can create an automated build that executes several command-line instructions in succession.
Basic Dockerfile Example
# Use an official Node.js runtime as the base image
FROM node:20-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy package files first (for better layer caching)
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci --only=production
# Copy the rest of the application code
COPY . .
# Expose the application port
EXPOSE 3000
# Define the command to run the application
CMD ["node", "server.js"]Common Dockerfile Instructions
| Instruction | Description | Example |
|---|---|---|
FROM | Sets the base image | FROM node:20-alpine |
WORKDIR | Sets the working directory | WORKDIR /app |
COPY | Copies files from host to image | COPY . . |
ADD | Copies files with extra features (tar extraction, URLs) | ADD archive.tar.gz /app |
RUN | Executes a command during build | RUN npm install |
CMD | Default command when container starts | CMD ["node", "app.js"] |
ENTRYPOINT | Configures the container as an executable | ENTRYPOINT ["python"] |
ENV | Sets environment variables | ENV NODE_ENV=production |
EXPOSE | Documents the port the container listens on | EXPOSE 8080 |
VOLUME | Creates a mount point | VOLUME /data |
ARG | Defines a build-time variable | ARG VERSION=1.0 |
LABEL | Adds metadata to the image | LABEL maintainer="dev@example.com" |
USER | Sets the user for subsequent instructions | USER appuser |
HEALTHCHECK | Defines a health check command | HEALTHCHECK CMD curl -f http://localhost/ |
Building an Image from a Dockerfile
# Build an image from the current directory
docker build -t myapp:1.0 .
# Build with a specific Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
# Build with build arguments
docker build --build-arg VERSION=2.0 -t myapp:2.0 .
# Build with no cache
docker build --no-cache -t myapp:1.0 .
# Build for a specific platform
docker build --platform linux/amd64 -t myapp:1.0 .Putting It All Together
Here is a complete workflow that uses all the core concepts:
# 1. Write a Dockerfile (defines the image)
# 2. Build the image
docker build -t myuser/myapp:1.0 .
# 3. Test locally by running a container
docker run -d -p 8080:3000 --name test-app myuser/myapp:1.0
# 4. Verify it works
curl http://localhost:8080
# 5. Push the image to a registry
docker login
docker push myuser/myapp:1.0
# 6. On another machine, pull and run
docker pull myuser/myapp:1.0
docker run -d -p 80:3000 myuser/myapp:1.0Next Steps
- Installation Guide — Install Docker on your platform
- Quick Start Tutorial — Build and run your first container
- Image Building Best Practices — Learn advanced image building techniques
- Dockerfile Reference — Complete Dockerfile instruction reference
- Docker Networking Guide — Understand container networking