Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Install Docker on Ubuntu

By Kokil Thapa | Last reviewed: August 2026

If you need to install Docker on Ubuntu for development or production in 2026, skip the outdated tutorials that still reference docker.io or deprecated keyrings. The correct approach uses Docker’s official apt repository with signed GPG keys, ensuring you receive security patches and the latest stable release immediately. This guide walks through the verified installation process for Ubuntu 24.04 LTS (Noble Numbat), including post-install hardening and rootless configuration.

How Do You Correctly Install Docker on Ubuntu 24.04?

The most reliable way to install Docker on Ubuntu is through Docker Inc.’s official apt repository. While Ubuntu ships a docker.io package in its universe repository, it is community-maintained, often months behind on security fixes, and lacks Docker Compose V2 integration. For any system where reliability matters — whether a local dev box or a server running client applications like those described in my Laravel development practice — the official CE (Community Edition) repository is mandatory.

Before installing, understand what you are adding to your system. Docker Engine consists of three core components that must be version-matched:

  • docker-ce: The daemon (dockerd) that manages images, containers, networks, and volumes.
  • docker-ce-cli: The docker command-line client that communicates with the daemon via REST API over a Unix socket.
  • containerd.io: The low-level container runtime that actually spawns and manages container processes. Docker delegates execution to containerd; without it, nothing runs.
Docker Engine Stack (Ubuntu)docker CLIUser CommanddockerdDaemon / APIcontainerdRuntime ManagerruncOCI ContainerLinux Kernel: cgroups · namespaces · overlayfs · netfilter
Docker Engine component hierarchy: CLI talks to dockerd, which delegates to containerd and runc atop kernel primitives

Step-by-Step Installation Commands

Run these commands sequentially on a fresh Ubuntu 24.04 system. Each step addresses a specific failure point I’ve encountered across dozens of deployments.

  1. Remove conflicting packages. Old Docker installations or snap versions will conflict with the official repo.
    sudo apt-get remove -y docker docker-engine docker.io containerd runc docker-compose 2>/dev/null
    sudo rm -rf /var/lib/docker /etc/docker
  2. Install prerequisites. These allow apt to fetch packages over HTTPS and verify signatures.
    sudo apt-get update
    sudo apt-get install -y ca-certificates curl gnupg lsb-release
  3. Add Docker’s official GPG key. Use the modern signed-by directory method, not the deprecated apt-key.
    sudo install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    sudo chmod a+r /etc/apt/keyrings/docker.gpg
  4. Add the repository. This pins the source to your exact Ubuntu codename.
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  5. Install Docker Engine. Include the compose plugin for V2 support.
    sudo apt-get update
    sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  6. Verify the installation. This confirms the daemon is running and can execute containers.
    sudo docker run hello-world

If the verification succeeds, you have a working Docker installation. If it fails with permission errors or missing socket issues, proceed to the post-install configuration below.

What Are the Common Mistakes When Installing Docker on Ubuntu?

In my experience maintaining servers for legal-tech portals and eCommerce platforms, most Docker installation failures stem from three preventable mistakes. Avoiding these saves hours of debugging.

Mistake 1: Using the Universe Repository Package

The docker.io package in Ubuntu’s universe repository is maintained by Debian/Ubuntu volunteers, not Docker Inc. In 2026, this package frequently lags behind on critical CVE patches. More importantly, it does not include Docker Compose V2 as an integrated plugin, forcing you to manage a separate binary. Always use docker-ce from the official repository.

Mistake 2: Skipping GPG Key Verification

Some tutorials still suggest piping the GPG key directly into apt-key add, which has been deprecated since Ubuntu 22.04. The correct method stores the key in /etc/apt/keyrings/ and references it explicitly in the sources list via signed-by. This prevents key collisions and ensures apt only trusts Docker’s signature for Docker packages.

Mistake 3: Running Containers as Root by Default

