🐳

Docker

13 notes  •  Containers & Orchestration

Docker Command Reference

Essential Docker commands for managing containers, images, networks, and volumes.

Key Concepts

  • docker run always creates a new container; docker start uses an existing stopped container.
  • You cannot remove a running container — stop it first, or use --force.
  • Containers communicate via their names as DNS, not IP addresses.

Container Management

# Run a container (host_port:container_port)
docker container run --publish 8081:80 --detach --name nginx8081 nginx

# Run with environment variables
docker container run -d   -e MARIADB_USER=db_user   -e MARIADB_PASSWORD=db_pass   -e MARIADB_DATABASE=frontend_app   -e MARIADB_ROOT_PASSWORD=mariadb_root_pass   --name my_backend mariadb:latest

# List running containers
docker container ls
docker ps

# List all containers (including stopped)
docker ps -a

# Stop and remove a container
docker container stop <name>
docker container rm <name>

# Force remove a running container
docker container rm -f <name>

# Execute a command inside a running container
docker exec -it <name> bash

# View container logs
docker logs -f <name>

# Inspect container details
docker inspect <name>

Image Management

# List local images
docker image ls

# Pull an image
docker pull nginx:alpine

# Build an image from a Dockerfile
docker build -t myapp:1.0 .

# Remove an image
docker image rm <image_id>

# Remove all unused images
docker image prune -a

Volume and Network

# Mount a host directory into a container
docker run -v /host/path:/container/path myimage

# List networks
docker network ls

# Create a custom bridge network
docker network create mynetwork

# Run container on custom network
docker run --network mynetwork --name app myimage

Docker Compose

# Start services in detached mode
docker-compose up -d

# Stop services
docker-compose down

# View logs
docker-compose logs -f

# Rebuild and restart
docker-compose up -d --build

System Cleanup

# Remove stopped containers, unused networks, dangling images, build cache
docker system prune

# Remove everything including volumes
docker system prune -a --volumes

Running Docker Containers via WSL on Windows

How to run Docker containers using the Windows Subsystem for Linux (WSL) on Windows 10/11.

Prerequisites

  • Windows 10 version 2004+ or Windows 11
  • WSL 2 installed and configured
  • Docker Desktop for Windows installed

Step 1 — Enable WSL 2

# In PowerShell (as Administrator)
wsl --install
wsl --set-default-version 2

Step 2 — Enable Docker WSL Integration

  1. Open Docker Desktop.
  2. Go to Settings → Resources → WSL Integration.
  3. Toggle on integration for your Linux distro (e.g., Ubuntu).
  4. Click Apply & Restart.

Step 3 — Verify Docker Access from WSL

# Open your WSL terminal and run:
docker version
docker run hello-world

Step 4 — Expose Docker Socket (Legacy WSL 1)

If using older WSL 1 without Docker Desktop integration, you can expose the Docker TCP socket:

# In Docker Desktop: Settings → General → Expose daemon on tcp://localhost:2375

# In WSL, set the DOCKER_HOST variable
export DOCKER_HOST=tcp://localhost:2375
echo 'export DOCKER_HOST=tcp://localhost:2375' >> ~/.bashrc

# Test
docker ps

Notes

  • WSL 2 is strongly preferred over WSL 1 — it provides a real Linux kernel.
  • File I/O is fastest when your project files are inside the WSL filesystem (/home/user/), not on the Windows mount (/mnt/c/).
  • Docker Desktop must be running for Docker commands to work in WSL.

Avoid tzdata Prompt in Docker Builds (Non-Interactive Install)

When building Docker images based on Ubuntu/Debian, installing certain packages (like certbot) triggers an interactive tzdata configuration prompt that hangs automated builds. Here is how to suppress it.

Solution — Set DEBIAN_FRONTEND and TZ

Add these environment variables to your Dockerfile before any apt-get install that pulls in tzdata:

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=UTC

