How To Install Docker In Linux

How To Install Docker In Linux

Reading time1 min
#Docker#Linux#Cloud#Ubuntu#Containers#DevOps

Step-by-Step: Installing Docker on Linux (Ubuntu) with Real-World Safeguards

Correct Docker installation underpins container reliability and security. Treating it as a basic package install ignores deeper system implications: kernel settings, user permissions, storage strategies. For production, these details determine system stability and minimize attack surface. This guide targets Ubuntu 20.04+ (tested with 22.04 LTS), but steps are transferable to Debian-based systems. File paths, group management, and package signatures—all matter.


1. Baseline OS Preparation

Critical: Update the package cache and ensure HTTPS transport support. Failing this, apt fetches can silently fail or expose your system to old packages. Run:

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

On minimal VMs, software-properties-common is sometimes omitted—its absence breaks add-apt-repository functionality (not used directly below, but required for key handling on some distributions).


2. Secure Docker’s GPG Key

No signature, no trust. Import Docker's GPG key and save it using armored storage for apt:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Side note: Key rotation occasionally breaks old instructions—Docker changed key fingerprints in late 2022. Always inspect contents with:

gpg --show-keys /usr/share/keyrings/docker-archive-keyring.gpg

3. Register Official Docker Repository

Why not use Ubuntu’s default docker.io package? Latency: repo lags six months or more behind Docker Inc. releases. To track stable mainline builds:

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

Replace $(lsb_release -cs) with your codename if the auto-detect fails; e.g., jammy for 22.04.


4. Install Docker Engine & Core Components

Update package index or apt may fetch from Ubuntu main instead of Docker’s repo.

sudo apt-get update
sudo apt-get install docker-ce=5:24.0.7~ubuntu.22.04~jammy docker-ce-cli=5:24.0.7~ubuntu.22.04~jammy containerd.io

Use apt-cache madison docker-ce to see available versions. Pinning versions is standard in CI/CD for reproducibility.

Components:

  • docker-ce: Actual Docker daemon and server logic.
  • docker-ce-cli: User CLI; useful to install separately for jump hosts.
  • containerd.io: Industry standard OCI runtime.

5. Smoke Test: Docker Daemon & Container Launch

Verify Engine install:

sudo systemctl status docker

Typical healthy output:

● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since...

Test container bootstrap:

sudo docker run --rm hello-world

Failure modes:

  • Cannot connect to the Docker daemon: The service isn’t running (systemd misconfiguration or missing /var/run/docker.sock).
  • permission denied while trying to connect...: User lacks group permissions (see next section).

6. Running Docker as Non-Root

Docker as root is a known privilege escalation risk. The following creates a docker group and puts your user inside:

sudo groupadd docker 2>/dev/null || true
sudo usermod -aG docker $USER

Log out and in—group membership won’t update in open shells.

Test:

docker run --rm hello-world

No sudo required. For multi-user systems: periodically review members of the docker group.


7. Persistent Service Enablement

On cloud VMs, containers need to survive reboots—docker.service should be enabled:

sudo systemctl enable docker
sudo systemctl start docker

Check logs for diagnostics—on misconfigured kernels, overlayfs or seccomp errors will appear here:

journalctl -u docker

8. Practical Example: Deploy a Custom Container

Deploy a namespaced NGINX server mapped to port 8080:

docker run -d --name demo-nginx -p 8080:80 nginx:1.25-alpine

Query its status:

docker ps --filter name=demo-nginx

Gotcha: If -p 8080:80 fails (bind: address already in use), the port’s occupied—choose another.

To tear down:

docker stop demo-nginx && docker rm demo-nginx

Non-Obvious Tips

  • Kernel Compatibility: For Docker 24.x, use Linux kernel ≥ 5.10 for optimal cgroups v2 and overlay2 support. Outdated kernels manifest as unexplained container deadlocks or errors like failed to mount overlay.
  • Storage Footprint: Default Docker root (/var/lib/docker) can easily fill disks on CI runners. Configure dockerd with --data-root=/mnt/docker if using ephemeral or dedicated volumes.
  • Image Source Validation: Use docker pull --disable-content-trust=false for signature checks on images where provenance is critical (not all upstream images are signed).
  • Partial Isolation Risk: Adding users to docker group effectively grants root; for strict compliance environments, prefer rootless Docker mode—though not all network plugins are compatible.
  • Daemon Reload: On configuration changes (/etc/docker/daemon.json), always reload instead of restart for minimal impact:
    sudo systemctl reload docker
    
    Not all options support reload; check logs.

Conclusion

Manual Docker installation demands closer inspection than “curl | sh” scripts. Each step—repository trust, GPG management, user groups, kernel settings—absorbs hidden risks if skipped or misunderstood. Production systems rarely behave like tutorials; version pinning and audit logging are routine. For edge cases, refer to Docker’s official install docs, then adapt—never blindly copy-paste.

For troubleshooting: /var/log/syslog and docker info provide early signals on resource or system call issues. Stay vigilant, monitor storage, and keep the engine patched.

ASCII Docker Lifecycle Sketch

[Client CLI] -> [Docker Daemon] -> [containerd] -> [runc]
                                   |
                                 [overlay2, aufs, etc.]