Docker Basics: The Daily Commands

Docker is the most popular container runtime — it wraps Linux’s namespaces and cgroups behind a friendly CLI and an image format that makes it trivial to package an app with all its dependencies and run it anywhere. This is the practical “what to type” guide.

Install

# Debian/Ubuntu (recommended: official repo, not distro version)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# log out and back in for group change

# Verify
docker run hello-world

The core concepts

  • Image — a read-only template (e.g. nginx:latest).
  • Container — a running instance of an image.
  • Volume — persistent storage, lives outside the container.
  • Network — virtual network for containers to talk to each other.
  • Registry — where images live (Docker Hub by default).

Run containers

# Run a one-off command
docker run --rm -it ubuntu:24.04 bash         # interactive shell
docker run --rm alpine echo "hello"            # run + print + exit

# Run as a long-lived service
docker run -d --name web -p 8080:80 nginx     # detached, port forwarded
docker run -d --name db -e POSTGRES_PASSWORD=secret postgres

# Common run flags
-d         detached (background)
-it        interactive + tty (for shells)
--rm       delete container when it exits
-p H:C     map host port H to container port C
-v PATH:PATH    bind mount a host directory
--name X   give container a name
-e KEY=val set env var
--network N attach to network N
--restart=always   restart on failure or boot

Inspect what’s running

docker ps                    # running containers
docker ps -a                  # also show stopped ones
docker logs web               # see container output
docker logs -f web            # follow logs
docker exec -it web bash      # shell into a running container
docker inspect web            # full JSON details
docker stats                  # live resource usage
docker top web                # processes in container

Stop, start, remove

docker stop web               # graceful (SIGTERM)
docker kill web               # immediate (SIGKILL)
docker start web              # start a stopped container
docker restart web
docker rm web                 # remove (must be stopped)
docker rm -f web              # stop + remove

# Bulk cleanup
docker container prune        # remove all stopped containers
docker rm $(docker ps -aq)    # remove ALL containers (after stopping)

Images

docker images                 # list local images
docker pull nginx:1.25        # download specific tag
docker rmi nginx:1.25         # remove image
docker image prune            # remove unused images
docker image prune -a         # remove ALL unused images
docker history nginx          # show image layers

Volumes (persistent data)

# Bind mount (host path → container path)
docker run -v /host/data:/var/data myapp

# Named volume (docker-managed)
docker volume create mydata
docker run -v mydata:/var/data myapp
docker volume ls
docker volume inspect mydata
docker volume prune           # remove unused

# Read-only mount
docker run -v /host/conf:/etc/myapp:ro myapp

Networks

docker network ls
docker network create mynet
docker run -d --network=mynet --name=db postgres
docker run -d --network=mynet --name=app myapp     # can reach 'db' by name

# Default network: 'bridge'
docker network inspect bridge

Build your own image

Create a Dockerfile:

# Dockerfile
FROM python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

EXPOSE 8000
CMD ["python", "app.py"]

Build and run:

docker build -t myapp:1.0 .
docker run -d -p 8000:8000 --name myapp myapp:1.0

docker compose (multi-container apps)

Define everything in one YAML file:

# compose.yaml
services:
  web:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:

Start everything:

docker compose up -d         # start in background
docker compose logs -f       # follow logs
docker compose ps             # status
docker compose down          # stop and remove everything
docker compose down -v       # also remove volumes

Daily one-liners

# Quick disposable test environment
docker run --rm -it python:3.12 python

# Run a command using a tool you don't have installed
docker run --rm -v $(pwd):/work -w /work node:20 npm install

# Throwaway database for testing
docker run --rm -d -p 5432:5432 -e POSTGRES_PASSWORD=test postgres

# Reverse shell into a misbehaving container
docker exec -it web bash || docker exec -it web sh

# Total disk used by Docker
docker system df
docker system prune -a       # clean EVERYTHING unused

Production tips

  • Pin image versions (nginx:1.25.3, not nginx:latest).
  • Use --restart=always or run via systemd.
  • Set resource limits: --memory=512m --cpus=1.
  • Run as non-root inside containers (set USER in Dockerfile).
  • Use named volumes for stateful data; never rely on container filesystem to persist.
  • Use multi-stage builds to keep images small.

Common mistakes

  • Storing data in the container filesystem — gone when container is removed.
  • Running as root inside the container by default.
  • Using :latest in production — non-deterministic.
  • Not setting memory limits — one container can eat the whole host.
  • Mounting /var/run/docker.sock into a container = root on the host.

What to learn next

You’ve reached the end of this roadmap. Where to go from here:

  • Kubernetes if you want container orchestration.
  • Cloud Linux — apply this knowledge on AWS, GCP, or DigitalOcean.
  • Specialize — go deep on networking, security, or DevOps tooling.

The fundamentals you now have transfer everywhere Linux runs — which is most of the modern world.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *