MAATRIX / Блог / YunoHost в Docker Compose: готовый файл

YunoHost в Docker Compose: готовый файл

MAATRIX

Если вы искали docker-compose.yml для YunoHost, чтобы поднять панель одной командой рядом с остальными контейнерами — короткий честный ответ: так это не работает, и проект прямо об этом говорит. YunoHost устроен не как приложение, а как целая операционная система с собственным управлением сетью, почтой и firewall, поэтому загонять его в контейнер приходится с оговорками. Ниже — рабочий Dockerfile и compose-файл для тестового стенда, объяснение, почему это именно тестовый стенд, а не прод, и что делать дальше, когда вы решите, что панель вам подходит.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое YunoHost и почему его обычно не ставят в Docker

YunoHost — это не «ещё одно веб-приложение», а дистрибутив-надстройка над Debian, которая после установки берёт под свой контроль всю машину: поднимает Nginx как единый фронт для всех сайтов, Postfix и Dovecot для почты, свой LDAP-каталог пользователей и единый вход (SSO) между приложениями, fail2ban, конфигурацию firewall через yunohost firewall, и системный каталог из сотен готовых приложений — от Nextcloud и WordPress до Mastodon и Jitsi, которые ставятся одной командой из веб-панели или CLI.

Официальный способ установки — это скрипт, который вы запускаете на чистом Debian 12 «в лоб»:

curl https://install.yunohost.org | bash

Скрипт разворачивает всё перечисленное прямо на хост-системе: правит /etc/hosts, sudoers, systemd-юниты, iptables/nftables, слушает порты 80, 443, 25, 465/587, 993, 995. Именно поэтому классический docker-контейнер — с одним процессом и минимальной изоляцией — YunoHost не подходит по умолчанию: приложению из его каталога нужен полноценный systemd, прямой доступ к сети хоста и возможность управлять firewall, а не «песочница» с проброшенными портами.

Когда всё-таки оправдан Docker-запуск

Несмотря на всё сказанное, контейнер с YunoHost — рабочий инструмент, если правильно понимать его роль:

  • Обкатать каталог приложений перед покупкой сервера. Понять, ставится ли нужный вам сервис (например, Nextcloud или Vaultwarden) через YunoHost так, как вы ожидаете, и насколько удобна админ-панель.
  • Демо для команды. Показать коллегам интерфейс и логику единого входа без выделения отдельной машины.
  • Одноразовое CI/тестовое окружение. Поднять, проверить сценарий, снести — без риска для рабочего сервера.
  • Изучить обновления и миграции. Прогнать yunohost tools upgrade на копии, прежде чем повторять на боевой системе.

Если ваша цель — реальный почтовый сервер, публичный сайт с несколькими доменами и SSO для команды на постоянной основе, контейнер — не финальная точка, а лишь черновик перед установкой на отдельный VPS (об этом — в последнем разделе).

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Готовый Dockerfile и docker-compose.yml для тестового стенда

Полноценный docker-образ YunoHost под все архитектуры проект не публикует как продакшен-артефакт, поэтому надёжнее собрать минимальный systemd-контейнер самостоятельно и внутри него выполнить тот же официальный установочный скрипт, что и на голом сервере. Так вы получаете предсказуемое поведение — ровно то же, что описано в документации YunoHost, только внутри Docker.

Dockerfile:

FROM debian:12-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
        systemd systemd-sysv dbus sudo curl wget gnupg2 \
        ca-certificates locales iproute2 iptables \
    && rm -rf /var/lib/apt/lists/* \
    && sed -i 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/' /etc/locale.gen \
    && locale-gen

# YunoHost требует полноценный systemd как init-процесс
STOPSIGNAL SIGRTMIN+3
CMD ["/lib/systemd/systemd"]

docker-compose.yml:

services:
  yunohost-test:
    build: .
    container_name: yunohost-test
    hostname: yunohost-test
    privileged: true
    tmpfs:
      - /run
      - /run/lock
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
      - yunohost-etc:/etc/yunohost
      - yunohost-apps:/var/www
      - yunohost-mail:/var/mail
    ports:
      - "80:80"
      - "443:443"
      - "25:25"
      - "465:465"
      - "587:587"
      - "993:993"
      - "22:2222"
    restart: unless-stopped

volumes:
  yunohost-etc:
  yunohost-apps:
  yunohost-mail:

Ключевой момент — privileged: true и проброс /sys/fs/cgroup. Без этого systemd внутри контейнера не запустится, а без работающего systemd не встанут ни Nginx, ни Postfix, ни один из юнитов, которые ставит YunoHost. Это стандартный паттерн для запуска «системных» дистрибутивов в Docker (тот же приём используют для тестовых образов CentOS/Fedora с systemd) — но у него есть цена, о которой ниже, в разделе про ограничения. SSH внутри контейнера пробрасывается на нестандартный порт 2222 хоста, чтобы не конфликтовать с SSH самого хост-сервера.

Установка YunoHost внутри контейнера

Соберите образ и поднимите контейнер:

docker compose up -d --build

Зайдите внутрь и запустите штатный установщик — тот же самый, что используется при установке на голое железо:

docker compose exec yunohost-test bash
curl https://install.yunohost.org | bash

Скрипт задаст пару вопросов (подтверждение перезаписи /etc/hosts, согласие с изменением системы) и установит базовый набор пакетов. После перезапуска systemd-юнитов внутри контейнера (сам контейнер перезагружать не нужно — процессы поднимутся штатно) выполните постустановку:

yunohost tools postinstall \
  --domain yunohost-test.local \
  --password 'ЗамениНаСвойСложныйПароль'

Для лабораторного стенда домен можно взять локальный (.local) или временный вида test.nip.io, если хочется получить настоящий SSL от Let's Encrypt через встроенный ACME-клиент YunoHost — но для боевой публикации домен должен реально резолвиться на IP сервера. После постустановки админка доступна по адресу контейнера или хоста:

https://<IP-хоста>/yunohost/admin

При первом заходе браузер предупредит о самоподписанном сертификате (если не привязан настоящий домен) — это ожидаемо для тестового стенда.

Ограничения и грабли контейнерного запуска

Прежде чем считать такую установку рабочей, честно проговорим, что в этой схеме не идеально:

  • privileged: true почти отменяет изоляцию Docker. Контейнер получает доступ к устройствам и возможностям ядра хоста, сравнимый с правами root на самой машине. Плюс контейнера здесь не «безопасность», а удобство пересборки и удаления — не путайте одно с другим.
  • Конфликт портов с хостом. Если на сервере уже крутится свой Nginx, Traefik или другой процесс на 80/443, поднять YunoHost-контейнер с такими же портами не выйдет — либо освобождайте порты на хосте, либо разводите по разным машинам. Если реверс-прокси на хосте нужен для других контейнеров, посмотрите отдельно Traefik как reverse proxy для Docker — совмещать его с YunoHost на одном порту 443 без дополнительной настройки не получится, панели конкурируют за роль единственного фронта.
  • Почтовые порты часто заблокированы у провайдера. Многие хостинги закрывают исходящий 25 порт по умолчанию из-за спама — уточняйте это до установки, а не после, когда обнаружите, что письма не уходят.
  • fail2ban и iptables внутри контейнера работают ограниченно. Правила firewall, которые накатывает YunoHost, применяются к сетевому стеку контейнера, но при некоторых конфигурациях Docker (особенно с собственными iptables-цепочками самого Docker) правила могут конфликтовать или не применяться предсказуемо — это нужно проверять руками через iptables -L, а не считать данностью.
  • Не все приложения каталога переживут вложенность. Приложения, которым самим нужен Docker (в YunoHost есть и такие интеграции) или доступ к специфичным модулям ядра, внутри уже контейнеризированной системы могут не завестись.
  • SSL для почты внутри теста не имеет смысла проверять до конца — без реального домена, резолвящегося на публичный IP, полноценно протестировать связку Postfix/Dovecot с TLS не получится, только заготовку конфигурации.

Ни один из этих пунктов не критичен для тестового стенда — но все они означают, что результаты нельзя переносить «как есть» на прод и объявлять систему готовой к работе с реальной почтой и пользователями.

Как перейти на нормальную установку на VPS

Когда каталог приложений и логика YunoHost вас устроили, следующий шаг — установка напрямую на чистый Debian 12 на отдельном VPS, без контейнера. Разница принципиальная:

Docker-стенд (этот гайд)Прямая установка на VPS
Systemd и сетьчерез privileged и проброс cgroup, с оговоркаминативно, без обходных путей
Почтовые портычасто конфликтуют с хостом/провайдеромвыделенный IP, порты свободны
SSL для доменатребует внешнего резолва доменаобычный Let's Encrypt через встроенный ACME
Firewall/fail2banограниченно предсказуемыработают как задумано разработчиками
Назначениетест, демо, обкатка каталогабоевая почта, сайты, SSO для команды

Практически это означает: берёте отдельный VPS с чистым Debian 12, заходите по SSH и на самом хосте выполняете тот же curl https://install.yunohost.org | bash — без Docker, без privileged, без проброса портов. Если вы уже привыкли ставить сервисы через Docker Compose на этом же сервере для других задач, посмотрите установку Docker на Ubuntu 24.04 с нуля — но саму YunoHost на этот сервер лучше не накладывать поверх уже занятых портов 80/443, ей нужна отдельная машина, где она единственный хозяин сети. Для сравнения, что получится в итоге на выходе — панель, из которой в один клик разворачивается тот же Nextcloud, — можно посмотреть в отдельном гайде про установку и настройку Nextcloud на VPS, это один из самых частых сценариев использования YunoHost.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли использовать docker-compose из этого гайда в проде?

Не рекомендуется. Контейнер с privileged: true подходит для теста и демо, но по изоляции и предсказуемости сети он ничем не лучше прямой установки на хост, а по сложности отладки — хуже. Для боевой почты и продакшен-сайтов ставьте YunoHost напрямую на VPS.

Почему YunoHost вообще не делает официальный production-образ для Docker?

Потому что архитектура панели построена вокруг управления всей ОС — сетью, firewall, systemd-юнитами, LDAP — а не вокруг одного изолированного процесса, как задумана модель Docker. Разработчики прямо указывают, что рекомендованный способ — установка на выделенную машину или VM.

У меня провайдер блокирует 25 порт, что делать с почтой?

Уточните у провайдера возможность разблокировки для конкретного IP (у части хостингов это делается по заявке), либо настройте отправку через внешний SMTP-relay — сам YunoHost такую переадресацию поддерживает через конфигурацию Postfix.

Что будет с данными, если пересобрать контейнер (docker compose up --build)?

Если используются вынесенные тома (yunohost-etc, yunohost-apps, yunohost-mail из примера), пользовательские данные и конфигурация сохранятся. Пересоздаётся сама файловая система контейнера и systemd-состояние — учтите это перед экспериментами с обновлением базового образа.

Нужен ли реальный домен для тестового стенда?

Нет, для проверки каталога приложений и интерфейса достаточно локального имени. Реальный домен, резолвящийся на публичный IP, понадобится только когда вы захотите получить настоящий SSL-сертификат и открыть сервис наружу.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →