
Photo by Ferenc Almasi on Unsplash
From installing the daemon to running secure, production‑ready containers
Introduction
Containerization has become the de facto standard for packaging applications on modern infrastructure. Whether you’re a hobbyist deploying a personal blog or an enterprise architect orchestrating microservices across hundreds of nodes, Docker gives you a lightweight runtime that sits on top of the Linux kernel and abstracts away differences between host systems.
In 2026 Docker remains the most widely adopted container engine—its community, tooling, and ecosystem have matured to the point where a single “Dockerfile” can be built once and run anywhere: from an Ubuntu laptop to a Kubernetes cluster in the cloud. Yet many newcomers still feel daunted by the sheer number of commands, concepts, and best‑practice guidelines that surround it.
This article is written for developers, system administrators, and DevOps engineers who already have a working knowledge of Linux but are looking to get hands‑on with Docker on their local machine or in a production environment. We’ll cover:
- Why Docker matters – the value proposition and use cases.
- Getting started on Linux – installation, first image, and basic commands.
- Core concepts – images, containers, volumes, networks, and layers.
- Lifecycle management – building, running, stopping, and cleaning up.
- Best practices & security – how to keep your containers safe and efficient.
By the end of this guide you should be comfortable creating a simple Dockerfile, running services in isolated containers, and applying basic security hardening techniques on Linux.
1. Why Docker? The Value Proposition
| Feature | Benefit |
|---|---|
| Consistency | Same image runs identically across development, staging, and production. |
| Isolation | Processes run in separate namespaces; no interference between services. |
| Resource efficiency | Containers share the host kernel, consuming far less memory than VMs. |
| Rapid deployment | Pull an image from a registry and start a service in seconds. |
| Scalability | Container orchestration (Kubernetes, Docker Swarm) can spin up hundreds of replicas automatically. |
These advantages make Docker indispensable for:
- Microservices architectures, where each component is packaged independently.
- Continuous integration / continuous deployment (CI/CD) pipelines that need reproducible environments.
- Testing—spinning up test databases or mock services on demand.
- Infrastructure as code—defining entire stack in declarative files (
docker-compose.yml).
2. Getting Docker on Linux
2.1 Prerequisites
- A recent Linux distribution (Ubuntu 22.04+, Debian 11+, Fedora 36+).
sudoprivileges or root access.- At least 4 GB of RAM for a comfortable experience.
2.2 Installing the Engine
On Ubuntu/Debian:
# Update package list
sudo apt update
# Install prerequisites
sudo apt install ca-certificates curl gnupg lsb-release
# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Set up the stable repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
On Fedora/CentOS:
sudo dnf -y remove podman-docker
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io
2.3 Verify Installation
docker --version # e.g., Docker version 26.1.0, build …
docker run hello-world # Pulls a test image and prints a confirmation message
If you see the “Hello from Docker!” output, the engine is up and running.
2.4 Managing the Service
sudo systemctl start docker # Start Docker daemon
sudo systemctl enable docker # Enable on boot
sudo systemctl status docker # Check health
Add your user to the docker group to run commands without sudo:
sudo usermod -aG docker $USER
newgrp docker # or log out / back in
3. Core Docker Concepts
Understanding these building blocks will help you design cleaner images and avoid common pitfalls.
3.1 Images vs Containers
| Term | Definition |
|---|---|
| Image | Immutable snapshot of a filesystem with metadata (layer stack, labels). Think of it as a blueprint. |
| Container | Running instance of an image. It has its own PID namespace, network interface, and writable layer on top of the image layers. |
Images are stored in registries (docker.io, ghcr.io, private registries). Containers live only while they’re running.
3.2 Layers & Build Cache
- Each instruction in a Dockerfile (e.g.,
RUN,COPY) creates a new layer. - Docker re‑uses layers from the cache when possible, speeding up builds.
- Keep layers small and order instructions thoughtfully: put commands that change less often first.
3.3 Volumes & Bind Mounts
| Type | Use Case |
|---|---|
Volumes (docker volume create) |
Persistent data stored outside container filesystem; ideal for databases, logs. |
Bind mounts (-v /host/path:/container/path) |
Direct mapping of a host directory into the container; useful for development hot‑reloading. |
3.4 Networks
Docker creates a default bridge network on installation. Containers can also join user‑defined bridge networks or use overlay networks in Swarm/Kubernetes.
docker network create mynet
docker run -d --network=mynet nginx
4. Building and Running Your First Container
4.1 A Minimal Dockerfile
Create a directory hello-docker and add Dockerfile:
# Use an official lightweight base image
FROM alpine:3.20
# Install curl for demonstration
RUN apk add --no-cache curl
# Set working directory
WORKDIR /app
# Copy a simple script
COPY hello.sh .
# Make it executable
RUN chmod +x hello.sh
# Default command
CMD ["./hello.sh"]
Add hello.sh:
#!/bin/sh
echo "Hello from inside a Docker container!"
curl -s https://worldtimeapi.org/api/timezone/Etc/UTC | jq .datetime
4.2 Build the Image
docker build -t hello-docker:latest .
You should see progress logs and final image ID.
4.3 Run It
docker run --rm hello-docker
The --rm flag cleans up the container after it exits. You’ll see a greeting followed by the current UTC time fetched via curl.
5. Managing Container Lifecycle
| Action | Command | Notes |
|---|---|---|
| List running containers | docker ps |
Add -a to show all, including stopped. |
| Stop a container | docker stop <id> |
Graceful shutdown; sends SIGTERM then SIGKILL after timeout. |
| Remove a container | docker rm <id> |
Requires the container to be stopped unless using -f. |
| Prune unused objects | docker system prune |
Removes dangling images, stopped containers, unused networks & volumes. |
5.1 Compose for Multi‑Container Apps
For services that depend on each other (e.g., a web server and database), Docker Compose simplifies orchestration:
# docker-compose.yml
version: "3.8"
services:
db:
image: postgres:15-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: example
web:
build: .
ports:
- "8080:80"
depends_on:
- db
volumes:
pgdata:
Run:
docker compose up --build
Compose handles network creation, dependency ordering, and volume persistence automatically.
6. Best Practices & Security Hardening
6.1 Image Hygiene
- Start from minimal bases (
alpine,scratch) to reduce attack surface. - Use multi‑stage builds: compile in one stage, copy artifacts into a lean runtime image.
- Avoid running as root inside the container. Add a non‑root user:
dockerfile
RUN adduser -D appuser
USER appuser
6.2 Runtime Security
| Technique | How |
|---|---|
| Seccomp profiles | Restrict system calls (--security-opt seccomp=unconfined or a custom profile). |
| AppArmor/SELinux | Enforce mandatory access controls on container processes. |
| Capabilities dropping | Remove unnecessary Linux capabilities (--cap-drop ALL --cap-add NET_BIND_SERVICE). |
6.3 Secrets Management
Never bake passwords into images:
- Use Docker secrets (Swarm) or external secret stores (HashiCorp Vault, AWS Secrets Manager).
- In Compose, reference environment files with
env_file:but keep them out of version control.
6.4 Regular Scanning
docker scan <image>
Docker Hub and other registries also offer automated vulnerability scanning on push. Keep base images up to date; run docker pull regularly or use tools like watchtower.
7. Troubleshooting Common Issues
| Symptom | Likely Cause | Quick Fix |
|---|---|---|
| Container exits immediately | CMD not found, wrong entrypoint, missing binary. | Verify CMD/ENTRYPOINT, check file permissions, run with docker run -it --entrypoint sh. |
| Port mapping conflict | Host port already in use. | Use a different host port (-p 8081:80) or stop the conflicting service. |
| Cannot access network from container | Docker networking disabled, firewall blocking. | Ensure iptables rules allow forwarding; try --network=host. |
| Large image size | Unnecessary files in layers (logs, docs). | Clean up in Dockerfile (RUN rm -rf /var/lib/apt/lists/*). |
Conclusion
Docker has matured into a foundational tool for modern Linux environments. By mastering the basics—installing the engine, building images with clear Dockerfiles, managing containers and volumes, and applying security best practices—you can confidently deploy reproducible, isolated services that scale from a single laptop to production clusters.
The next steps are to explore orchestration platforms like Kubernetes or Docker Swarm, integrate CI/CD pipelines that build and push images automatically, and keep your registry and runtime hardened against emerging threats. With the fundamentals covered here, you’re ready to take those strides. Happy containerizing!
Frequently Asked Questions (FAQ)
Q1: How do I keep my Docker containers secure on a Linux host?
A: Run containers with the least privilege possible—use non‑root users inside images, limit capabilities (--cap-drop/--cap-add), and enable seccomp or AppArmor profiles. Regularly scan base images for vulnerabilities (e.g., docker image inspect, trivy) and keep Docker Engine up to date.
Q2: What is the difference between a Docker image and a container?
A: An image is an immutable snapshot of filesystem layers plus metadata; it’s like a template. A container is a running instance of that image, isolated in its own namespace with writable layers that disappear when stopped (unless volumes are used).
Q3: How can I persist data generated by a container across restarts?
A: Mount host directories or Docker named volumes into the container (-v /host/path:/container/path or --mount source=myvol,target=/data). Volumes are managed by Docker and survive container removal, while bind mounts keep data on the host filesystem.
Q4: Why should I use a multi‑stage Dockerfile for production images?
A: Multi‑stage builds let you separate build-time dependencies from runtime ones. The final image contains only the compiled binaries and essential libraries, reducing size, attack surface, and speeding up deployment compared to single‑stage builds that include compilers or build tools.


