SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-26

Как развернуть Octop на своем сервере через Docker

Узнайте, как установить Octop версии v0.9.19 на VPS с использованием Docker Compose. Настройте изоляцию пользователей, TLS и OpenAI-совместимый бэкенд без использования curl.

Что такое Octop и зачем его размещать на собственном сервере

Octop — это AI-ассистент для домашнего использования или небольшой команды, который вы размещаете на собственном сервере. Причина выбора Octop вместо обычного интерфейса чата заключается в изоляции пользователей друг от друга. Open WebUI предоставляет браузерный интерфейс для работы с моделью. Octop добавляет систему учетных записей с ролью администратора, личное рабочее пространство и набор учетных данных для каждого пользователя, а также библиотеку специализированных агентов, между которыми пользователь может переключаться в зависимости от задачи. Именно это отличие позволяет одному VPS обслуживать пять человек вместо одного.

Проект находится по адресу github.com/TencentCloud/Octop. Это единый процесс, который предоставляет веб-панель управления, интерфейс командной строки, каналы чатов (Feishu, DingTalk, QQ, Discord, WeCom) и планировщик задач, работающие на основе одной базы данных SQLite по пути ~/.octop/. Все инструкции ниже написаны для версии v0.9.19, выпущенной 5 августа 2026 года. Если вы еще выбираете платформу, сравнение альтернатив Open WebUI для запуска на VPS охватывает более широкий спектр решений.

Важный момент, который стоит прояснить, прежде чем тратить вечер на настройку. Octop — это программное обеспечение версии до 1.0, опубликованное организацией-разработчиком на GitHub, имеющее около 900 звезд по состоянию на август 2026 года. Проект активно развивается, о чем говорят номера версий, и ничто из описанного здесь не является гарантией стабильного пути обновления. Фиксируйте версию (тег), читайте журнал изменений и делайте резервные копии.

Что необходимо перед началом работы

  • VPS под управлением Ubuntu 24.04 с установленными Docker Engine и плагином Compose. Если вы не знакомы с Compose, начните с основ Docker Compose для VPS.
  • git, так как вы будете клонировать конкретный релиз, а не загружать готовый образ.
  • Доменное имя, указывающее на ваш VPS, так как вам потребуется TLS (transport layer security) перед этим сервисом.
  • Бэкенд модели, поддерживающий API OpenAI: локальный Ollama, self-hosted шлюз или платный ключ доступа.

Сам по себе Octop потребляет мало ресурсов. Это Python-процесс и файл SQLite. Основная нагрузка ложится на бэкенд модели, поэтому, если вы планируете запускать модель на том же сервере, подбирайте конфигурацию оборудования с учетом требований модели.

Почему мы не рекомендуем установщик через curl

В файле README первым делом предлагается установка одной командой:

curl -fsSL https://finnie-1258344699.cos.ap-guangzhou.myqcloud.com/octop/install.sh | bash

Мы не рекомендуем использовать этот способ на сервере, который вам дорог, по одной конкретной причине: этот скрипт отсутствует в репозитории. Он загружается из хранилища Tencent Cloud Object Storage. Его содержимое не привязано к git-тегу или коммиту, поэтому вы не можете сравнить текущую версию скрипта с версией недельной давности, а история изменений отсутствует. Завтра из этого хранилища может быть отдана другая версия файла, и в проекте это никак не зафиксируется. Передача результата выполнения напрямую в bash также означает, что машина исполняет скрипт до того, как вы прочитали хотя бы одну его строку.

Кроме того, установщик вносит изменения непосредственно в хостовую систему, а не в контейнер. Он использует uv для загрузки Python 3.12 и создания окружения, о котором ваш менеджер пакетов ничего не знает, поэтому последующее удаление будет выполняться вручную.

Существует два более предпочтительных варианта. Загрузите скрипт, изучите его содержимое и только потом запустите — это займет у вас тридцать секунд: curl -fsSL <url> -o install.sh, затем less install.sh, и наконец bash install.sh. Либо используйте Docker, о чем рассказывается в остальной части этого руководства. Пакет из PyPI (pip install octop) — это как минимум версионированный артефакт, который можно зафиксировать на конкретном релизе.

Развертывание Octop с помощью Docker Compose, версия v0.9.19

По состоянию на август 2026 года опубликованный образ для загрузки отсутствует. Поставляемый файл Compose собирает образ из репозитория, поэтому фиксация версии означает переключение на соответствующий git-тег. Это требует на один шаг больше, чем большинство self-hosted проектов, так как, например, self-hosted рабочее пространство AFFiNE привязывается к тегу опубликованного образа и не требует сборки на вашем VPS. Процедура клонирования, переключения тега и сборки, описанная ниже, идентична той, что приведена в руководстве по развертыванию openGym, поэтому, если вы уже настраивали его, структура процесса вам знакома.

git clone https://github.com/TencentCloud/Octop.git
cd Octop
git checkout v0.9.19

Ниже представлен сервис, описанный в файле, с сокращениями до наиболее важных частей:

services:
  octop:
    build:
      context: ..
      dockerfile: docker/Dockerfile
    image: octop:latest
    container_name: octop
    restart: unless-stopped
    ports:
      - "${OCTOP_PORT:-8088}:${OCTOP_PORT:-8088}"
    volumes:
      - ${OCTOP_DATA:-~/.octop}:/data/.octop
    environment:
      - HOME=/data
      - OCTOP_BIND_HOST=0.0.0.0
      - OCTOP_PORT=${OCTOP_PORT:-8088}
      - OCTOP_DEFAULT_PASSWORD=${OCTOP_DEFAULT_PASSWORD:-octop}
      - OCTOP_ADMIN_USERNAME=${OCTOP_ADMIN_USERNAME:-admin}
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}

Обратите внимание на блок build:. image: octop:latest — это имя, которое получает ваша собственная сборка, а не ссылка на реестр, поэтому latest здесь означает то, что вы скомпилировали в последний раз. Укажите путь к данным явно, вместо использования значения по умолчанию, и задайте пароль для учетной записи администратора до первого запуска. Разместите это в docker/.env:

OCTOP_PORT=8088
OCTOP_ADMIN_USERNAME=admin
OCTOP_DEFAULT_PASSWORD=<a long random password>
OCTOP_DATA=/srv/octop-data

Одна ловушка здесь важнее, чем остальное содержимое файла. Compose считывает docker/.env только для подстановки значений в плейсхолдеры ${...} в YAML-файле. Ключ, который вы добавляете в этот файл, не попадет в контейнер, если он также не указан в секции environment: в файле Compose. Если добавить OCTOP_ACCESS_TOKEN_TTL только в .env, это не даст никакого эффекта, причем без вывода ошибок. Альтернативный вариант — прописать те же ключи в ~/.octop/env внутри смонтированной директории с данными, которые Octop загружает при старте. В руководстве по файлам окружения и секретам в Docker Compose подробно объясняется, почему эти два механизма не являются идентичными.

Соберите и запустите проект:

docker compose -f docker/docker-compose.yml up -d --build
docker compose -f docker/docker-compose.yml ps
curl http://127.0.0.1:8088/api/health

Исправный экземпляр отвечает на проверку работоспособности (health check) кодом {"status":"ok","version":"..."}. Если результат иной, изучите docker compose -f docker/docker-compose.yml logs -f octop, прежде чем открывать браузер.

Теперь присвойте только что собранному образу осмысленное имя, так как следующий вызов --build перезапишет octop:latest, и вы не сможете их различить:

docker image tag octop:latest octop:0.9.19

При первом запуске выполняется octop init, и начальные учетные данные записываются в том данных:

docker exec -it octop cat /data/.octop/credential.txt

Значения по умолчанию — admin / octop, и они применяются только при первой инициализации. Это объясняет вопрос, который часто задают пользователи: изменение OCTOP_DEFAULT_PASSWORD после того, как контейнер был запущен хотя бы раз, ничего не меняет, так как учетная запись уже создана. Смените пароль через панель управления.

Не публикуйте порт 8088

Строка ports: выше привязывает контейнер ко всем интерфейсам VPS. В момент запуска контейнера панель управления оказывается доступна из публичного интернета в открытом виде с паролем по умолчанию. Значение OCTOP_BIND_HOST по умолчанию в Octop — 127.0.0.1; в файле Compose оно переопределено на 0.0.0.0, так как процесс должен принимать трафик извне собственного сетевого пространства имён. Это переопределение корректно. Опасность представляет именно публикация порта.

Отредактируйте строку ports: в файле docker/docker-compose.yml, чтобы привязка осуществлялась только к loopback-интерфейсу:

    ports:
      - "127.0.0.1:${OCTOP_PORT:-8088}:${OCTOP_PORT:-8088}"

Не пытайтесь исправить это с помощью обычного файла переопределения. Compose объединяет списки ports из нескольких файлов, а не заменяет их, поэтому в итоге вы получите публикацию обоих портов, и второй не сможет занять адрес. Если вы хотите оставить исходный файл без изменений, используйте тег !override для последовательности — это документированный способ замены, а не дополнения. В пояснении о том, как Compose объединяет несколько файлов описаны остальные правила слияния.

Привязка к loopback также решает проблему, с которой вы иначе столкнулись бы при настройке межсетевого экрана. Docker записывает правила для опубликованных портов в таблицу nat перед цепочками, которыми управляет ufw, поэтому ufw deny 8088 не блокирует опубликованный порт контейнера. Порт, привязанный к 127.0.0.1, никогда не будет доступен извне, независимо от настроек ufw, поэтому это решение является правильным, а не компромиссным.

Развертывание TLS с помощью обратного прокси-сервера

Caddy — это самый простой путь, так как он самостоятельно запрашивает сертификат через ACME (automatic certificate management environment) и проксирует WebSockets без дополнительной настройки:

octop.example.com {
    reverse_proxy 127.0.0.1:8088
}

nginx требует более тщательной настройки, так как Octop передает чат через WebSocket:

server {
    listen 443 ssl;
    server_name octop.example.com;

    ssl_certificate     /etc/letsencrypt/live/octop.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/octop.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8088;
        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-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}

Каждая строка здесь выполняет свою задачу. Чат работает через WS /agents/{id}/chat/ws, поэтому без proxy_http_version 1.1 и двух заголовков upgrade nginx отвечает на попытку обновления протокола кодом 400 Bad Request: панель управления загружается нормально, но каждое отправленное сообщение зависает без вывода ошибки на странице. proxy_buffering off важен, так как эндпоинт возобновления работы с участием человека (human-in-the-loop) возвращает text/event-stream, а SSE (server-sent events), удерживаемые в буфере прокси, приходят одним пакетом в конце вместо потоковой передачи. proxy_read_timeout необходим для длительных запусков инструментов, так как стандартный таймаут в 60 секунд прерывает работу агента в процессе выполнения, что приводит к записи upstream timed out (110: Connection timed out) в логи.

Как работает аутентификация JWT за прокси

Octop выполняет аутентификацию с помощью bearer-токена, а не cookie. POST /api/auth/login возвращает {access_token, role, user, ...}, и последующие вызовы содержат Authorization: Bearer <access_token>. Для обратного прокси это преимущество: нет домена cookie, флага Secure или правила SameSite, которые можно настроить неверно, поэтому сессия, работающая на http://127.0.0.1:8088, ведет себя так же на https://octop.example.com.

Перед тем как предоставлять доступ реальным пользователям, стоит учесть два последствия.

WebSocket передает токен в URL. Конечная точка — WS /agents/{id}/chat/ws?token=<jwt>, так как JavaScript в браузере не может установить заголовок Authorization при рукопожатии WebSocket. TLS защищает этот токен при передаче. Однако он не защищает его от ваших собственных логов: по умолчанию nginx записывает полную строку запроса, включая строку параметров, в access_log, поэтому рабочий токен реального пользователя попадает в текстовый файл на сервере. Логируйте путь без аргументов. $uri — это нормализованный путь с уже удаленной строкой параметров, поэтому поместите его в блок http и ссылайтесь на него из конфигурации сервера:

log_format octop_noargs '$remote_addr [$time_local] '
                        '"$request_method $uri $server_protocol" '
                        '$status $body_bytes_sent';
access_log /var/log/nginx/octop.log octop_noargs;

Отсутствует завершение сессии для отдельных пользователей. OCTOP_ACCESS_TOKEN_TTL по умолчанию имеет значение 86400, поэтому токен остается действительным в течение 24 часов после входа. Единственный документированный способ аннулировать токен — octop admin rotate-jwt-secret, который обновляет ключ подписи, хранящийся в ~/.octop/secrets/jwt_secret, и немедленно делает недействительными все существующие токены для всех пользователей. Поэтому, когда сотрудник покидает команду, порядок действий следующий: удалите пользователя, обновите секретный ключ, затем попросите остальных пользователей войти в систему снова. Если это кажется слишком сложным, сократите время жизни токена, не забыв добавить переменную в список environment:, а также в .env:

OCTOP_ACCESS_TOKEN_TTL=28800

Защита от перебора реализована: OCTOP_LOGIN_MAX_ATTEMPTS по умолчанию допускает 5 неудачных попыток, а OCTOP_LOGIN_LOCKOUT_SECONDS составляет 900, поэтому заблокированный пользователь просто ждет пятнадцать минут, вместо того чтобы видеть нерабочую установку. Octop имеет собственное хранилище пользователей и не поддерживает OIDC в версии v0.9.19, поэтому, если вам нужен полноценный единый вход (SSO), установите перед ним аутентифицирующий прокси, для чего предназначен самостоятельно развернутый сервер Authentik.

Настройка Octop для работы с модельным бэкендом

Провайдеры настраиваются для каждого агента в панели управления, а octop provider list показывает текущие параметры. Octop поставляется с предустановками для API, совместимых с OpenAI, DashScope (Qwen) и Ollama. Учетные данные хранятся в таблице providers вашей собственной базы данных SQLite. Выбор провайдера определяет ваши расходы и то, какие данные покидают сервер.

Локальная модель через Ollama. Данные не покидают сервер, а платой за использование становится оперативная память, а не токены. Важный нюанс: контейнер не может обратиться к Ollama на хосте по адресу 127.0.0.1:11434, так как этот адрес является loopback-интерфейсом самого контейнера. Добавьте запись host gateway в сервис:

    extra_hosts:
      - "host.docker.internal:host-gateway"

Затем установите базовый URL провайдера на http://host.docker.internal:11434/v1 — это путь Ollama, совместимый с OpenAI. В поле API key введите любую непустую строку, так как Ollama игнорирует его, а клиенты OpenAI не отправляют пустые значения. Чтобы это заработало, Ollama должна принимать соединения не только через loopback, для чего в ее systemd-юните нужно указать OLLAMA_HOST=0.0.0.0:11434. Это рискованная часть: в Ollama нет аутентификации, поэтому открытый порт 11434 на публичном IP делает ваш сервер доступным для любого, кто его просканирует. Разрешите доступ только из частной сети Docker, sudo ufw allow from 172.16.0.0/12 to any port 11434 proto tcp, и запретите все остальные. В статье Запуск Ollama на VPS рассматривается подбор размера моделей, а в сравнении Ollama и vLLM — случаи, когда Ollama перестает быть подходящим решением.

Еще одно предупреждение касательно локальных моделей: проблема, которая выглядит как баг в Octop, им не является. Агенты работают через вызов инструментов, поэтому системный промпт, определения инструментов и история переписки формируют большой запрос. Ollama использует модели с небольшим контекстным окном по умолчанию, из-за чего начало промпта, где находятся определения инструментов, выпадает из окна. В результате модель перестает вызывать инструменты или выдумывает несуществующие. Увеличьте num_ctx до 16k или 32k и выберите модель, которая хорошо справляется с вызовом функций. Если ответ обрывается на полуслове — это другая проблема, связанная с настройкой num_predict. Если ответы приходят обрезанными, стоит проверить, где задан num_predict и что говорит done_reason, прежде чем винить агента. Если вы хотите начать с конкретной модели, а не с короткого списка, попробуйте Nemotron 3.5 Lightning. В этом руководстве указан точный тег для загрузки, требования к RAM и информация о том, справится ли только CPU.

Self-hosted шлюз. Установите self-hosted шлюз LiteLLM между Octop и остальными сервисами. Вы получите единый базовый URL, отдельные ключи для каждого пользователя, лимиты расходов и централизованный лог. Вы также сможете менять модель на бэкенде, не внося изменений в Octop.

