This guide covers installing Docker Engine + Docker Compose from the official Docker repository, through deploying your first app with a docker-compose.yml. All commands use an auto-detect approach for architecture & OS version to avoid errors from wrong codenames or bad copy-pastes.
System Requirements
- OS: Ubuntu 20.04 / 22.04 / 24.04 or Debian 11 / 12
- Architecture: x86_64 (amd64) or arm64
sudoor root access- Internet connection
apt install docker.io) — that version is outdated and often conflicts with docker-ce. Use the official Docker repo in this guide.Part 1 — Install Docker Engine
-
1
Remove Old Versions (if any)
Remove all old Docker packages at once. Ignore errors if the packages aren't installed yet.
apt remove -y docker.io docker-doc docker-compose docker-compose-v2 containerd runc apt autoremove -y
-
2
Update & Install Prerequisites
apt update && apt install -y ca-certificates curl gnupg
-
3
Create Directory for GPG Key
mkdir -p /etc/apt/keyrings
-
4
Download Docker's Official GPG Key
The command below automatically detects Ubuntu or Debian — no need to choose manually.
. /etc/os-release curl -fsSL https://download.docker.com/linux/$ID/gpg -o /tmp/docker.gpg gpg --dearmor -o /etc/apt/keyrings/docker.gpg /tmp/docker.gpg rm /tmp/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg
-
5
Add the Docker Repository
The
teecommand below writes the repository line to thedocker.listfile automatically — with the architecture, distro, and codename filled in.This is the step that most often causes errors. Do not type thedeb [...]line directly in the terminal — it must be written to thedocker.listfile. Use theteecommand below.. /etc/os-release echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$ID $VERSION_CODENAME stable" | tee /etc/apt/sources.list.d/docker.list
Verify the file contents are correct:
cat /etc/apt/sources.list.d/docker.list
Example correct output (Ubuntu 22.04 amd64):deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable -
6
Install Docker Engine + Plugins
apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
-
7
Start & Enable Docker on Boot
enable --now= start immediately + run automatically on every reboot.Don't skip this! Without this step,docker compose upwill fail with "Cannot connect to the Docker daemon... Is the docker daemon running?" — even though the installation succeeded.systemctl enable --now docker systemctl enable --now containerd
-
8
Verify Installation
docker --version docker compose version docker run hello-world
If you see "Hello from Docker!", the installation was successful.
-
9
Run Docker Without sudo (Optional)
usermod -aG docker $USER newgrp docker # or logout & log back in
Security note: Users in thedockergroup have root-equivalent access. Only add trusted users.
Part 2 — Deploy Your First App (Docker Compose)
As an example, we'll deploy Filebrowser (a web file manager). The pattern is the same for any other app: create a folder → write docker-compose.yml → run it.
-
1
Create a Folder
mkdir -p ~/filebrowser && cd ~/filebrowser mkdir -p /srv/downloads # folder to be managed
-
2
Create docker-compose.yml
nano docker-compose.yml
Fill it with the following configuration:
services: filebrowser: image: filebrowser/filebrowser:latest container_name: filebrowser restart: unless-stopped ports: - "8080:80" # left = host port (change if 8080 is taken) environment: - FB_DATABASE=/database/filebrowser.db - FB_ROOT=/srv # root folder to manage - FB_LOG=stdout - FB_NOAUTH=false # MUST be false to require login - TZ=Asia/Jakarta volumes: - /srv/downloads:/srv # file storage, point to a large disk - filebrowser_db:/database # database (named volume, auto-created) - filebrowser_config:/config healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/health"] interval: 30s timeout: 5s retries: 3 volumes: filebrowser_db: filebrowser_config:Save: Ctrl + O → Enter. Exit: Ctrl + X.
Tip: Always userestart: unless-stoppedso the container automatically comes back up after a server reboot. -
3
Run It
-d= run in the background (detached). Docker will automatically download the image and start the container.docker compose up -d
-
4
Check Status
docker compose ps # service status docker compose logs -f # view logs (Ctrl+C to exit)
Open in browser:
http://SERVER-IP:8080. Default Filebrowser login: useradmin, passwordadmin— change it immediately after logging in.
Part 3 — Command Cheatsheet
# Containers docker ps # running containers docker ps -a # all containers (including stopped) docker logs -f <name> # view logs docker exec -it <name> bash # enter container shell # Compose (run from the folder containing docker-compose.yml) docker compose up -d # start all services docker compose down # stop & remove containers docker compose restart <svc> # restart a specific service docker compose pull && docker compose up -d # update image then restart # Cleanup docker system df # check disk usage docker system prune -a # remove unused resources (use with caution)
Part 4 — Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Cannot connect to the Docker daemon |
Daemon not running / not enabled | systemctl enable --now docker (Part 1, Step 7) |
Unable to locate package docker-ce |
Docker repo not added | Redo Part 1 Step 5, then apt update |
apt update → 404 / Release file not found |
OS codename not yet supported by Docker repo | Check cat /etc/os-release, verify VERSION_CODENAME is correct |
Conflict with docker.io |
Old packages not fully removed | Go back to Part 1 Step 1, remove old packages first |
Unit docker.service is masked |
Service is masked | systemctl unmask docker && systemctl enable --now docker |
docker --version works but daemon is stopped |
docker-ce install incomplete | apt install --reinstall -y docker-ce, then enable --now |