Skip to content
On this page

    Install Docker on Ubuntu (Hetzner Server Setup)

    2 min read

    Today I decided to document the Docker installation steps I repeat every time I spin up a new Hetzner server. I deploy projects the old school way: a bare Ubuntu VPS, Docker, and docker compose. No Kubernetes, no managed container services. It keeps costs low and the setup predictable.

    The problem is I end up Googling “install docker ubuntu” every single time. Not anymore.

    The Full Installation Script

    This uses Docker’s official APT repository (not the docker.io package from Ubuntu’s default repos, which is often outdated).

    #!/bin/bash
    set -e
    
    echo "==> Updating packages and installing dependencies..."
    sudo apt update
    sudo apt install -y ca-certificates curl
    
    echo "==> Adding Docker 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
    
    echo "==> Adding Docker APT repository..."
    sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
    Types: deb
    URIs: https://download.docker.com/linux/ubuntu
    Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
    Components: stable
    Architectures: $(dpkg --print-architecture)
    Signed-By: /etc/apt/keyrings/docker.asc
    EOF
    
    echo "==> Installing Docker Engine..."
    sudo apt update
    sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    echo "==> Enabling and starting Docker..."
    sudo systemctl enable docker
    sudo systemctl start docker
    
    echo "==> Adding current user to docker group..."
    sudo usermod -aG docker $USER
    
    echo "==> Verifying installation..."
    docker --version
    
    echo ""
    echo "Docker installed successfully!"
    echo "Log out and back in (or run 'newgrp docker') to use Docker without sudo."

    What Gets Installed

    PackagePurpose
    docker-ceDocker Engine (Community Edition)
    docker-ce-cliCLI tools for managing containers
    containerd.ioContainer runtime
    docker-buildx-pluginExtended build capabilities with BuildKit
    docker-compose-plugindocker compose (v2, replaces standalone docker-compose)

    How to Use

    Option A: Save and run locally

    nano install-docker.sh
    # paste the script, save with Ctrl+X
    chmod +x install-docker.sh
    ./install-docker.sh

    Option B: Run from a remote URL (if you host the script in a repo)

    curl -fsSL https://your-repo.com/install-docker.sh | bash

    Post-Install: Apply Group Change

    After the script completes, the docker group membership won’t take effect until you start a new session. Apply it immediately:

    newgrp docker

    Then verify everything works:

    docker run hello-world
    docker compose version

    What I Learned

    • Always use Docker’s official APT repository. The docker.io package in Ubuntu’s default repos lags behind significantly
    • The docker-compose-plugin gives you docker compose (with a space) as a native subcommand. No need to install standalone docker-compose separately anymore
    • usermod -aG docker $USER saves you from typing sudo before every Docker command, but requires a re-login to take effect
    • newgrp docker is the shortcut to avoid a full logout/login cycle
    • Keeping this as a single script means a fresh Hetzner server goes from bare Ubuntu to Docker-ready in under 60 seconds

    Deploying to Hetzner or similar VPS providers? I’d love to hear about your setup. Reach out on LinkedIn.