Adding your user to the docker group grants root-equivalent privileges because the Docker socket is owned by root. For shared development machines or CI runners, prefer rootless mode. For dedicated servers where convenience outweighs isolation risk, the docker group is acceptable but should be documented as a conscious trade-off.

Installation MethodSecurity UpdatesCompose V2Rootless SupportRecommended For
docker-ce (Official Repo)Immediate from Docker Inc.Integrated pluginFull supportProduction & Development
docker.io (Universe)Delayed, community-maintainedSeparate binary requiredLimitedQuick testing only
Snap PackageAutomatic but sandboxedBundled but isolatedNot applicableDesktop users avoiding apt
Static BinariesManual download onlyManual setupComplex setupAir-gapped environments

How Do You Configure Post-Install Settings After Installing Docker on Ubuntu?

Installation alone does not make Docker production-ready. Three post-install steps address performance, usability, and persistence.

Enable and Start the Service

Docker should start automatically on boot. Verify and enable if needed:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service
sudo systemctl status docker

If the service fails to start, check journalctl -xeu docker.service. A common cause on minimal Ubuntu installs is missing iptables legacy binaries; install them with sudo apt install iptables.

Configure Non-Root Access Safely

For development workflows where typing sudo before every command is impractical:

sudo usermod -aG docker $USER
newgrp docker

The newgrp command activates the group membership without requiring logout/login. Document this privilege escalation in your team’s onboarding docs. For production systems handling sensitive data (like legal document portals), skip this and use rootless mode instead.

Persist Daemon Configuration

Create or edit /etc/docker/daemon.json to set defaults that survive upgrades:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "live-restore": true,
  "default-address-pools": [
    {"base": "172.30.0.0/16", "size": 24}
  ]
}

The live-restore option keeps containers running during daemon restarts (e.g., during package upgrades). The log rotation prevents disk exhaustion — a recurring issue I’ve diagnosed on client servers where unrotated JSON logs consumed entire partitions. Restart the daemon after editing: sudo systemctl restart docker.

Post-Install Configuration Flow1. Enable Servicessystemctl enableBoot Persistence2. User Permissionsusermod -aG dockerOR Rootless Mode3. daemon.jsonLog RotationLive RestoreRestart Daemonsudo systemctl restart docker✓ Ready for Production Workloads
Sequential post-install steps: enable services, configure permissions, set daemon options, then restart

Should You Use Rootless Docker on Ubuntu for Production?

Rootless Docker runs the daemon and containers entirely under an unprivileged user account, eliminating the risk of container breakout granting host root access. Whether this matters depends on your threat model.

When Rootless Mode Is Worth the Complexity

  • Multi-tenant CI/CD runners: Untrusted code executes in containers; rootless prevents escape to host root.
  • Shared development servers: Multiple developers with shell access; prevents one user’s compromised container from affecting others.
  • Compliance-regulated environments: Legal-tech platforms handling court documents or personal data benefit from defense-in-depth.

When Standard Docker Is Acceptable

  • Dedicated application servers: Single-purpose VMs running trusted code (e.g., a Laravel app you built and deployed).
  • Performance-critical workloads: Rootless adds overhead for network namespace setup and storage drivers.
  • Legacy applications: Some containers require privileged operations incompatible with rootless restrictions.

To enable rootless mode after standard installation:

sudo apt-get install -y uidmap dbus-user-session
dockerd-rootless-setuptool.sh install
export PATH=/home/$USER/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

Add the exports to your shell profile. Note that rootless containers cannot bind to ports below 1024 or use certain network features without additional configuration. Test thoroughly before adopting in production.

Rootful vs Rootless Security BoundaryRootful DockerDaemon runs as rootContainer breakout = host rootBest for: Dedicated ServersRootless DockerDaemon runs as unprivileged userBreakout limited to user namespaceBest for: Multi-Tenant / CIVSTrade-Off SummaryRootful: Full Features + Performance | Rootless: Isolation + SafetyChoose based on threat model, not default preference
Security boundary comparison: rootful offers full functionality at higher risk; rootless trades features for isolation