Платный API. Максимальное качество при очевидном компромиссе: содержимое диалогов покидает ваш сервер и попадает к провайдеру, что противоречит основной цели self-hosting. Ключ вводится в docker/.env как OPENAI_API_KEY, что уже предусмотрено в файле Compose.

Что бы вы ни выбрали, файл Compose также содержит OCTOP_LANGFUSE_ENABLED, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY и LANGFUSE_BASE_URL. Это позволяет отправлять трассировки в ваш собственный экземпляр Langfuse и видеть, что именно делают агенты, вместо того чтобы гадать по окну чата.

Пользователи, роли и общая библиотека агентов

Учетная запись администратора, созданная при первом запуске, управляет остальными пользователями. Каждый пользователь получает собственные агенты, рабочее пространство и учетные данные; эта изоляция обеспечивается токеном, который хранится в браузере. Рядом находится общий пул навыков и вспомогательных агентов, доступных всем участникам. Именно эта функция делает использование системы оправданным для семьи: один человек создает эффективного исследовательского агента, и остальным не нужно повторять эту работу.

Будьте осторожны с инструментами. Octop поддерживает подтверждение использования инструментов и защитные механизмы для shell-команд. Оба компонента работают, но агент, выполняющий shell-команды, запускает их внутри контейнера Octop, к которому подключен ваш том с данными. Защитные механизмы ограничивают последствия неосторожных запросов. Они не являются полноценной «песочницей», поэтому оставляйте подтверждение использования инструментов включенным для всех, кому вы не доверили бы прямой доступ к shell. Если вы сравниваете это решение с другими вариантами, обзор self-hosted AI агентов поможет понять, как каждый из них решает подобные задачи.

Обновление проекта с высокой частотой релизов

ChartDays between Octop releases, v0.9.16 to v0.9.19 (repository tags, 7 August 2026)
The data behind this chart
[
  {
    "version": "v0.9.16",
    "days_since_previous_release": 2
  },
  {
    "version": "v0.9.17",
    "days_since_previous_release": 3
  },
  {
    "version": "v0.9.18",
    "days_since_previous_release": 1
  },
  {
    "version": "v0.9.19",
    "days_since_previous_release": 3
  }
]

Это даты тегов из репозитория по состоянию на 7 августа 2026 года. За девять дней было выпущено 4 релизов, при этом минимальный интервал между ними составил 1 день, а версия v0.9.19 вышла через 3 дня после предыдущего тега. Такая частота — хороший показатель для проекта, но плохой повод для запуска latest. Изучите изменения перед их применением:

cd Octop
git fetch --tags
git tag --sort=-creatordate | head
NEW_TAG=$(git tag --sort=-creatordate | head -1)
git log --oneline "v0.9.19..$NEW_TAG"

Всегда делайте резервную копию, так как миграции базы данных выполняются при запуске, и в случае сбоя миграции в проекте версии до 1.0 вам придется исправлять последствия самостоятельно:

docker compose -f docker/docker-compose.yml stop
sudo tar czf octop-backup-$(date +%F).tgz -C /srv octop-data
docker compose -f docker/docker-compose.yml start

Затем переключитесь на новый тег и выполните пересборку с помощью docker compose -f docker/docker-compose.yml up -d --build. Если что-то пойдет не так, возврат к старому тегу и пересборка восстановят код, но только архив с резервной копией позволит восстановить базу данных.

Этот архив содержит octop.db, config.json, секретный ключ для подписи JWT и credential.txt, поэтому он так же критически важен, как и сам сервер. Установите права доступа 600 и храните копию вне сервера. Для более крупных инсталляций проект также поставляет docker/docker-compose.postgres.yml, который запускает PostgreSQL с расширением pgvector вместо SQLite.

Типичные сбои и сообщения об ошибках

Проверка работоспособности не отвечает. curl http://127.0.0.1:8088/api/health зависает или выдает отказ. Прочитайте docker compose -f docker/docker-compose.yml logs -f octop. Контейнер, который завершает работу во время первой инициализации, обычно не может записать данные в каталог, поэтому проверьте права доступа к пути, который вы указали в OCTOP_DATA.

