Dockge — веб-интерфейс для Compose-стеков. В отличие от систем, которые прячут конфигурацию в своей базе, он работает с обычными compose.yaml на диске. Стек можно изменить в браузере, а затем открыть тот же каталог и выполнить привычный docker compose ps.
Это удобно для homelab, но требует аккуратной защиты: Dockge получает доступ к Docker socket и фактически может создавать привилегированные контейнеры, подключать любые каталоги хоста и выполнять команды. Публичная панель с простым паролем равна удалённому административному доступу к серверу.
Подготовка каталогов
Официальный путь для стеков — /opt/stacks. Каталог самого Dockge держим отдельно:
sudo mkdir -p /opt/dockge/data /opt/stacks
sudo chown -R "$USER":"$USER" /opt/dockge /opt/stacks
cd /opt/dockge
Проверьте UID и GID пользователя, которому должны принадлежать новые Compose-файлы:
id -u
id -g
В примере ниже используется 1000:1000. Замените значения результатом команд, если они отличаются.
Предполагается, что общая сеть для Caddy уже создана:
docker network inspect homelab_proxy >/dev/null 2>&1 \
|| docker network create homelab_proxy
compose.yaml
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
environment:
DOCKGE_STACKS_DIR: /opt/stacks
PUID: "1000"
PGID: "1000"
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
- type: bind
source: ./data
target: /app/data
- type: bind
source: /opt/stacks
target: /opt/stacks
networks:
- proxy
networks:
proxy:
external: true
name: homelab_proxy
Самое важное правило Dockge: путь каталога стеков слева и справа должен совпадать. Правильно:
- /opt/stacks:/opt/stacks
Неправильно:
- /opt/stacks:/app/stacks
Compose внутри управляемого стека использует пути хоста. Если Dockge видит каталог под другим именем, относительные и абсолютные mounts начинают указывать не туда.
Порт 5001 в этом варианте не опубликован. Панель доступна только Caddy через общую Docker-сеть.
Reverse proxy через Caddy
Добавьте в Caddyfile:
dockge.example.ru {
encode zstd gzip
reverse_proxy dockge:5001
}
Проверьте и примените конфигурацию:
cd /opt/caddy
docker compose exec caddy \
caddy validate --config /etc/caddy/Caddyfile
docker compose exec caddy \
caddy reload --config /etc/caddy/Caddyfile
Caddy автоматически проксирует WebSocket, который Dockge использует для живого терминала и вывода команд. Добавлять вручную Connection: upgrade не требуется.
Запустите Dockge:
cd /opt/dockge
docker compose config
docker compose up -d
docker compose ps
docker compose logs -f --tail=100 dockge
Откройте https://dockge.example.ru и создайте первого администратора с уникальным длинным паролем.
Если Caddy ещё не настроен, можно временно добавить:
ports:
- "127.0.0.1:5001:5001"
Затем подключиться через SSH-туннель:
ssh -L 5001:127.0.0.1:5001 user@server.example.ru
После настройки HTTPS удалите временную публикацию порта и пересоздайте контейнер через docker compose up -d.
Почему Docker socket — главный риск
Файл /var/run/docker.sock даёт доступ к Docker API. Процесс с таким доступом может запустить контейнер с mount корневой файловой системы хоста и изменить её. Опция read_only для socket не решает проблему: она относится к файловому mount, а не запрещает Docker API создавать и удалять ресурсы.
Поэтому:
- не публикуйте
5001:5001 на 0.0.0.0;
- для административной панели предпочитайте VPN или список разрешённых IP;
- не используйте пароль от других сайтов;
- обновляйте Dockge и Docker без многомесячных задержек;
- не открывайте Docker daemon по TCP без взаимной TLS-аутентификации;
- не подключайте socket к контейнерам, которым он не нужен.
Отдельный непривилегированный Linux-пользователь для каталогов полезен, но не изолирует действия через Docker socket от root-доступа к хосту.
Как устроены стеки
Каждый стек хранится в отдельном каталоге:
/opt/stacks/
├── uptime-kuma/
│ └── compose.yaml
├── vaultwarden/
│ ├── compose.yaml
│ └── .env
└── jellyfin/
└── compose.yaml
Название каталога становится естественным именем проекта. Не кладите несколько независимых compose.yaml прямо в /opt/stacks без подкаталогов.
Секреты не следует записывать в Compose-файл. Если сервис не поддерживает Docker secrets, храните .env с правами 600, исключайте его из Git и включайте в зашифрованную резервную копию:
chmod 600 /opt/stacks/vaultwarden/.env
Подключение существующего стека
Сначала выясните его текущее имя и состояние:
cd /старый/каталог
docker compose ls
docker compose ps
Остановите стек только если перенос каталога меняет пути, от которых зависят bind mounts:
docker compose down
sudo mkdir -p /opt/stacks/my-stack
sudo cp -a compose.yaml .env /opt/stacks/my-stack/
Не копируйте .env, если его нет. Перед запуском из нового каталога проверьте итоговую конфигурацию:
cd /opt/stacks/my-stack
docker compose config
docker compose up -d
В Dockge откройте меню и выполните Scan Stacks Folder. Если старый стек продолжает работать под другим Compose project name, можно получить второй набор контейнеров. Поэтому до запуска сравните docker compose ls, имена сетей и volumes.
Именованные volumes обычно получают префикс проекта. Перенос каталога может изменить этот префикс и создать пустой volume. Для важных данных сначала выполните:
docker volume ls
docker inspect "$(docker compose ps -q app)" --format '{{json .Mounts}}'
Не удаляйте старые volumes, пока новый стек не открыл реальные данные и не прошёл проверку.
Приватные registry
Официальный пример предлагает подключить Docker-конфигурацию с авторизацией. Делайте это только если стек действительно использует закрытый registry:
volumes:
- type: bind
source: /root/.docker
target: /root/.docker
read_only: true
В каталоге может находиться токен registry. Ограничьте права на хосте, не копируйте его в общий backup без шифрования и по возможности используйте короткоживущие токены с минимальными правами.
Типовые проблемы
Стек появился, но mounts указывают в пустые каталоги
Проверьте совпадение /opt/stacks:/opt/stacks, текущий каталог проекта и результат:
docker compose config
docker inspect CONTAINER --format '{{json .Mounts}}'
Не создавайте недостающие каталоги вслепую: сначала найдите прежнее хранилище данных.
Permission denied при сохранении compose.yaml
Сравните PUID/PGID и владельца:
stat -c '%u:%g %a %n' /opt/stacks
docker compose exec dockge id
Исправьте владельца конкретного каталога. Не используйте chmod -R 777: он даёт запись всем процессам хоста и маскирует неправильный UID.
Dockge не видит Docker
ls -l /var/run/docker.sock
docker compose logs --tail=100 dockge
docker info
Проверьте, что Docker daemon запущен и socket подключён по точному пути. Не заменяйте диагностику запуском privileged: true — Dockge этого не требует.
Терминал зависает за reverse proxy
Убедитесь, что Caddy и Dockge находятся в одной сети и используется обычный reverse_proxy dockge:5001. Caddy поддерживает WebSocket автоматически. Проверьте также расширения браузера и промежуточный CDN, который может разрывать долгие соединения.
Резервная копия
Нужно сохранить две части: внутренние данные Dockge и сами каталоги стеков.
backup_dir="$HOME/backups/dockge-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
cd /opt/dockge
docker compose stop dockge
sudo tar -C /opt -czf "$backup_dir/dockge-and-stacks.tar.gz" \
dockge stacks
docker compose start dockge
sha256sum "$backup_dir/dockge-and-stacks.tar.gz" \
> "$backup_dir/SHA256SUMS"
Архив может содержать .env и registry-токены. Шифруйте его перед отправкой во внешнее хранилище. Проверяйте восстановление в отдельном каталоге без подключения к рабочему Docker socket.
Обновление
После копии прочитайте заметки к релизу и выполните:
cd /opt/dockge
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --since=10m dockge
Откройте несколько стеков, проверьте редактор, compose config и журнал одного тестового запуска. Не нажимайте массовое обновление всех приложений сразу: у каждого сервиса свой формат данных и порядок миграции.
Официальные источники