βοΈ Docker Installation and Configuration
You understand what containers are and how Docker's pieces fit together β now let's get it running on your own machine. This lesson walks through installation on all three major operating systems, then the configuration and security settings that turn a fresh install into a comfortable, safe development environment.
π― Learning Objectives
By the end of this lesson, you will be able to:
- Choose the right Docker edition for your operating system
- Install Docker on Windows, macOS, and Linux and verify it works
- Run Docker as a non-root user on Linux safely
- Tune the daemon through daemon.json and allocate resources sensibly
- Use Docker contexts to switch between local and remote engines
- Apply core security best practices from day one
Estimated Time: 30β40 minutes β’ Difficulty: BeginnerβIntermediate
Hands-on: Install Docker, run hello-world, and confirm your setup end to end.
In This Lesson
Docker Editions
Installation differs a little by platform, but the core is the same everywhere. First, pick the right edition.
| Edition | Platform | What you get |
|---|---|---|
| Docker Desktop | Windows, macOS (and Linux) | Engine + CLI + Compose + a GUI; runs a small Linux VM behind the scenes on non-Linux hosts |
| Docker Engine | Linux | The core runtime, CLI-first, runs natively with no VM; installed via your package manager |
| Cloud services | AWS, GCP, Azure | Managed container platforms (ECS/Fargate, Cloud Run, ACI) β no local install needed |
π Right vehicle for the trip: Docker Desktop is a comfortable family car with a dashboard; Docker Engine on Linux is a stripped-down race car β faster and lighter, but you drive it from the command line. Pick for your journey.
β οΈ Docker Desktop licensing
Docker Desktop is free for personal use, education, and small businesses, but larger companies need a paid subscription. Docker Engine on Linux remains free and open source. Check current terms before deploying it across a big organization.
Installing on Windows
Requirements
- Windows 10/11 64-bit (recent build)
- WSL 2 (Windows Subsystem for Linux) enabled β the recommended backend
- Hardware virtualization enabled in BIOS/UEFI
- At least 4 GB RAM
Steps
- Install WSL 2 (open PowerShell as administrator):
Reboot when prompted.wsl --install - Download the installer from Docker Desktop and run it, keeping the WSL 2 backend option selected.
- Launch Docker Desktop from the Start menu and let it initialize.
- Verify in PowerShell:
docker --version docker run hello-world
β οΈ Common Windows snags
- Virtualization disabled: enable it in BIOS/UEFI (often labelled VT-x, AMD-V, or SVM).
- WSL 2 missing: run
wsl --installin an elevated PowerShell. - Hypervisor conflicts: other virtualization tools can clash; close or disable them if Docker won't start.
Installing on macOS
Requirements
- A recent macOS release
- At least 4 GB RAM
- No VirtualBox needed β Docker Desktop uses Apple's native Virtualization framework
Steps
- Download the
.dmgfrom Docker Desktop, choosing the build for your chip (Apple Silicon or Intel). - Open the
.dmgand drag Docker into Applications. - Launch Docker from Applications, authorizing with your password if prompted, and wait for it to start.
- Verify in Terminal:
docker --version docker run hello-world
π‘ Apple Silicon (M-series) notes
Apple Silicon Macs run ARM64 images natively. Most popular images now publish ARM64 variants, so you rarely notice. When you must run an x86 image, Docker emulates it (slower); force the platform explicitly:
docker pull --platform linux/amd64 some-image
Installing on Linux
Docker Engine runs natively on Linux β no VM, minimal overhead. The recommended path is Docker's official apt/dnf repository. Here's the modern Ubuntu install using the current signed-keyring method:
# Remove any distro-packaged old versions first
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove -y $pkg
done
# Add Docker's official GPG key
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install the Engine, CLI, containerd, and the Compose & Buildx plugins
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# Verify
sudo docker run hello-world
For Fedora/RHEL/CentOS the equivalent uses dnf and Docker's docker-ce.repo, then sudo systemctl enable --now docker to start the service at boot.
β
Run Docker without sudo
By default the Docker socket is root-owned, so commands need sudo. Add yourself to the docker group to skip it:
sudo groupadd docker # usually already exists
sudo usermod -aG docker $USER # add yourself
newgrp docker # apply now (or log out/in)
docker run hello-world # no sudo needed
Security note: the docker group grants root-equivalent power over the host. Only add trusted users.
Verifying the Install
These commands work on every platform and confirm the client, daemon, and registry access all function:
docker --version # client version, quick sanity check
docker info # detailed daemon info: storage driver, resources, etc.
docker version # full client + server (daemon) version breakdown
docker run hello-world # end-to-end test
The hello-world container is the canonical smoke test. Running it exercises the entire architecture from the previous lesson:
- The client contacts the daemon.
- The daemon pulls the
hello-worldimage from Docker Hub. - The daemon creates and runs a container from it (via containerd β runc).
- The container prints a message and exits.
Success looks like:
Hello from Docker!
This message shows that your installation appears to be working correctly.
Configuring the Daemon
Fresh Docker works out of the box, but a few settings make development smoother.
Docker Desktop (Windows/macOS)
Open Settings (the gear icon) to adjust Resources (CPU, memory, disk), File sharing (which host directories may be bind-mounted), Network, and the Docker Engine JSON β the same daemon config as on Linux, just behind a GUI.
Linux daemon.json
On Linux the daemon reads /etc/docker/daemon.json. A sensible starter config caps log size (unbounded logs are a classic disk-filler) and pins the recommended storage driver:
{
"data-root": "/var/lib/docker",
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"default-address-pools": [
{ "base": "172.30.0.0/16", "size": 24 }
]
}
# Apply changes
sudo systemctl restart docker
| Option | What it controls |
|---|---|
data-root | Where Docker stores images, containers, and volumes |
storage-driver | Layer storage backend (overlay2 is standard) |
log-opts | Log rotation size and file count |
registry-mirrors | Caching mirrors to speed up pulls |
default-address-pools | IP ranges for container networks (avoid clashes) |
Right-sizing resources
Give Docker enough to be fast but not so much that the host chokes. Reasonable developer defaults:
- CPU: around half your cores
- Memory: 4β8 GB (depends on your stack)
- Disk: 60 GB+, more for large projects
Reclaim space periodically with docker system prune, which removes stopped containers, unused networks, and dangling images.
Docker Contexts
A context stores the connection details for a Docker endpoint, letting you switch between a local daemon, a remote server over SSH, or a cloud engine without editing environment variables each time.
# List contexts (the active one is marked with *)
docker context ls
# Create a context pointing at a remote host over SSH
docker context create remote-server \
--docker "host=ssh://user@remote-server"
# Switch to it
docker context use remote-server
# Or target it for a single command without switching
docker --context remote-server ps
# Inspect or remove a context
docker context inspect remote-server
docker context rm remote-server
π Browser profiles: Contexts are like separate browser profiles β each remembers its own connection and settings, so you flip between "local dev" and "staging server" in one command instead of reconfiguring everything.
π‘ Compose is built in now
You no longer install Compose separately β modern Docker ships Compose V2 as a CLI plugin (installed above via docker-compose-plugin). Invoke it as docker compose version, with a space and no hyphen.
Security Best Practices
Docker's convenience comes with real power over the host. Build these habits in from the start.
β Do
- Run containers as a non-root user. Add
USER appuserin your Dockerfile, or--user 1000:1000at runtime. - Drop unneeded Linux capabilities:
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx - Set resource limits so a runaway container can't hog the host:
docker run --memory=512m --cpus=1 nginx - Scan images for known vulnerabilities (e.g.
docker scout cve) and prefer minimal, official base images. - Keep Docker updated to receive security patches.
β οΈ Don't
- Don't expose the daemon on an unencrypted TCP port β use TLS or SSH for remote access.
- Don't add untrusted users to the
dockergroup; it's equivalent to giving them root. - Don't run containers with
--privilegedunless you genuinely need it. - Don't disable HTTPS on registries (
insecure-registries) except for a trusted local one.
π Layers of protection: Securing Docker is like securing a home β good locks (non-root users), controlled access (dropped capabilities), and utility limits (resource caps) work together. No single measure is enough alone.
Hands-on Exercise
ποΈ Install, Verify, and Configure
Objective: Get a working Docker setup and prove it end to end.
Instructions:
- Install Docker using the instructions for your OS above.
- Run all four verification commands:
docker --version,docker info,docker version, anddocker run hello-world. - From
docker info, find and note your storage driver, logging driver, and Docker's data root path. - Create a context for your local daemon, switch to it, and confirm it works:
(On Windows, use the named-pipe hostdocker context create local-dev \ --docker "host=unix:///var/run/docker.sock" docker context use local-dev docker psnpipe:////./pipe/docker_engineinstead.) - Reflect: based on the security section, name one change you'd make before running a container that exposes a network port.
π‘ Hint
If docker run hello-world fails with a permission error on Linux, you probably skipped the docker group step β add yourself and run newgrp docker. docker info lists the storage and logging drivers near the top of its output.
β Solution
On a healthy Linux install, docker info typically reports Storage Driver: overlay2, Logging Driver: json-file, and Docker Root Dir: /var/lib/docker. The context commands should switch the active context (marked * in docker context ls) and docker ps should return without error.
A good reflection answer: run the container as a non-root user and/or add --cap-drop=ALL --cap-add=NET_BIND_SERVICE so it has only the privileges it needs to bind its port.
π― Quick Quiz
Question 1: On Windows, which backend does Docker Desktop use to provide a real Linux kernel for containers?
Question 2: On Linux, what is the purpose of adding your user to the docker group?
Question 3: Which single command gives the most detailed picture of your running daemon β storage driver, resources, and configuration?
Summary & Quiz
π Key Takeaways
- Docker Desktop suits Windows/macOS (via WSL 2 or Apple's hypervisor); Docker Engine runs natively on Linux.
- Verify any install with
docker --version,docker info, anddocker run hello-world. - On Linux, join the docker group to drop
sudoβ and know it's root-equivalent power. - Tune the daemon through daemon.json: rotate logs, set the storage driver, size resources.
- Contexts switch between local, remote, and cloud engines; Compose V2 ships built in.
- Bake in security: non-root users, dropped capabilities, resource limits, image scanning.
π Further Reading
π What's Next?
With Docker installed and configured, you're ready to build your own images. Next we write Dockerfiles for different languages β Node.js, Python, and PHP β and learn to make them small, fast, and production-ready.
π Setup complete!
Docker is running on your machine. Now let's put it to work building images.