Панель управления загружается, но чат зависает. На странице нет ошибок, но ответы не приходят. Откройте консоль браузера и найдите неудачное соединение с wss://octop.example.com/agents/.../chat/ws. Прокси-сервер не выполняет перенаправление (upgrade) соединения. Добавьте proxy_http_version 1.1, а также заголовки Upgrade и Connection.

Весь ответ появляется сразу, с задержкой в несколько секунд. Потоковая передача работает, но включена буферизация. Установите proxy_buffering off.

bind: address already in use. Порт 8088 уже занят другим процессом. sudo ss -tlnp | grep 8088 покажет, какой именно процесс его использует. Эта же ошибка возникает, если вы добавили вторую запись ports в файл переопределения (override), вместо того чтобы отредактировать исходный файл.

Правильный пароль отклоняется. Пять неудачных попыток приводят к блокировке на 900 секунд. Дождитесь окончания блокировки, вместо того чтобы переустанавливать приложение.

Новый пароль в .env не применился. Эти учетные данные используются только при первой инициализации. Измените пароль в панели управления.

Агент отвечает, но не запускает инструменты. Почти всегда это проблема локальной модели: контекстное окно слишком мало для определений инструментов или модель плохо справляется с вызовом функций. Увеличьте num_ctx и попробуйте модель, специально обученную для работы с инструментами.

FAQ

Является ли Octop заменой Open WebUI?

Только если вам нужны функции, которые он добавляет. Open WebUI — это чат-интерфейс для взаимодействия с моделью, который хорошо справляется со своей задачей для одного пользователя или доверенной группы лиц. Octop добавляет учетные записи с ролью администратора, рабочие пространства и учетные данные для каждого пользователя, а также библиотеку специализированных агентов с возможностью переключения. Это позволяет нескольким людям использовать один сервер, не смешивая историю переписки. Если вам достаточно одной учетной записи, Open WebUI будет более простым и зрелым решением.

Почему не стоит использовать скрипт установки Octop через curl?

Скрипт загружается из бакета Tencent Cloud Object Storage, а не из репозитория, поэтому он не привязан к git-тегам или коммитам. Вы не можете сравнить текущую версию скрипта с той, что была неделю назад, а передача его в bash выполняет код до того, как вы его прочитаете. Кроме того, скрипт устанавливает собственное окружение Python 3.12 непосредственно на хост, в обход вашего пакетного менеджера. Сначала скачайте и изучите скрипт или разверните решение через Docker Compose из проверенного тега.

Может ли Octop использовать локальную модель вместо платного API?

Да. Octop поддерживает API, совместимые с OpenAI, и содержит предустановку для Ollama. Настройка через http://host.docker.internal:11434/v1 будет работать, если вы добавите extra_hosts: ["host.docker.internal:host-gateway"] в контейнер и установите OLLAMA_HOST=0.0.0.0:11434 на хосте. Закройте порт 11434 брандмауэром для диапазона адресов Docker, так как в Ollama нет встроенной аутентификации. Будьте готовы увеличить num_ctx в Ollama до 16k или выше, так как промпты агентов с определениями инструментов переполняют стандартное окно контекста, из-за чего модель перестает вызывать инструменты.

Нужен ли мне reverse proxy или можно открыть порт 8088?

Вам необходим прокси. В поставляемом файле Compose порт 8088 открыт на всех интерфейсах без TLS, поэтому пароли и bearer-токены будут передаваться через интернет в открытом виде. Измените опубликованный порт на 127.0.0.1:8088:8088 и установите перед ним Caddy или nginx с сертификатом. При использовании nginx настройте пересылку заголовков WebSocket upgrade и установите proxy_buffering off, иначе страница загрузится, но чат не будет отвечать.

Готов ли Octop к промышленной эксплуатации?

Проект находится на стадии до версии 1.0 и выпускает несколько релизов в неделю по состоянию на август 2026 года, поэтому его следует рассматривать как перспективный, а не как устоявшийся продукт. Это приемлемо для семьи или небольшой внутренней команды, если вы фиксируете конкретный тег, читаете журнал коммитов перед каждым обновлением и делаете резервную копию тома с данными перед каждой пересборкой. Не запускайте его на latest и пока не храните в нем данные клиентов.