How Do You Maintain Docker After Installation on Ubuntu?

Installing Docker is a one-time task; maintaining it is ongoing. Three practices prevent most operational issues.

Automate Security Updates

Enable unattended upgrades specifically for Docker packages to ensure CVE patches apply without manual intervention:

sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Edit /etc/apt/apt.conf.d/50unattended-upgrades to include Docker’s origin pattern. This avoids the scenario where a known vulnerability persists for weeks because nobody remembered to run apt upgrade.

Monitor Disk Usage Proactively

Docker accumulates unused images, stopped containers, and dangling build cache. Set up a weekly cleanup cron job:

echo "0 3 * * 0 docker system prune -af --volumes >> /var/log/docker-prune.log 2>&1" | sudo tee /etc/cron.weekly/docker-prune
sudo chmod +x /etc/cron.weekly/docker-prune

The --volumes flag removes anonymous volumes not attached to any container. Review named volumes separately before pruning; deleting database volumes is irreversible. On projects like eCommerce platforms with frequent image rebuilds, this single cron job has prevented multiple disk-full incidents.

Pin Versions in Production

For production servers, avoid blindly upgrading Docker during routine maintenance. Pin specific versions in /etc/apt/preferences.d/docker:

Package: docker-ce docker-ce-cli containerd.io
Pin: version 5:27.*
Pin-Priority: 1001

This allows security patch updates within the major version while preventing unexpected breaking changes from new releases. Upgrade intentionally during maintenance windows after reviewing changelogs.

Final Steps After You Install Docker on Ubuntu

You now have a correctly configured Docker installation on Ubuntu 24.04 using the official repository, with post-install hardening appropriate for your use case. The key decisions remaining are whether to adopt rootless mode based on your security requirements and how aggressively to automate maintenance tasks. Both choices depend on your specific workload rather than generic best practices.

If you are setting up Docker as part of a larger infrastructure deployment for a Laravel application, legal-tech platform, or eCommerce system, consider pairing this installation with proper CI/CD pipelines and monitoring. For teams in Nepal evaluating whether to self-host or use managed container services, weigh the operational overhead against the cost savings — sometimes paying for managed infrastructure is cheaper than debugging Docker at 2 AM. If you need hands-on assistance configuring Docker for production workloads or integrating it into an existing deployment workflow, reach out to discuss your specific requirements.

Frequently Asked Questions

Use the official Docker repository, not the default Ubuntu apt packages. Run sudo apt install docker-ce docker-ce-cli containerd.io after adding Docker’s GPG key and repo. This ensures you get the latest stable release with security patches, whereas Ubuntu’s docker.io package often lags behind by months or years.

Docker Engine is free and open-source for personal and commercial use. Costs only apply if you need Docker Business for enterprise management features or paid support. For most Nepal-based projects I work on, the community edition is sufficient, so your only expense is the underlying VPS hosting at roughly NPR 1,500–3,000 monthly.

No, installation requires sudo because Docker modifies system services and kernel networking. However, post-installation you can add your user to the docker group with sudo usermod -aG docker $USER to run containers without sudo. Always log out and back in for group changes to take effect.

The docker.io package in Ubuntu repos is maintained separately and frequently lacks recent security fixes, newer container runtime features, and compatibility with current Docker Compose specifications. In production environments I manage, this version gap has caused subtle networking and storage driver issues. The official docker-ce package from Docker Inc. receives timely updates and matches upstream documentation exactly, making troubleshooting predictable and reducing deployment surprises during framework or application upgrades.

Run docker run hello-world after installation. If it pulls the image and prints a success message, the daemon, CLI, and container runtime are functional. Also check systemctl status docker to confirm the service is active. On fresh Ubuntu 24.04 installs, I always validate this before deploying any application stack to catch permission or cgroup configuration problems early.