RUN apt-get update && apt-get install -y \
    tzdata \
    certbot \
    && rm -rf /var/lib/apt/lists/*

Alternative — Pass ENV at Build Time

docker build --build-arg DEBIAN_FRONTEND=noninteractive -t myimage .

Alternative — Pre-configure tzdata with debconf

RUN echo "tzdata tzdata/Areas select Etc" | debconf-set-selections && \
    echo "tzdata tzdata/Zones/Etc select UTC" | debconf-set-selections && \
    apt-get install -y tzdata

Verify

# Build the image — it should complete without pausing for input
docker build -t myapp .

Notes

  • Set DEBIAN_FRONTEND=noninteractive only for the build stage. Do not set it as a persistent ENV in production images — it suppresses helpful prompts in interactive shells.
  • Adjust TZ to your required timezone (e.g., America/New_York, Asia/Kolkata).

Install Docker CE on Ubuntu 18.04 / 20.04 / 22.04

How to install Docker Community Edition on Ubuntu using the official Docker APT repository.

Prerequisites

  • Ubuntu 18.04, 20.04, or 22.04 (64-bit)
  • sudo or root access

Step 1 — Install Dependencies

sudo apt-get update
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

Step 2 — Add Docker GPG Key and Repository

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

sudo apt-get update

Step 3 — Install Docker CE

sudo apt-get install -y docker-ce

# Verify installation
sudo docker --version
sudo docker run hello-world

Step 4 — Run Docker Without sudo (Optional)

sudo usermod -aG docker $USER
# Log out and back in for this to take effect

Step 5 — Enable Docker on Boot

sudo systemctl enable docker
sudo systemctl start docker

Verify

docker info
docker ps

Fix Docker overlay2 'no such file or directory' Error

Docker can fail to start containers with an error referencing a missing path under /var/lib/docker/overlay2/. This indicates a corrupted storage layer.

Error Example

ERROR: stat /var/lib/docker/overlay2/feaf2aa314e4078.../: no such file or directory

Fix — Reset Docker Storage

Warning: This removes all containers, images, and volumes stored locally.

sudo systemctl stop docker
sudo rm -rf /var/lib/docker
sudo systemctl start docker

Verify Storage Driver

docker info | grep -i storage

If Backing Filesystem is blank or incorrect, the overlay2 driver may not be compatible with your filesystem.

Alternative Fix — Downgrade Docker

If the error persists after resetting storage, the current Docker version may be incompatible with your kernel. Install an earlier version:

# List available versions
apt-cache madison docker-ce

# Install a specific version
sudo apt-get install docker-ce=5:20.10.24~3-0~ubuntu-focal

sudo systemctl restart docker

Prevention

  • Use docker system prune regularly to clean dangling layers.
  • Avoid hard-killing the Docker daemon (kill -9) — always use systemctl stop docker.

Create a Docker Image from a Running Container

You can snapshot a running (or stopped) container's filesystem into a new Docker image using docker commit. This is useful for capturing changes made interactively inside a container.

Prerequisites

  • Docker installed and running
  • A container to snapshot

Step 1 — Start a Base Container

docker run -d --name nginx_base -p 80:80 nginx:alpine

Step 2 — Make Changes Inside the Container

docker exec -it nginx_base sh

# Inside the container, install something or modify files
apk add curl
exit

Step 3 — Commit the Container as an Image

docker commit nginx_base my-custom-nginx:1.0

Step 4 — Verify the New Image

docker image ls | grep my-custom-nginx

Step 5 — Run a Container from the New Image

docker run -d --name custom_nginx -p 8080:80 my-custom-nginx:1.0

Step 6 — (Optional) Push to a Registry

docker tag my-custom-nginx:1.0 yourdockerhubuser/my-custom-nginx:1.0
docker push yourdockerhubuser/my-custom-nginx:1.0

Notes

  • Prefer Dockerfiles for reproducible images. Use docker commit only for quick snapshots or debugging.
  • The committed image does not include data stored in mounted volumes.

Fix Docker Login Error with Private Registry (credential-helpers)

On Ubuntu 18.04 and some Debian releases, docker login may fail with a credential helper error caused by a broken golang-github-docker-docker-credential-helpers package dependency.

Error Example

Error saving credentials: error storing credentials - err: exit status 1, out: \`\`

Fix — Remove the Broken Credential Helper

sudo rm /usr/bin/docker-credential-secretservice

Then retry:

docker login registry.example.com

Permanent Fix — Configure Credentials Store

Edit (or create) ~/.docker/config.json to use the pass store or no helper:

{
  "credsStore": ""
}

Or install the pass-based helper:

sudo apt-get install pass
docker-credential-pass

Notes

  • The rm workaround must be re-applied after package updates that restore the broken binary.
  • This issue primarily affects Ubuntu 18.04 and some Debian 9/10 installations.

Host Multiple Websites on One VPS with Docker and Nginx Proxy

Use Docker and an Nginx reverse proxy container to host multiple websites on a single VPS, each in its own container.

Prerequisites

  • Docker and Docker Compose installed
  • A domain or subdomains pointing to the VPS IP

Step 1 — Create a Shared Docker Network

docker network create webproxy

Step 2 — Run the Nginx Proxy Container

Use jwilder/nginx-proxy which auto-configures virtual hosts via environment variables:

docker run -d --name nginx-proxy \
  -p 80:80 -p 443:443 \
  -v /var/run/docker.sock:/tmp/docker.sock:ro \
  --network webproxy \
  jwilder/nginx-proxy

Step 3 — Run Each Website Container

Set the VIRTUAL_HOST environment variable on each app container:

# Site 1
docker run -d --name site1 \
  -e VIRTUAL_HOST=site1.example.com \
  --network webproxy \
  my-site1-image

# Site 2
docker run -d --name site2 \
  -e VIRTUAL_HOST=site2.example.com \
  --network webproxy \
  my-site2-image

Step 4 — (Optional) Add SSL with Let's Encrypt

docker run -d --name letsencrypt \
  -e DEFAULT_EMAIL=admin@example.com \
  --volumes-from nginx-proxy \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  --network webproxy \
  jrcs/letsencrypt-nginx-proxy-companion

Then add to each site container:

-e LETSENCRYPT_HOST=site1.example.com \
-e LETSENCRYPT_EMAIL=admin@example.com

Step 5 — Verify

docker ps
curl -I http://site1.example.com

Notes

  • All app containers must be on the same webproxy network as the proxy container.
  • For Docker Compose setups, declare the external network in each docker-compose.yml.

Using Docker Utility Containers

Utility containers let you run commands on the host system without installing the required tools. The container provides the runtime environment; the results affect the host filesystem via volume mounts.

Concept

  • Run tools (Node, Python, Composer, etc.) inside a container.
  • Mount a host directory so the container's output lands on the host.
  • The host needs no additional software installed.

Example — Node.js Utility Container

Dockerfile

FROM node:18-alpine
WORKDIR /app
ENTRYPOINT ["node"]

Build the Image

docker build -t nodeutil .

Run Commands via the Container

# Run a script
docker run --rm -v $(pwd):/app nodeutil app.js

# Initialize a new Node project in the current directory
docker run -it --rm -v $(pwd):/app --entrypoint npm nodeutil init

Example — Composer (PHP) Utility Container

docker run --rm -v $(pwd):/app composer install

Example — Run Any Tool Without Installing It

# Run a Python script without Python installed on the host
docker run --rm -v $(pwd):/scripts python:3.11-alpine python /scripts/myscript.py

Notes

  • Always use --rm so the container is removed after it finishes.
  • Use -v $(pwd):/app to mount the current directory into the container's working directory.
  • Use --entrypoint to override the default entrypoint when you need to run a different binary (e.g., npm instead of node).

View Only access.log or error.log from an Nginx Docker Container

Nginx inside Docker writes access logs to stdout and error logs to stderr. The docker logs command captures both streams, but you can filter them separately.

View Only error.log (stderr)

docker logs -f nginx 2>&1 1>/dev/null

Or equivalently, redirect stdout to null:

docker logs -f nginx 1>/dev/null

View Only access.log (stdout)

docker logs -f nginx 2>/dev/null

View Both Streams (Default)

docker logs -f nginx

View Last N Lines

docker logs --tail 100 nginx

Notes

  • Stream 1 (stdout) = access log
  • Stream 2 (stderr) = error log
  • This works because the official Nginx Docker image symlinks /var/log/nginx/access.log to /dev/stdout and error.log to /dev/stderr.

Install Docker and Docker Compose on Ubuntu

How to install Docker Engine and Docker Compose plugin on Ubuntu 20.04 / 22.04 using the official Docker APT repository.

Step 1 — Update and Install Dependencies

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y git ca-certificates curl gnupg lsb-release

Step 2 — Add Docker's Official GPG Key

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Step 3 — Add the Docker Repository

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

Step 4 — Install Docker Engine and Compose

sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Step 5 — Verify Installation

docker --version
docker compose version
sudo docker run hello-world

Step 6 — Allow Running Docker Without sudo

sudo usermod -aG docker $USER
newgrp docker

Step 7 — Enable Docker on Boot

sudo systemctl enable docker
sudo systemctl enable containerd

Install Podman on Ubuntu

Podman is a daemonless, rootless container engine compatible with Docker commands. This guide covers installation on Ubuntu 18.04 / 20.04 / 22.04.

Prerequisites

  • Ubuntu 18.04 or later
  • sudo access

Step 1 — Install Podman (Ubuntu 20.10+)

sudo apt-get update
sudo apt-get install -y podman

Step 1 (Alternative) — Install on Ubuntu 18.04 / 20.04 via PPA

. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | \
  sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list

curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key" | \
  sudo apt-key add -

sudo apt-get update
sudo apt-get install -y podman

Step 2 — Verify Installation

podman --version
podman run hello-world

Step 3 — Use Docker-compatible Commands

Podman is CLI-compatible with Docker. You can alias Docker to Podman:

alias docker=podman
echo "alias docker=podman" >> ~/.bashrc

Key Differences from Docker

  • No central daemon — each container is a child process of the user.
  • Rootless by default — containers run without root privileges.
  • Compatible with Docker Compose via podman-compose.
# Install podman-compose
pip3 install podman-compose

podman-compose up -d

Docker Swarm Command Reference

Docker Swarm is Docker's native clustering and orchestration solution. Use it to deploy services across multiple Docker hosts.

Initialize and Join

# Initialize a new swarm on the manager node
docker swarm init --advertise-addr <MANAGER_IP>

# Get the worker join token
docker swarm join-token worker

# Join as a worker (run on worker node)
docker swarm join --token <TOKEN> <MANAGER_IP>:2377

# List nodes in the swarm
docker node ls

Service Management

# Create a service
docker service create --name web --publish 80:80 --replicas 3 nginx

# List services
docker service ls

# Show tasks (containers) for a service
docker service ps web

# Scale a service
docker service update web --replicas=5

# Update a service image
docker service update --image nginx:alpine web

# Remove a service
docker service rm web

Stack Deployment (Compose in Swarm)

# Deploy a stack from a Compose file
docker stack deploy -c docker-compose.yml mystack

# List stacks
docker stack ls

# List services in a stack
docker stack services mystack

# Remove a stack
docker stack rm mystack

Swarm Information

# View swarm status and node info
docker info | grep -A5 Swarm

# Inspect a node
docker node inspect <node_id> --pretty

# Drain a node (move workloads away before maintenance)
docker node update --availability drain <node_id>

# Re-activate a node after maintenance
docker node update --availability active <node_id>

Leaving the Swarm

# On a worker node
docker swarm leave

# On the manager (force)
docker swarm leave --force