How To Install Docker Linux

How To Install Docker Linux

Reading time1 min
#Docker#Linux#Containers#DockerInstallation#LinuxSysAdmin#Containerization

Mastering Docker Installation on Linux: A Step-by-Step Practical Guide

Deployment pipelines, CI/CD workflows, stateful services—all routinely demand isolation, portability, and reproducibility. Odds are, you’ll need Docker running on Linux before your first production deployment or local integration test ever passes. But “installation” isn’t just a curl-bash script: package source hygiene, systemd implications, and kernel module compatibility matter. Below, practical steps—distilled from production setups—for Ubuntu and RHEL-based distros, with common gotchas annotated.


Pre-Install Checklist: Environment Sanity and Old Binaries

Failing to purge legacy Docker traces (“docker-engine”, “containerd”, etc.) can trigger obscure daemon conflicts:

# Ubuntu/Debian
sudo apt-get remove -y docker docker-engine docker.io containerd runc

# CentOS/RHEL
sudo yum remove -y docker docker-client docker-client-latest docker-common \
  docker-latest docker-latest-logrotate docker-logrotate docker-engine

Verify your distribution and architecture—critical for repo setup:

lsb_release -a             # Ubuntu/Debian
cat /etc/redhat-release    # CentOS/RHEL/Fedora
uname -m                   # Architecture, e.g. x86_64 or aarch64

Note: Some lightweight or cloud-optimized distros (AlmaLinux, Amazon Linux 2, etc.) may require minor adjustments.


Ubuntu 20.04/22.04+: Official Repo and Engine Deployment

Repository trust is non-negotiable. Skip unofficial mirrors—even a minor difference in signing keys compromises the “supply” side of your supply chain.

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

Add Docker’s GPG key and source list (as of 2024, the repo location remains stable):

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

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
sudo apt-get update

Now install the complete engine, including CLI and runtime:

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

Verify with:

docker --version
# Docker version 24.0.6, build ed223bc

A simple CI test: can you pull and run from Docker Hub?

sudo docker run --rm hello-world

Gotcha: If docker.socket or containerd fails to start, check /var/log/syslog for AppArmor or cgroup v2 issues—particularly in hardened or custom kernel environments.


CentOS 7/8, RHEL 8+: Engine, Repo, Service Management

Minimal images frequently lack yum-utils. Install dependencies or the install will fail, mid-way.

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

Add and verify the Docker repository:

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum makecache

For CentOS Stream or RHEL 8, swap yum for dnf as needed.

Install the latest stable engine:

sudo yum install -y docker-ce docker-ce-cli containerd.io

After package install: systemd must manage the lifecycle. Enable on boot, then start manually to avoid orphaned containers after reboots.

sudo systemctl enable docker
sudo systemctl start docker

Verify health and logs:

sudo systemctl status docker
journalctl -u docker --since "10 minutes ago"

Test container launch:

sudo docker run --rm hello-world

Note: With hybrid physical/virtual RHEL clusters, storage driver defaults can mismatch (e.g., overlay2 vs. devicemapper). Inspect with docker info and adjust /etc/docker/daemon.json if needed.


Post-Install: Secure Access and Shell Usability

By default, Docker’s UNIX socket at /var/run/docker.sock is root-owned, which is deliberate. To allow non-root Docker commands (full container access is granted):

sudo usermod -aG docker $USER
newgrp docker

May require shell re-login; test access:

docker run --rm hello-world

Security note: Never expose the Docker socket (-H tcp://0.0.0.0:2375 or similar) unless it’s strictly firewalled—privilege escalation risk is substantial.


Troubleshooting: What Breaks, and Why

  • Daemon unreachable:

    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    

    Usually either systemctl start docker is missing or group permissions aren’t applied. Check with id $USER and verify restart.

  • Installation blocked by firewall or proxy:

    Manifests as Timeout while connecting to .... Either set http_proxy/https_proxy environment variables or ensure outbound 443 is allowed.

  • Kernel version unsupported for overlay2:

    Typical with self-customized kernels or old VPS images. Confirm with:

    uname -r
    docker info | grep 'Storage Driver'
    

    Upgrade kernel or adjust daemon.json.

  • Stray or stale packages:

    After repo/key changes, always:

    sudo apt-get clean
    sudo apt-get update
    

Practical Example: Multi-Arch Setup on a Build Host

Building cross-architecture images? Validate QEMU and binfmt_misc support post-install:

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker run --rm --platform linux/arm64 alpine uname -m
# Expected output: aarch64

Beyond Installation

Next logical steps: iteration with a minimal Dockerfile, basic Compose orchestration, or hardening the runtime with user namespaces in /etc/docker/daemon.json. In CI, always lock engine minor versions for reproducibility (apt-mark hold docker-ce).

Example minimal Dockerfile for node.js:

FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npm", "start"]

Known issue: Some CI runners (GitHub-hosted Ubuntu 22.04, for instance) pre-install an older containerd; purge before custom-engine installation to avoid clingy segfaults.


No installation is ever perfect—expect subtle edge cases around kernel, shell, or new LTS releases. Still, following the above will get you a resilient Docker host, not just a passing “hello-world”. For edge-case errors or environment-specific questions, scan /var/log/syslog, use strace, and avoid trial-and-error via random forum answers.