· 8 min read · updated August 2, 2026

Introduction

Virtualization has changed the game in software development. Docker and Docker Compose are must-have tools that let you build, manage and orchestrate containerized applications efficiently. This article walks you step by step through installing Docker and Docker Compose on a Linux system, whether that’s a PC, a virtual machine (VM), a Raspberry Pi or an LXC container (CT) on Proxmox VE.

If you want to take your projects to the next level with lightweight, efficient containers, stick around to the end!

Why Install Docker and Docker Compose?

The word Why? handwritten in black on a white background, opening the section on why to use Nginx Proxy Manager

Before getting into the technical steps, it’s worth understanding why these tools are so popular:

Ready to install these tools? Let’s go!

Prerequisites

Illustration of hands ticking boxes on a checklist with a pencil

Before you start, make sure you have the following:

For this tutorial the installation runs inside an LXC container (CT) on Proxmox VE, but the steps apply to any Linux environment.

Steps to Install Docker and Docker Compose

Illustration of a person at a laptop while a screen displays the word Installing

Step 1: Update the System

First, make sure your system is up to date:

sudo apt update && sudo apt upgrade -y

This ensures every package is on its latest version and avoids possible compatibility errors.

Step 2: Install curl

curl is an essential tool for downloading the Docker installation script. Install it by running:

sudo apt install curl -y

Check that it installed correctly with:

curl --version

You should see something like this:

curl --version output with the version number outlined in red

Step 3: Install Docker and Docker Compose

Now let’s install Docker and Docker Compose using the official script:

curl -sSL https://get.docker.com/ | sh

One note before you run it. That command downloads a script and hands it straight to your shell, so you are trusting the server to return exactly what you expect. It is the method Docker itself offers for getting started quickly and it works well, but their own repository says it plainly: “it is not recommended to depend on this script for deployment to production systems”.

If you would rather see what is about to happen before it happens, download it separately and read it:

curl -fsSL https://get.docker.com -o get-docker.sh
less get-docker.sh
sh get-docker.sh

For a server that will actually run something, the official route is Docker’s package repository, documented at docs.docker.com/engine/install. It takes longer, but it leaves the system updating through apt like any other package.

What does this command do?

  1. Checks the system:
    • Verifies your operating system distribution and version to make sure it’s compatible with Docker.
  2. Sets up the official repositories:
    • Adds the required Docker repositories to your system (APT for Debian/Ubuntu or YUM for CentOS/RHEL).
  3. Installs Docker:
    • Installs the Docker container engine (Docker Engine).
    • Installs the Docker command line interface (Docker CLI).
  4. Includes Docker Compose V2:
    • Docker Compose V2 ships inside the Docker CLI binary, so it comes along automatically.
  5. Enables and starts Docker:
    • Configures Docker to start automatically at boot.
    • Starts the Docker service right after installation.
  6. Cleanup and final setup:
    • Makes sure the installation is complete and ready to use.

Once the installation finishes, check the installed version:

docker --version

You should get output like this:

Docker version 27.3.1, build ce12230

Then check the Docker Compose installation:

docker compose version

You should see something like this:

Docker Compose version v2.29.7

Step 4: Let your user run Docker

Docker talks through a socket owned by root. Straight after installing, any command from your regular user answers with this:

permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock

If you are working as root (inside a Proxmox LXC container, for instance) you will never see this error and can skip the step. Otherwise, add your user to the docker group:

sudo usermod -aG docker $USER

And here is the part that costs people half an hour: the change does not apply to your current session. You add the group, run the command again, and it fails in exactly the same way. Log out and back in, or force the refresh without leaving:

newgrp docker
groups

docker should appear in the list that groups returns.

It is worth understanding what you just granted: being in the docker group is equivalent to having root on that machine. From there you can start a container that mounts the host’s entire disk and read or write it without restriction. This is not a harmless convenience shortcut. On your own server it is perfectly reasonable; on a machine shared with other people, leave the group alone and type sudo docker instead.

Step 5: Test the Installation

To make sure Docker is working properly, run a test container:

docker run hello-world

If everything is set up correctly, you’ll see a confirmation message telling you Docker is working.

docker run hello-world output with the Hello from Docker message outlined, confirming the installation

Your first docker-compose.yml

You have installed both pieces, but so far you have only used one. Docker Compose is what turns a long, unrepeatable command into a file you can save, version, read six months from now and bring back up on another machine without remembering a thing.

The difference is clearest side by side. This is starting Uptime Kuma (a service monitor) by hand:

docker run -d --restart=always -p 3001:3001 \
  -v uptime-kuma:/app/data --name uptime-kuma \
  louislam/uptime-kuma:1

It works. But three months from now, when you want to change the port or move the service to another server, that command will be long gone from your shell history. This is exactly the same thing, in a file called docker-compose.yml:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: always
    ports:
      - "3001:3001"
    volumes:
      - uptime-kuma:/app/data

volumes:
  uptime-kuma:

Line by line, because each one earns its place:

KeyWhat it does
services:The list of containers. There is one here, but there could be ten and they would all start together.
image:Which image to use. The :1 at the end is not decoration: it pins the major version. Without it you land on :latest, and the day the project jumps to version 2 you go with it without noticing.
restart: alwaysBrings the container back after a reboot or a crash.
ports:"3001:3001" reads as host_port : container_port, in that order. Swapping them is the most common mistake there is.
volumes:Where the data lives. This is the line that prevents disaster: without it, deleting the container deletes your entire configuration and history.

Save it in its own folder and bring it up:

mkdir -p ~/services/uptime-kuma
cd ~/services/uptime-kuma
nano docker-compose.yml     # paste the content from above
docker compose up -d

Every Compose command runs from the folder holding the file. These four cover 95% of what you will ever need:

docker compose ps        # what is running
docker compose logs -f   # follow the logs live
docker compose down      # stop and remove (volumes survive)
docker compose pull && docker compose up -d   # update

That last line is the one that wins people over: updating any service is two commands, always the same two, with no need to remember which flags you started it with. And if something breaks, you change one line in the file and bring it back up.

A warning about older tutorials. You will find countless examples that open with version: "3.8" on the first line. That is no longer needed: the Compose specification marks the field as obsolete and current versions ignore it, printing a warning. If a tutorial insists on it, it was written for Compose v1 and probably has more than that out of date.

You now have what the title of this guide promises. From here on, almost every service you will see on this blog is deployed with a file just like that one: only the image name and the ports change.

Next Steps

Done! Docker and Docker Compose are now set up on your system. From here you can start to:

Further Reading

To go deeper into Docker and Docker Compose, take a look at these sources:

Final Thoughts

Closing illustration with the word Conclusions, a lit lightbulb, check marks and charts

Docker and Docker Compose are not just handy tools, they are powerful allies for developers and DevOps teams. With this basic installation in place, you’re already on your way to streamlining your workflows and improving how you deploy applications.

If you found this article useful, share it with your colleagues and friends!

Still have questions? Leave them in the comments and I’ll be happy to help.

Next steps: what to deploy with Docker

With Docker and Docker Compose installed, you have the foundation to deploy just about any self-hosted service. Here are a few projects you can follow on this blog:

To expose these services securely without opening ports on your router, check out how to create a free Cloudflare tunnel.

Essential Docker commands

Some commands you’ll use constantly:

# List running containers
docker ps

# List all containers (including stopped ones)
docker ps -a

# View a container's logs
docker logs container-name

# Stop a container
docker stop container-name

# Remove a stopped container
docker rm container-name

# Update a service with docker-compose
cd /path/to/project
docker compose pull
docker compose up -d

Leave a Reply

Your email address will not be published. Required fields are marked *