_____ _ ___ _________ __ |_ _|__ _ __ _ __ ___ (_)_ __ __ _| \ \ / / ____\ \/ / | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | |\ \ / /| _| \ / | | __/ | | | | | | | | | | | (_| | | \ V / | |___ / \ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_| \_/ |_____/_/\_\
Docker is an open-source platform that allows you to package, distribute, and run applications in isolated environments called containers. Developed by Solomon Hykes in 2013, it quickly became one of the standard tools in the software world. With Docker, the "it works on my machine" problem disappears because the application is packaged with all its dependencies and runs the same way in every environment.
Unlike virtual machines, containers do not carry their own operating system kernel. Instead, they share the host machine's kernel and contain only the files and libraries necessary for the application to run. This enables containers to start in seconds, consume very few resources, and allow hundreds of containers to run in parallel on the same machine.
Containers and virtual machines (VMs) are different virtualization approaches:
Containers stand out for their lightness and speed, while VMs are preferred in scenarios requiring full isolation. In modern architectures, containers are mostly used because they align perfectly with the microservice approach.
# Check if Docker is installed
$ docker --version
# Verify Docker service is running
$ docker info
# First test — Hello World container
$ docker run hello-world
A Docker image is a read-only template containing all the files, libraries, and configuration needed for a container to run. Containers are created from these images.
# List local images
$ docker images
# Filter a specific image
$ docker images nginx
# Show image sizes
$ docker images --format "table {{.Repository}} {{.Tag}} {{.Size}}"
# Pull an image from Docker Hub
$ docker pull nginx
# Pull a specific version
$ docker pull node:18-alpine
# Pull from a specific registry
$ docker pull ghcr.io/user/app:latest
# Remove an image
$ docker rmi nginx
# Force remove
$ docker rmi -f old-image
# Clean all unused images
$ docker image prune -a
docker run creates a new container from an image and starts it. It is Docker's most fundamental and frequently used command.
# Run a simple container
$ docker run nginx
# Run in the background (-d: detached)
$ docker run -d nginx
# Run with a name
$ docker run -d --name my-web-server nginx
# Port mapping (-p host:container)
$ docker run -d -p 8080:80 --name web nginx
# Accessible at http://localhost:8080 in browser
# Interactive mode (-it: interactive terminal)
$ docker run -it ubuntu bash
# Auto-remove (container deleted when stopped)
$ docker run --rm -it alpine sh
# Set environment variable
$ docker run -d -e MYSQL_ROOT_PASSWORD=pass123 mysql:8
# Multiple options combined
$ docker run -d --name database -p 3306:3306 -e MYSQL_ROOT_PASSWORD=strong_password -e MYSQL_DATABASE=myapp -v mysql-data:/var/lib/mysql mysql:8
# List running containers
$ docker ps
# List all containers (including stopped)
$ docker ps -a
# List only container IDs
$ docker ps -q
# Custom format listing
$ docker ps --format "table {{.Names}} {{.Status}} {{.Ports}}"
# Stop a container
$ docker stop my-web-server
# Start a container
$ docker start my-web-server
# Restart a container
$ docker restart my-web-server
# Connect to a running container
$ docker exec -it my-web-server bash
# View container logs
$ docker logs my-web-server
# Follow logs in real-time
$ docker logs -f my-web-server
# Inspect container details
$ docker inspect my-web-server
# Remove a container (must be stopped first)
$ docker stop my-web-server
$ docker rm my-web-server
# Force remove (even while running)
$ docker rm -f my-web-server
# Clean all stopped containers
$ docker container prune
A Dockerfile is a text file used to create your own custom Docker images. Each line creates a layer and defines how the image should be built.
# Dockerfile for a simple Node.js application
# Filename: Dockerfile
# Base image
FROM node:18-alpine
# Working directory
WORKDIR /app
# Copy dependency files
COPY package*.json ./
# Install dependencies
RUN npm install --production
# Copy application files
COPY . .
# Port the application listens on
EXPOSE 3000
# Application start command
CMD ["node", "server.js"]
# Build an image from Dockerfile in current directory
$ docker build -t myapp:v1 .
# Specify a different Dockerfile
$ docker build -f Dockerfile.prod -t myapp:prod .
# Build with build arguments
$ docker build --build-arg NODE_ENV=production -t myapp:prod .
# Run the built image
$ docker run -d -p 3000:3000 myapp:v1
Containers are ephemeral by default; when a container is deleted, the data inside it is also lost. Volumes enable data to be stored persistently, independent of the container lifecycle.
# Create a named volume
$ docker volume create data-store
# List volumes
$ docker volume ls
# Run a container with a volume
$ docker run -d --name database -v data-store:/var/lib/mysql mysql:8
# Bind mount a host directory
$ docker run -d --name web -v $(pwd)/site:/usr/share/nginx/html -p 8080:80 nginx
# Inspect volume details
$ docker volume inspect data-store
# Clean unused volumes
$ docker volume prune
# List networks
$ docker network ls
# Create a custom network
$ docker network create app-network
# Connect a container to a specific network
$ docker run -d --name web --network app-network nginx
$ docker run -d --name api --network app-network node:18
# Containers on the same network can find each other by name
# From web container to api: curl http://api:3000
# Inspect network details
$ docker network inspect app-network
Docker Compose allows you to define and manage multiple containers with a single YAML file. It is ideal for multi-container applications.
# docker-compose.yml example
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./site:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
ports:
- "3000:3000"
environment:
- DB_HOST=database
- DB_PASSWORD=pass123
depends_on:
- database
database:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=pass123
- MYSQL_DATABASE=myapp
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
# Start all services
$ docker compose up -d
# View logs
$ docker compose logs -f
# Stop services
$ docker compose down
# Stop services and remove volumes
$ docker compose down -v
# Restart a specific service
$ docker compose restart api
# View service status
$ docker compose ps
# View system-wide disk usage
$ docker system df
# Clean all unused resources
$ docker system prune -a
# Copy file from container
$ docker cp my-web-server:/etc/nginx/nginx.conf ./nginx.conf
# Copy file to container
$ docker cp ./index.html my-web-server:/usr/share/nginx/html/
# Monitor container resource usage
$ docker stats
Docker is an indispensable tool for modern software development and deployment processes. Thanks to container technology, you can run your applications in isolated, portable, and reproducible environments. Creating containers with docker run, building custom images with docker build, managing persistent data with volumes, and orchestrating multi-container applications with Docker Compose — once you learn these fundamental concepts, you can begin leveraging the vast possibilities the container world offers. Your Docker knowledge will be your greatest advantage in advanced topics such as microservice architecture, CI/CD pipelines, and cloud deployments.