Install Docker on Ubuntu

Khimananda Oli 8 min read Virtualization
Install Docker on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

Getting a reliable container runtime is the first step for any modern DevOps workflow, but outdated tutorials often lead to broken dependencies or insecure defaults. To correctly install Docker on Ubuntu 24.04 LTS (Noble Numbat), you must use the official Docker CE repository rather than the older docker.io package found in Ubuntu’s default archives. This guide walks you through the verified installation process, post-install security hardening, and validation steps required for production-grade infrastructure.

1. CleanupRemove docker.io& legacy deps2. RepositoryAdd GPG Key& Official Repo3. Installdocker-cecontainerd.io4. VerifyService Status& Hello World
The four critical phases to install Docker on Ubuntu cleanly and securely

How do I prepare my system before I install Docker on Ubuntu?

Before running any installation commands, you must clean up conflicting packages. Ubuntu’s default repositories contain an older docker.io package that conflicts with Docker’s official Community Edition (CE). If you have previously installed Docker from the Ubuntu archives or via snap, those versions will prevent the official packages from functioning correctly.

Run the following command to remove all legacy Docker components. This is safe even if you have never installed Docker before; apt will simply report that the packages are not installed.

sudo apt-get remove -y docker docker-engine docker.io containerd runc docker-compose-plugin

Next, update your local package index and install the prerequisite dependencies required for adding external HTTPS repositories. These tools allow apt to securely fetch packages and verify signatures.

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

A common mistake at this stage is skipping the cleanup and proceeding directly to repository configuration. This leads to version mismatches where docker compose commands fail because the system is mixing the official CLI with the older Ubuntu-managed daemon. Always start with a clean slate. For teams managing multiple servers, consider automating this preparation phase using the patterns described in our guide to automate server setup with Ansible playbooks.

What are the exact commands to install Docker on Ubuntu 24.04?

The most reliable method to install Docker on Ubuntu is via the official Docker CE repository. This ensures you receive the latest stable releases, security patches, and compatibility updates directly from Docker Inc., rather than waiting for Ubuntu maintainers to backport fixes.

Add the official Docker GPG key and repository

Docker now uses a signed-by mechanism for repository verification, which is more secure than the legacy global keyring approach. Create the keyrings directory and download the GPG key:

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 repository to your apt sources. This command dynamically detects your Ubuntu codename (e.g., noble for 24.04) and architecture:

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 Docker Engine packages

Update the package index again to include the new Docker repository, then install the three core packages. The docker-compose-plugin is included here as it provides the modern docker compose V2 command:

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

After installation completes, verify the service is active and enabled to start on boot:

sudo systemctl enable --now docker
sudo systemctl status docker

You should see active (running) in the output. If the service fails to start, check journalctl -xeu docker.service for errors related to storage drivers or conflicting configurations.

Docker Engine Architecture on UbuntuDocker CLIUser Commandsdocker run / buildDocker DaemondockerdAPI & Image MgmtcontainerdContainer LifecycleImage & NetworkOCI Runtimerunc / crunKernel Namespaces
Docker daemon delegates container lifecycle to containerd and OCI runtimes after you install Docker on Ubuntu

Should I use rootless Docker or add users to the docker group?

This is one of the most important security decisions you make when you install Docker on Ubuntu. By default, the Docker daemon binds to a Unix socket owned by root. Adding a user to the docker group grants them full root-equivalent privileges on the host, because they can mount host filesystems and escape containers trivially.

For development machines and CI runners where convenience outweighs isolation risk, the docker group is acceptable:

sudo usermod -aG docker $USER
newgrp docker

However, for production servers, multi-tenant environments, or compliance-scoped systems (SOC 2, ISO 27001), rootless mode is strongly preferred. Rootless Docker runs the daemon and containers entirely under a non-root user namespace, eliminating the privilege escalation vector.

To enable rootless mode after installation:

sudo apt-get install -y uidmap dbus-user-session
dockerd-rootless-setuptool.sh install

Rootless mode has trade-offs: no binding to privileged ports (<1024) without additional configuration, no ICMP ping by default, and slightly higher overhead for network namespace setup. Evaluate these against your security requirements. For teams building CI pipelines, understanding these trade-offs is essential when configuring self-hosted CI runners.

CriteriaDocker GroupRootless Mode
Security IsolationRoot-equivalent accessUser namespace isolation
Privileged PortsYesNo (requires net.ipv4.ip_unprivileged_port_start)
Setup ComplexitySingle commandAdditional packages + config
Compliance FriendlyNoYes (SOC 2 / ISO 27001)
Best ForDev laptops, trusted CIProduction, multi-tenant

How do I optimize Docker daemon settings for production?

The default Docker configuration works for local development but lacks the guardrails needed for production. After you install Docker on Ubuntu, create or edit the daemon configuration file at /etc/docker/daemon.json.

A production-ready configuration should include log rotation, live restore, and explicit storage driver settings:

{
  "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
    }
  ],
  "storage-driver": "overlay2"
}
  • Log rotation prevents container logs from filling your root partition — a frequent cause of outages in Nepal-based hosting environments where disk monitoring may be limited.
  • Live restore keeps containers running when the Docker daemon restarts for updates, reducing maintenance window impact.
  • Address pools prevent subnet conflicts when running Docker alongside VPNs or other overlay networks.
  • Overlay2 is the recommended storage driver for Ubuntu 24.04’s ext4/xfs filesystems; avoid deprecated drivers like aufs or devicemapper.