Docker requires a 64-bit Ubuntu version (20.04, 22.04, or 24.04 LTS), kernel 5.4+, and at least 2GB RAM for basic workloads. Storage needs depend on images and layers, but allocate minimum 20GB SSD. Enable systemd and ensure cgroups v2 support. On low-spec Nepali hosting providers, verify these prerequisites before installation to avoid runtime failures.

Enable the service with sudo systemctl enable docker after installation. Verify with systemctl is-enabled docker. On Ubuntu 24.04, Docker enables itself by default, but I always confirm this explicitly during server provisioning. If containers must also auto-start, use restart policies like --restart=unless-stopped in your compose files rather than relying solely on systemd dependencies.

No, Docker Desktop is a GUI tool intended for local development on desktop operating systems. Production Ubuntu servers should run Docker Engine directly via CLI. Installing Desktop on headless servers wastes resources and introduces unnecessary licensing concerns. Every production Laravel and eCommerce system I deploy uses standalone Docker Engine managed through systemd and Docker Compose, keeping the footprint minimal and operations straightforward.

Add your user to the docker group using sudo usermod -aG docker $USER, then log out and log back in completely. Alternatively, prefix commands with sudo temporarily. Never modify /var/run/docker.sock permissions manually as this creates security risks. On shared Ubuntu servers where multiple developers need access, managing group membership properly prevents both permission errors and accidental privilege escalation during collaborative deployment workflows.

Docker CE (Community Edition) is free, open-source, and suitable for most applications including production Laravel, WordPress, and eCommerce systems. Docker EE (now Mirantis Container Runtime) adds enterprise support, certified plugins, and compliance tools for regulated industries. Unless your Nepal-based legal-tech or financial project has specific compliance mandates requiring vendor support contracts, CE provides identical core functionality. I have shipped dozens of production systems using only CE without limitations.

Remove packages with sudo apt purge docker-ce docker-ce-cli containerd.io, then delete data directories using sudo rm -rf /var/lib/docker /etc/docker. Optionally remove the docker group with sudo groupdel docker. Back up volumes and images first if needed. On client servers where Docker was misconfigured initially, this clean removal followed by fresh official-repo installation resolves more issues than attempting incremental repairs.

Yes, for any multi-container application. Install the Compose plugin with sudo apt install docker-compose-plugin to get v2.x integrated into the docker CLI. Standalone docker-compose binaries are deprecated. In my Laravel and WooCommerce deployments, Compose defines web, database, cache, and queue services reproducibly. Version-controlled compose.yml files make environment parity achievable across development, staging, and production without manual container orchestration or fragile shell scripts.

Restrict Docker socket access to trusted users only, never expose the API over TCP without TLS. Run containers as non-root where possible, use read-only filesystems, and limit capabilities with security-opt flags. Keep Docker and host kernel updated. Enable UFW rules blocking unused ports. On legal-tech portals handling sensitive documents, I additionally audit image sources, scan for vulnerabilities with Trivy, and isolate networks between public-facing and internal services to reduce attack surface significantly.

Kernel updates sometimes change cgroup or overlay filesystem behavior that Docker depends on. Check journalctl -u docker.service for specific errors. Usually restarting Docker with sudo systemctl restart docker resolves transient incompatibilities. If persistent, verify kernel module loading with lsmod | grep overlay and ensure apparmor profiles are compatible. Pinning Docker versions matching tested kernel combinations prevents surprise breakages during routine Ubuntu security maintenance cycles on production servers.

First test the target version in staging. On production, run sudo apt update && sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io during low-traffic windows. Running containers continue operating during package upgrade, but schedule restarts afterward to apply new runtime features. Always read release notes for breaking changes. In my experience maintaining multiple client servers, staged rollouts with rollback plans prevent extended downtime when upstream releases introduce unexpected behavioral shifts affecting application networking or volume mounts.

Share this article

Quick Contact Options
Choose how you want to connect me: