Containers

Install Dockge on Ubuntu: Self-Hosted Docker Compose Manager

Managing Docker Compose stacks by hand gets old fast. You SSH into the box, edit a compose.yaml in vim, run docker compose up -d, then tail logs in a second terminal to see whether anything caught fire. Dockge folds all of that into one web page: edit the compose file in the browser, deploy it, and watch the container logs stream live on the same screen.

Original content from computingforgeeks.com - post 171579

This guide walks through how to install Dockge on Ubuntu, create the first admin account, deploy a real stack, and put the whole thing behind Nginx with HTTPS. Dockge comes from the developer behind Uptime Kuma, and it shows: the interface is light, fast, and does one job well instead of trying to manage every corner of your Docker host like Portainer does.

Ran through this on Ubuntu 26.04 in September 2026 with Docker Engine 29.8 and Dockge 1.5. The same steps apply on 24.04, since the Docker repo carries both releases.

Where Dockge fits next to Portainer and Komodo

Dockge is not trying to be a full container platform. It manages Compose stacks that live as plain compose.yaml files on disk, and that is the whole point. Your stacks stay readable and portable, so if you ever drop Dockge, the files still work with a bare docker compose up -d. That is a real difference from tools that store stack definitions in their own database.

ItemDockgePortainerKomodo
ScopeCompose stacks onlyFull Docker + Swarm + K8sMulti-server builds and deploys
Stack storagePlain files in /opt/stacksInternal databaseGit repos + database
In-browser compose editingFirst-classLimitedYes
FootprintTiny (one container)MediumMedium, plus agents
Best forHomelab and single-host stacksBroad Docker managementGitOps across many hosts

If you run a handful of Compose stacks on one or two hosts, Dockge is the leaner fit. For fleet-wide GitOps, Komodo is the heavier tool built for that job.

Prerequisites

You need an Ubuntu 26.04 or 24.04 host with a sudo user, Docker Engine with the Compose plugin (installed below), and TCP port 5001 free for the web UI. If you already run Docker from the Docker and Compose setup, skip straight to installing Dockge.

Dockge itself is cheap to run. The container is a small Node service with a SQLite database, so it sips RAM. What actually sizes the box is the stacks you point it at, not Dockge. A host that comfortably runs your containers already has the headroom for Dockge on top. The lab here used 2 vCPU and 4 GB of RAM, which is a floor for following along rather than a target to plan production around.

1. Install Docker Engine

Dockge ships as a container, so Docker Engine and the Compose plugin come first. Add Docker’s official repository, which carries the current engine rather than the older build in the Ubuntu archive. Set up the keyring and repo:

sudo apt-get update
sudo apt-get install -y ca-certificates curl
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. The line below resolves your release codename automatically, which is why the exact same command works on 26.04 and 24.04. Docker publishes both, so nothing needs hard-coding:

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

Refresh the index and pull in the engine, CLI, containerd, and the Compose plugin:

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

Confirm the engine and Compose plugin are both present:

docker --version
docker compose version

Both print a version and the service reports active:

Docker version 29.8.1, build 4a63305
Docker Compose version v5.5.1

Add your user to the docker group so you can run Compose without sudo. Log out and back in (or run newgrp docker) for the group change to take effect:

sudo usermod -aG docker $USER

2. Install Dockge

Dockge keeps two directories: one for its own compose file and data, and one that holds every stack it manages. Create both. The stacks path must be a full, absolute path, and the same path has to appear on both sides of the volume mount later, so /opt/stacks is the sane default:

sudo mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

Pull the official compose file into the Dockge directory:

sudo curl -fsSL https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml

Look at what it defines before starting it:

cat compose.yaml

The important lines are the Docker socket mount, the data volume, and the stacks directory, which is passed to Dockge through an environment variable:

services:
  dockge:
    image: louislam/dockge:1
    restart: unless-stopped
    ports:
      - 5001:5001
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data
      - /opt/stacks:/opt/stacks
    environment:
      - DOCKGE_STACKS_DIR=/opt/stacks

That socket mount is how Dockge talks to Docker, and it is also the reason Dockge effectively has root on the host. Keep the UI behind authentication and off the public internet. Bring it up:

sudo docker compose up -d

Docker pulls the image and starts the container. Check that it is healthy and listening on 5001:

docker compose ps

The container shows as up and healthy with the port published:

NAME              IMAGE               STATUS                   PORTS
dockge-dockge-1   louislam/dockge:1   Up 6 minutes (healthy)   0.0.0.0:5001->5001/tcp

Here is the engine, the Compose plugin, and the running Dockge container together on the test box:

Terminal showing Docker and Docker Compose versions with the Dockge container healthy on Ubuntu

If ufw is active on this host, open the port so you can reach the UI from your LAN. A fresh Ubuntu server image usually has ufw disabled, in which case you can skip this:

sudo ufw allow 5001/tcp

3. Create your admin account

Open http://SERVER_IP:5001 in a browser. On first load Dockge sends you to a setup page to create the single admin account. There is no default password to change and no email step, just a username and a password you pick.

Dockge first-run setup page creating the admin account on Ubuntu

Pick a strong password (this account can start and stop anything on the Docker host) and submit. Dockge logs you straight in to the home view, which shows your stack counts and a live tile for active, exited, and inactive stacks.

Dockge dashboard home view listing Docker Compose stacks on Ubuntu

The home screen also has a handy trick: paste a long docker run command into the Docker Run box, click Convert to Compose, and Dockge turns it into a compose file you can save as a stack. It is the fastest way to migrate a one-off container into something version controlled.

4. Deploy your first stack

Click Compose in the top left to start a new stack. Give it a name (that name becomes a folder under /opt/stacks), then paste a compose definition into the editor. A small two-service stack is enough to see how it behaves, an Nginx web server plus a Redis cache:

services:
  web:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "8080:80"
  cache:
    image: redis:alpine
    restart: unless-stopped

Hit Deploy. Dockge writes the file to /opt/stacks/webapp/compose.yaml, runs the equivalent of docker compose up -d, and flips the stack to active. The stack page then shows each container with its state and published ports, the compose file on the right, and a terminal panel streaming the live logs.

Dockge managing a Docker Compose stack showing running containers and live logs on Ubuntu

Because the file lives at a real path on disk, you can edit it in the browser or in vim on the server, and both stay in sync. The Edit, Restart, Update, and Stop buttons map to the Compose commands you already know, so nothing about the stack is locked inside Dockge.

If you drop compose files into /opt/stacks from the shell, use the Scan Stacks Folder item in the top-right menu and Dockge picks them up.

5. Put Dockge behind Nginx with HTTPS

Port 5001 over plain HTTP is fine on a trusted LAN, but anything that can start containers deserves TLS and a real hostname. Put Dockge behind Nginx as a reverse proxy and let certbot handle the certificate. Set two shell variables first so the rest of the step pastes as-is:

export DOCKGE_DOMAIN="dockge.example.com"
export ADMIN_EMAIL="[email protected]"

Point an A record for that hostname at the server’s IP, then install Nginx:

sudo apt-get install -y nginx

Create the site file. Dockge drives its live terminal and log streaming over WebSockets, so the proxy has to pass the Upgrade and Connection headers, otherwise those features break even though the page itself loads:

sudo vim /etc/nginx/sites-available/dockge

Add the following server block. Leave DOCKGE_DOMAIN_HERE as a literal placeholder for now; a sed command in a moment swaps in your real hostname:

server {
    listen 80;
    server_name DOCKGE_DOMAIN_HERE;

    location / {
        proxy_pass http://127.0.0.1:5001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Substitute your hostname, enable the site, drop the default one, and test the config:

sudo sed -i "s/DOCKGE_DOMAIN_HERE/${DOCKGE_DOMAIN}/g" /etc/nginx/sites-available/dockge
sudo ln -sf /etc/nginx/sites-available/dockge /etc/nginx/sites-enabled/dockge
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t

A clean config reports the syntax is ok and the test is successful:

nginx: configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload Nginx, then let certbot issue the certificate and rewrite the vhost for HTTPS. The --nginx plugin uses the HTTP-01 challenge, which works with any DNS provider as long as port 80 is reachable from the internet:

sudo systemctl reload nginx
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d "${DOCKGE_DOMAIN}" --non-interactive --agree-tos --redirect --no-eff-email -m "${ADMIN_EMAIL}"

Certbot installs the certificate, adds the 443 server block, and sets up the HTTP to HTTPS redirect. Confirm renewal is wired up:

sudo certbot renew --dry-run

Open port 443 (and 80 for the redirect and future renewals) if a firewall is in front of the box, and reach Dockge at https://dockge.example.com with a valid certificate.

Issuing the certificate without a public port 80

If the server sits on a private LAN behind NAT with no inbound port 80, or you want a wildcard certificate, use the DNS-01 challenge instead. It proves domain ownership through a DNS TXT record, so no inbound HTTP is needed. Certbot has a plugin per provider:

DNS providerCertbot plugin
Cloudflarepython3-certbot-dns-cloudflare
Route 53python3-certbot-dns-route53
DigitalOceanpython3-certbot-dns-digitalocean
Google Cloud DNSpython3-certbot-dns-google
Linodepython3-certbot-dns-linode
RFC2136 (BIND)python3-certbot-dns-rfc2136

Substitute your provider’s plugin below. This shows Cloudflare, where you store a scoped API token in a credentials file and point certbot at it:

sudo apt-get install -y python3-certbot-dns-cloudflare
echo "dns_cloudflare_api_token = your-scoped-token" | sudo tee /etc/letsencrypt/cloudflare.ini
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "${DOCKGE_DOMAIN}" --non-interactive --agree-tos -m "${ADMIN_EMAIL}"

Unlike the --nginx plugin, certonly only fetches the certificate. It does not edit your Nginx config, so the TLS server block is on you. Swap the plain-HTTP site created earlier for an HTTPS version:

sudo vim /etc/nginx/sites-available/dockge

Replace the contents with the block below. It terminates TLS on 443, redirects plain HTTP to HTTPS, and keeps the same WebSocket headers so the live terminal survives the switch. Leave DOCKGE_DOMAIN_HERE as a placeholder again:

server {
    listen 80;
    server_name DOCKGE_DOMAIN_HERE;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name DOCKGE_DOMAIN_HERE;

    ssl_certificate     /etc/letsencrypt/live/DOCKGE_DOMAIN_HERE/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/DOCKGE_DOMAIN_HERE/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Substitute the hostname across the file, test the config, and reload:

sudo sed -i "s/DOCKGE_DOMAIN_HERE/${DOCKGE_DOMAIN}/g" /etc/nginx/sites-available/dockge
sudo nginx -t
sudo systemctl reload nginx

Certbot’s systemd timer renews the certificate on its own. A renewal only swaps the files on disk, so pair it with an Nginx reload hook or a periodic sudo systemctl reload nginx to pick up the fresh certificate.

6. Update Dockge

Updates pin to the 1 major tag, so a pull grabs the latest release in that line without a surprise major bump. From the Dockge directory:

cd /opt/dockge
sudo docker compose pull
sudo docker compose up -d

Compose recreates the container only if the image changed, and your stacks keep running untouched because they are separate Compose projects. You can also trigger this from the UI with the Update button on the Dockge container itself.

Fixing the problems you will hit

The live terminal and logs are blank behind a reverse proxy

This is the one that trips people up. Dockge’s terminal and log streaming run over a WebSocket, and a proxy without the upgrade headers refuses the connection. In testing, a WebSocket handshake through a correct vhost returns 101 Switching Protocols, while the same request through a vhost missing proxy_http_version 1.1 and the Upgrade and Connection headers returns 400 Bad Request. The page loads either way, which is what makes it confusing. If your logs panel is empty, the fix is the three proxy lines from the vhost above.

Error: “permission denied while trying to connect to the Docker daemon socket”

Dockge shows this when its container cannot read /var/run/docker.sock. It almost always means the socket mount is missing from the compose file or the host socket has non-default permissions. Confirm the /var/run/docker.sock:/var/run/docker.sock line is present, then recreate the container with sudo docker compose up -d --force-recreate.

A stack you created on disk does not appear

Dockge only lists stacks under the directory it was told about, which is /opt/stacks from DOCKGE_STACKS_DIR. A stack elsewhere, or one added while Dockge was running, will not show until you use Scan Stacks Folder. If a stack still refuses to appear, check that its file is named compose.yaml inside its own subfolder, because a loose file in the root of the stacks directory is ignored.

Keep reading

Best UI Applications for Managing Docker Containers Containers Best UI Applications for Managing Docker Containers Install Docker and Run Containers on Ubuntu 24.04|22.04 Containers Install Docker and Run Containers on Ubuntu 24.04|22.04 Install UniFi OS Server on Ubuntu 24.04 LTS Containers Install UniFi OS Server on Ubuntu 24.04 LTS Install and Self-Host Karakeep with Docker AI Install and Self-Host Karakeep with Docker Qdrant vs Weaviate vs Milvus vs pgvector Benchmarked AI Qdrant vs Weaviate vs Milvus vs pgvector Benchmarked DeepSeek Harness vs Claude Code: What Is Actually Different AI DeepSeek Harness vs Claude Code: What Is Actually Different

Leave a Comment

Press ESC to close