After editing the configuration, validate the JSON syntax and reload the daemon:

sudo dockerd --validate
sudo systemctl reload docker

For teams adopting infrastructure-as-code practices, managing this configuration declaratively is far superior to manual edits. Our guide on infrastructure as code with Terraform covers patterns for provisioning Docker hosts with pre-configured daemon settings.

How do I verify Docker is working correctly after installation?

Verification goes beyond running hello-world. A proper validation confirms networking, volume mounts, DNS resolution, and permission boundaries are all functional.

  1. Basic connectivity: Run docker run --rm hello-world to confirm image pull and execution.
  2. Network stack: Run docker run --rm alpine wget -qO- http://ifconfig.me to verify outbound NAT and DNS.
  3. Volume mounts: Run docker run --rm -v /tmp:/host alpine ls /host to confirm bind mount permissions.
  4. Compose integration: Run docker compose version to verify the V2 plugin is installed and functional.
  5. Resource limits: Run docker run --rm --memory=64m alpine free -m to confirm cgroup memory enforcement works.

If any step fails, isolate the issue systematically. Network failures usually indicate firewall or proxy misconfiguration. Volume mount failures suggest AppArmor or SELinux restrictions. Memory limit failures indicate missing cgroup v2 support in your kernel parameters.

Install Docker on UbuntuProduction or Compliance?YESNORootless ModeUser namespace isolationNo root escalation riskDocker GroupConvenient but riskyDev / Trusted CI onlyConfigure daemon.jsonAdd user to docker group
Decision framework for choosing between rootless mode and docker group after you install Docker on Ubuntu

Final Steps After You Install Docker on Ubuntu

A successful installation is just the starting point. Ensure your setup remains maintainable by pinning package versions in automation scripts, enabling automatic security updates via unattended-upgrades, and integrating container scanning into your CI pipeline. Monitor disk usage regularly with docker system df and prune unused resources weekly to prevent storage exhaustion.

If you are setting up Docker as part of a larger infrastructure initiative or need help hardening your container runtime for compliance audits, reach out to discuss your specific requirements. Properly configured Docker foundations save countless hours of debugging downstream.

Frequently Asked Questions

Use the official Docker apt repository instead of the default Ubuntu packages. Add the GPG key, configure the stable repo, then run sudo apt install docker-ce docker-ce-cli containerd.io for the latest version and security updates in 2026.

Yes but avoid it for production. Snap Docker runs in strict confinement causing permission issues with volumes and networking. The official apt package provides better performance, compatibility, and standard systemd integration for server environments.

Run docker run hello-world to test the daemon and client. Check systemctl status docker to confirm the service is active. Verify the version with docker --version to ensure you have the expected release.

Adding your user avoids typing sudo for every command but grants root-equivalent privileges. For shared servers or CI runners, use sudo explicitly instead. If adding users, log out and back in for group changes to take effect.

Ubuntu repositories prioritize stability over new features, often lagging months behind upstream releases. The docker.io package lacks recent security patches and functionality. Always prefer docker-ce from the official repository for current stable builds and timely CVE fixes.

Enable the service with sudo systemctl enable docker after installation. This creates necessary symlinks so the daemon starts during system initialization. Verify persistence by rebooting and checking docker info returns valid output without manual intervention.

No ports are required for local-only container workloads. Opening port 2375 or 2376 exposes the daemon API and risks remote code execution. Only expose the socket via SSH tunnel or mutual TLS if remote management is absolutely necessary.

Edit /etc/docker/daemon.json and set data-root to your desired path like /mnt/docker-data. Restart the daemon with sudo systemctl restart docker afterward. Ensure the target filesystem has sufficient space and proper permissions before migrating existing images.

No. Docker Desktop targets developers needing GUI tools and WSL integration. Servers should use Docker Engine directly via apt. It consumes fewer resources, avoids licensing restrictions for commercial use, and integrates natively with Linux init systems.

Run sudo apt purge docker-ce docker-ce-cli containerd.io to remove binaries. Delete /var/lib/docker and /etc/docker to clear images, containers, and configs. Remove the repository file in /etc/apt/sources.list.d to prevent future accidental reinstalls.

Kernel updates sometimes break container runtime dependencies or cgroup configurations. Reboot first to load the new kernel fully. If issues persist, reinstall containerd.io and docker-ce to rebuild kernel module bindings against the updated headers.

Yes but requires nesting enabled in the LXC config and AppArmor unconfined mode. Performance suffers due to double virtualization overhead. Prefer running Docker directly on the host or use lightweight VMs for better isolation and reliability.

The error means your user lacks access to /var/run/docker.sock. Either prefix commands with sudo or add your account to the docker group using sudo usermod -aG docker $USER. Log out and back in to apply group membership changes.

Use json-file with max-size and max-file options to prevent disk exhaustion. Default logging grows indefinitely and crashes nodes under load. Configure this globally in daemon.json rather than per-container to enforce consistent retention policies across all services.

Docker Engine Community Edition is free and open source for personal and commercial use. Docker Desktop requires paid subscriptions for larger organizations. On Ubuntu servers, stick with docker-ce from the official repository to avoid licensing complications entirely.