Руководства по развёртыванию, секретам, доменам и управлению контейнерами.

Манифесты: варианты и откуда брать значения

Все поля манифеста, шесть готовых примеров под разные проекты и таблица «где взять каждое значение» — для GitHub и GitLab. · обновлено 2026-10-13

Справочник по полям манифеста и готовые примеры под разные проекты. Общая последовательность действий — в статье «Как добавить приложение через панель».

1. Как устроен манифест

Манифест — это JSON, который вы вставляете в панели в поле манифеста и сохраняете. Панель передаёт его агенту на вашей машине, агент сохраняет файл и дальше работает по нему: клонирует репозиторий, собирает образ, запускает контейнеры.

Обязательное поле одно — app (имя приложения). Остальные имеют значения по умолчанию, поэтому минимальный манифест состоит из адреса репозитория, ветки и файла-инструкции.

2. Поля манифеста

Поле По умолчанию Зачем
app — (обязательно) имя приложения: строчные латинские буквы, цифры, -, _, до 32 символов; по нему помечаются контейнеры и оно показывается в панели
repo_url — адрес репозитория по HTTPS (или ssh://, git@…); нужен для клонирования
branch main ветка, из которой разворачивается код; у многих проектов основная ветка master — уточните на странице репозитория
subdir . папка внутри репозитория, где лежит проект (для монорепозиториев), например services/api
compose_file docker-compose.yml имя compose-файла внутри subdir; если файл есть — приложение считается compose-проектом
services [] список сервисов compose для запуска; пусто — запускаются все. Например ["api","worker"]
dockerfile Dockerfile имя Dockerfile — используется, когда compose-файла нет
tag apppilot/<app>:latest имя и метка образа, который собирается из Dockerfile
image — готовый образ из реестра (например nginx:1.27-alpine): вместо сборки будет docker pull; для проекта с собственным Dockerfile не указывается
run_args [] аргументы запуска для проекта без compose: публикация портов (-p), тома (-v), параметры (--memory=512m)
env {} переменные окружения приложения, например {"APP_ENV":"production"}; передаются и в compose-запуск, и в отдельный контейнер
health_url — адрес для проверки кнопкой «Health-check», например http://127.0.0.1:8080/ (запрос идёт с самой машины)
health_timeout 5.0 сколько секунд ждать ответа по health_url

Логина и токена в манифесте нет. Доступ к приватному репозиторию задаётся отдельно — в карточке токена на странице «Контейнеры». Токен хранится на вашей машине и не попадает ни в манифест, ни в базу панели, ни в журналы.

3. Пример 1: публичный репозиторий с docker-compose

Самый частый случай: код в корне репозитория, инструкция — docker-compose.yml.

{
  "app": "webapp",
  "repo_url": "https://github.com/acme/webapp.git",
  "branch": "main",
  "subdir": ".",
  "compose_file": "docker-compose.yml",
  "health_url": "http://127.0.0.1:8080/"
}

Порты наружу публикует сам compose-файл (секция ports), панель к этому не причастна. Если health_url не указать, «Health-check» покажет только состояние и health-статусы контейнеров.

4. Пример 2: приватный репозиторий на GitHub

Манифест отличается от примера 1 только адресом репозитория — токена в нём нет. Токен задаётся отдельно: «Контейнеры» → выберите машину и приложение → карточка токена → вставьте токен → «Сохранить токен». Панель покажет «токен: задан», а сам токен обратно не покажет никогда.

{
  "app": "webapp",
  "repo_url": "https://github.com/acme/webapp.git",
  "branch": "main",
  "compose_file": "docker-compose.yml"
}

Где взять адрес: на странице репозитория — кнопка Code → вкладка HTTPS → скопировать адрес (он оканчивается на .git).

Где взять токен (нужен только на чтение):

  • GitHub → аватар → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token: Repository access — «Only select repositories» и ваш репозиторий; Permissions → Repository permissions → Contents: Read-only. Такой токен не даёт доступа ни к чему, кроме чтения кода.
  • Либо классический токен (Tokens (classic)) с единственной областью repo.

Логин при работе по токену GitHub не проверяет: поле «Логин» можно оставить пустым — агент подставит oauth2. Важен сам токен.

Токен — это пароль. Храните его в надёжном месте и выдавайте минимальные права: чтение кода. Если токен попал к посторонним — отзовите его на хостинге и сохраните в панели новый.

5. Пример 3: приватный репозиторий на GitLab

{
  "app": "shop-api",
  "repo_url": "https://gitlab.com/acme/shop-api.git",
  "branch": "main",
  "subdir": ".",
  "compose_file": "docker-compose.yml"
}

Токен (любой из вариантов, все — только на чтение репозитория):

  • Project Access Token (рекомендуется): проект → Settings → Access tokens → Add new token, роль Reporter, область read_repository.
  • Deploy Token: проект → Settings → Repository → Deploy tokens → включить read_repository. GitLab сам выдаёт логин и токен — логин берите из карточки токена, а не произвольный.
  • Личный токен: профиль → Edit profile → Access tokens → область read_repository.

Логин для project access token и личного токена — любое непустое значение (GitLab его не проверяет): можно указать oauth2 или имя из карточки токена. Для deploy token логин берётся из карточки токена и вводится в поле «Логин» рядом с токеном.

Для GitLab берите адрес из кнопки Code → Clone with HTTPS и убедитесь, что он ведёт на тот же домен, на котором создан токен (например gitlab.com): если хостинг перенаправляет на другой домен, авторизация по токену теряется.

6. Пример 4: монорепозиторий со своим compose-файлом

Проект лежит в подпапке, а compose-файл называется иначе:

{
  "app": "shop-front",
  "repo_url": "https://gitlab.com/acme/monorepo.git",
  "branch": "release",
  "subdir": "apps/frontend",
  "compose_file": "compose.prod.yml",
  "services": ["web", "proxy"]
}

Из одного репозитория можно развернуть несколько приложений — сохраните два манифеста с разными app и разными subdir. Требование одно: имена приложений должны быть разными, а сервисы — не занимать один и тот же порт на машине.

7. Пример 5: проект без compose, только Dockerfile

Если compose-файла нет, агент собирает образ из Dockerfile и запускает одиночный контейнер. Порт публикуется через run_args:

{
  "app": "tictactoe",
  "repo_url": "https://gitlab.com/my/tictactoe-app.git",
  "branch": "main",
  "dockerfile": "Dockerfile",
  "tag": "tictactoe:latest",
  "run_args": ["-p", "0.0.0.0:8080:80"],
  "health_url": "http://127.0.0.1:8080/"
}

8. Пример 6: готовый образ из реестра

Свой код не нужен — например, база данных или кэш для вашего приложения:

{
  "app": "cache",
  "image": "redis:7-alpine",
  "run_args": ["-p", "127.0.0.1:6379:6379", "--appendonly", "yes"]
}

Учтите: образ из реестра не содержит вашего кода, поэтому «Клонировать» и «Собрать» для него не нужны — достаточно «Запустить всё». Адрес 127.0.0.1 в run_args оставляет порт доступным только внутри машины (для базы или кэша это обычно то, что нужно).

9. Где взять каждое значение

Значение GitHub GitLab
Адрес репозитория (repo_url) страница репозитория → Code → HTTPS страница проекта → Code → Clone with HTTPS
Основная ветка (branch) на главной странице в переключателе веток; сменить — Settings → Branches → Default branch проект → Settings → Repository → Default branch
Токен для чтения кода Settings → Developer settings → Personal access tokens: fine-grained (Contents: Read-only) или classic с областью repo проект → Settings → Access tokens (read_repository) или Settings → Repository → Deploy tokens
Логин (поле «Логин») имя аккаунта или x-access-token — при токене значение не проверяется для project/личного токена — любое непустое (oauth2); для deploy token — логин из карточки токена
Токен (поле «Токен») сам токен (после закрытия страницы он не показывается — храните копию) сам токен
Файл-инструкция (compose_file, dockerfile) имя файла в репозитории; если он в подпапке — путь к папке в subdir, а в поле файла остаётся только имя то же
Порт приложения в проекте с compose — секция ports; в проекте с Dockerfile — строка EXPOSE подсказывает порт, а публикует его run_args то же

10. Частые ошибки в манифестах

Что происходит Причина Как исправить
панель не принимает манифест: «app: допустимы…» в имени приложения заглавные буквы, пробелы, точки, кириллица или длина больше 32 оставьте строчные латинские буквы, цифры, - и _, например shop-api
клонирование просит логин или отвечает «Authentication failed» приватный репозиторий без токена, заполнено только одно из полей логина/пароля, токен просрочен или хостинг перенаправляет на другой домен заполните оба поля, выпустите новый токен, возьмите адрес из кнопки «Clone» (при перенаправлении — конечный домен)
«ветка не найдена» в репозитории основная ветка master, а в манифесте main (или наоборот) посмотрите имя основной ветки на странице репозитория и поправьте branch
«compose-файл не найден» файл называется docker-compose.yaml, лежит в подпапке или не закоммичен проверьте compose_file и subdir; убедитесь, что файл есть в разворачиваемой ветке
сборка «пропускает» изменения в коде Docker переиспользует кэш слоёв нажмите «Пересобрать» (сборка без кэша), перед этим — «Клонировать репозиторий»
порт занят (address already in use) такой порт на машине уже слушает другое приложение назначьте другой порт в ports/run_args: у разных приложений порты на машине не должны совпадать
приложение не отвечает на «Health-check» health_url указывает не на тот порт или на внешний адрес проверку задавайте на адрес внутри машины: http://127.0.0.1:порт/
«Обновить образ» не даёт эффекта образ собирается на машине, в реестре его нет используйте «Пересобрать»

11. Что платформа не разрешает

Проверка идёт перед сборкой и запуском — и в панели, и на самой машине. Запрещено то, что даёт контейнеру права машины хоста:

Запрещено Почему
privileged: true, --privileged контейнер получает доступ к устройствам и ядру хоста
network_mode: host, --network host, network_mode: container:… контейнер живёт в сети машины: видит внутренние порты и сервисы
pid/ipc/uts/userns: host общие пространства имён с хостом
cap_add с SYS_ADMIN, NET_ADMIN, SYS_PTRACE, ALL и подобными capability, которые обходят изоляцию
devices, --device, --volumes-from, --sysctl проброс устройств и параметров ядра
security_opt: seccomp=unconfined, apparmor=unconfined, label=disable снимает защиту контейнера
тома с путями хоста вне каталога приложения, включая /var/run/docker.sock сокет Docker — это root на машине; чужие каталоги хоста — чужие данные
build.context и env_file с абсолютным путём или .. сборка и чтение файлов вне каталога приложения

Разрешено всё обычное: публикация портов, именованные тома и тома внутри каталога приложения, healthcheck, restart, лимиты, переменные окружения, cap_drop, read_only.

Если отказали, панель покажет конкретное нарушение — уберите эту настройку и повторите. Нужен полный контроль над контейнерами и доступ к системе машины — заказывайте виртуальную машину: там root выдаётся, и ограничений платформы нет.

12. Полезно знать

  • Переменные из env видны в контейнере как обычные переменные окружения. Секреты в манифесте допустимы, но помните: он хранится на вашей машине в открытом виде — для токенов и паролей лучше использовать отдельные механизмы (токен репозитория задаётся вне манифеста).
  • Один аккаунт репозитория можно использовать для нескольких приложений, но лучше завести отдельный read-only токен на каждое приложение: так проще отзывать доступ.
  • Удаление приложения в панели убирает контейнеры; чтобы вернуть приложение, достаточно сохранить манифест и повторить клонирование, сборку и запуск.
  • Если репозиторий закрыт совсем (без токенов) или лежит в вашей внутренней сети, доступный вариант — собрать и запустить приложение по SSH самостоятельно; панель покажет контейнеры, но операции уровня приложения к ним не применит.