SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Установка Planka через Docker Compose на свой сервер

Пошаговое руководство по развертыванию Planka с Postgres и Traefik. Узнайте, как настроить переменные окружения и почему неверный BASE_URL блокирует вход в систему.

Преимущества самостоятельного хостинга Planka

Самостоятельный хостинг Planka предоставляет вашей команде Kanban-доску с моделью карточек, списков и меток, знакомой пользователям Trello, которая работает на подконтрольном вам VPS. Здесь нет ограничений на количество рабочих мест и нет оплаты за каждого пользователя, так как единственные затраты — это сервер. В этом руководстве описывается развертывание с помощью Docker Compose за Traefik, использование Postgres для данных и именованного тома для всех файлов, загружаемых пользователями.

Planka 2 выпускается под собственной лицензией Fair Use License, которую проект характеризует как source-available, а не open source. Использование для внутренних проектов вашей организации разрешено. Предложение Planka третьим лицам в качестве коммерческого хостинг-сервиса требует лицензии Pro или Enterprise.

Это руководство предназначено для команд из двух-пяти человек, которые переходят с бесплатного тарифа Trello. Если вы еще выбираете, какую доску использовать, сначала прочитайте сравнение альтернатив Trello для самостоятельного хостинга. Это руководство предполагает, что выбор уже сделан, и охватывает только процесс развертывания.

Вам потребуется VPS с установленным Docker Engine и плагином Compose, а также DNS A-запись, указывающая на этот сервер. Также необходим уже настроенный экземпляр Traefik, выполняющий TLS termination (transport layer security) на этом узле. Если Traefik еще не настроен, сначала разверните reverse proxy Traefik перед несколькими приложениями Compose и ознакомьтесь с основами Docker Compose для VPS, если приведенный ниже файл кажется вам незнакомым.

Сколько ресурсов VPS требуется для Planka?

Проект не публикует минимальные системные требования, поэтому любые цифры следует воспринимать как отправную точку, а не как точный замер. Значения 2 vCPU и 4 GB, которые часто встречаются на страницах хостинг-провайдеров, являются комфортным стандартом, а не требованием, измеренным разработчиками. Это избыточный объем для доски, которой пользуются пять человек.

Фактически работающие компоненты занимают мало места: один процесс Node.js, обслуживающий API и собранный фронтенд, а также сервер Postgres, хранящий данные. Postgres запускает управляющий процесс и по одному фоновому процессу на каждое открытое соединение. Внутри контейнера Planka также работает небольшой прокси-процесс для фильтрации исходящих запросов. Тариф с 1 vCPU и 2 GB RAM позволяет поддерживать доску для группы от двух до пяти человек, при этом большая часть свободной памяти будет использоваться под кэш Postgres. Доска — «легкий» сосед, поэтому если на этом же VPS должны храниться документы вашей команды, рассчитывайте ресурсы исходя из потребностей того приложения: запуск AFFiNE в качестве рабочего пространства в стиле Notion требует пару гигабайт оперативной памяти еще до того, как Planka запросит свои ресурсы.

Рассчитывайте объем диска до того, как определитесь с памятью, так как вложения — это та часть данных, которая постоянно растет. Выполните замеры на собственном экземпляре, вместо того чтобы полагаться на этот текст:

docker stats --no-stream
docker system df -v

Первая команда выводит текущее потребление памяти и процессора для каждого контейнера. Вторая показывает, сколько места занимает каждый том. Снимайте оба показателя после полноценной рабочей недели, а не в день установки, так как простаивающая доска не дает представления о реальной нагрузке вашей команды.

Создание файла Compose

Создайте каталог и назначьте себя его владельцем, чтобы вам не приходилось редактировать эти файлы через sudo.

sudo mkdir -p /opt/planka
sudo chown "$USER":"$USER" /opt/planka
cd /opt/planka

Сгенерируйте секреты в файл .env рядом с файлом Compose. Compose автоматически считывает этот файл и подставляет значения.

umask 077
{
  printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 64)"
  printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)"
  printf 'ADMIN_PASSWORD=%s\n' "$(openssl rand -hex 12)"
} > .env
chmod 600 .env

Использование openssl rand -hex сделано намеренно. Шестнадцатеричная строка содержит только цифры и буквы от a до f, поэтому она не может нарушить строку подключения DATABASE_URL, в которую вставляется. Пароль в формате base64, содержащий косую черту или символ «собаки», вызывает ошибку подключения, которая выглядит как неверное имя хоста, на диагностику чего уходит час. Более общие рекомендации описаны в хранении секретов вне файла Compose.

Теперь docker-compose.yml. Замените kanban.example.com на ваше собственное имя хоста в обоих местах, где оно встречается.

services:
  planka:
    image: ghcr.io/plankanban/planka:2.2.1
    restart: unless-stopped
    volumes:
      - planka-data:/app/data
    environment:
      - BASE_URL=https://kanban.example.com
      - DATABASE_URL=postgresql://planka:${POSTGRES_PASSWORD}@postgres/planka
      - SECRET_KEY=${SECRET_KEY}
      - TRUST_PROXY=true
      - DEFAULT_ADMIN_EMAIL=you@example.com
      - DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD}
      - DEFAULT_ADMIN_NAME=Your Name
      - DEFAULT_ADMIN_USERNAME=admin
    networks:
      - proxy
      - internal
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.planka.rule=Host(`kanban.example.com`)"
      - "traefik.http.routers.planka.entrypoints=websecure"
      - "traefik.http.routers.planka.tls.certresolver=default"
      - "traefik.http.services.planka.loadbalancer.server.port=1337"
    depends_on:
      postgres:
        condition: service_healthy

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=planka
      - POSTGRES_USER=planka
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    networks:
      - internal
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U planka -d planka"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  planka-data:
  db-data:

networks:
  proxy:
    external: true
  internal:

Четыре решения в этом файле требуют пояснения, так как именно их пользователи меняют, а затем жалеют об этом.

  • В сервисе Planka отсутствует блок ports:. Traefik обращается к контейнеру через сеть proxy, поэтому порт 1337 никогда не публикуется на хосте. Публикация порта позволила бы любому обойти ваш прокси и сертификат.
  • loadbalancer.server.port=1337 указывает порт внутри контейнера. Planka прослушивает порт 1337, а в исходном примере обращение идет через 3000, так как там выполняется проброс порта на хост. Здесь проброса нет, поэтому Traefik должен знать порт контейнера.
  • condition: service_healthy работает в связке с проверкой работоспособности (healthcheck) Postgres. Без этого Planka запускается раньше, чем база данных начинает принимать подключения, выполняет первый запрос с ошибкой и завершается, что выглядит как цикл аварийных перезапусков. Механика процесса описана в проверках работоспособности и порядке запуска в Compose.
  • Сервис базы данных намеренно назван postgres. Planka 2 направляет свои исходящие запросы через внутренний фильтр, чей список блокировки по умолчанию включает localhost,postgres. Переименуйте сервис, и вы незаметно исключите свою базу данных из этого списка.

Перед запуском убедитесь, что Compose видит ваши секреты:

docker compose config | grep -E 'image:|BASE_URL|POSTGRES_USER'

Эта команда выведет содержимое файла с уже подставленными значениями .env. Пустое значение означает, что Compose не считывает файл .env, обычно это происходит, если вы запускаете команду из другого каталога.

Назначение переменных начальной настройки администратора

Начиная с версии Planka 1.13, администратор не создается автоматически, поэтому в новой базе данных нет пользователей, которые могли бы войти в систему. Группа переменных DEFAULT_ADMIN_* — один из двух способов решить эту проблему.

При запуске Planka ищет пользователя, соответствующего DEFAULT_ADMIN_EMAIL. Если такой пользователь отсутствует, система создает его, используя указанные рядом пароль, отображаемое имя и имя пользователя. Это происходит при первом запуске на пустой базе данных, поэтому данные переменные выполняют начальную настройку учетной записи, а не управляют ею в дальнейшем.

Переменная DEFAULT_ADMIN_EMAIL выполняет вторую функцию, которая часто сбивает пользователей с толку. Пока эта переменная задана, учетную запись с указанным именем невозможно отредактировать или удалить через интерфейс. Это механизм защиты от блокировки, и именно поэтому вы не можете переименовать такую учетную запись или изменить её адрес электронной почты в UI. Удалите переменную и перезапустите контейнер — после этого учетная запись станет обычной административной записью, которую можно редактировать как любую другую.

Будьте осторожны со строкой пароля. Любой, кто может выполнить docker inspect в контейнере, способен прочитать содержимое environment:, поэтому DEFAULT_ADMIN_PASSWORD не должна оставаться там постоянно. Войдите в систему, измените пароль через интерфейс, удалите эту строку из конфигурации, а затем снова выполните docker compose up -d.

Более чистый способ — вообще не использовать эти переменные. Закомментируйте всю группу DEFAULT_ADMIN_*, а затем создайте учетную запись в интерактивном режиме:

docker compose run --rm planka npm run db:create-admin-user

Система запросит адрес электронной почты, пароль, отображаемое имя и (опционально) имя пользователя, после чего запишет данные напрямую в базу данных. Пароль при этом не попадает в файл Compose или переменные окружения контейнера. Используйте этот метод, если доступ к оболочке (shell) на VPS есть у нескольких человек. Команда запускает Postgres первым благодаря depends_on, поэтому она работает даже на стеке, который еще ни разу не был запущен.

Любой из этих способов оставляет управление паролями Planka на ваше усмотрение. Вплоть до версии 2.1.1 Community edition могла передавать аутентификацию OIDC-провайдеру, например, Authentik, запущенному как ваш собственный сервер единого входа, но в версии 2.2.0, выпущенной в августе 2026 года, поддержка OIDC и SSO была перенесена в PLANKA Pro. В том же релизе Community edition получила двухфакторную аутентификацию (TOTP) для локальных учетных записей, поэтому обязательно включите её хотя бы для административной учетной записи.

Почему BASE_URL нарушает работу входа, если он не совпадает с именем хоста

BASE_URL — это точный адрес, который пользователи вводят в браузере, включая схему и без косой черты в конце. Для этого стека это https://kanban.example.com. Planka формирует свои ссылки и WebSocket-соединение на основе этого значения, поэтому неверный BASE_URL не выдает явную ошибку. Вместо этого вы получаете страницу, которая загружается, но процесс загрузки никогда не завершается.

Распространенный вариант: вы копируете пример из upstream, оставляете BASE_URL=http://localhost:3000 как есть и заходите на сайт по HTTPS через свой реальный домен. Форма входа отправляет данные, учетные данные принимаются, но доска не появляется. Откройте консоль разработчика в браузере, и вы увидите, что запросы к /socket.io/ завершаются ошибкой, так как клиенту было указано открыть активное соединение с localhost:3000, а на вашем компьютере этот адрес никуда не ведет.

TRUST_PROXY=true — это вторая часть той же проблемы. Planka находится за Traefik, поэтому каждый запрос поступает к ней с адреса прокси по обычному HTTP внутри сети Docker. Без TRUST_PROXY приложение игнорирует заголовки X-Forwarded-Proto и X-Forwarded-For, которые устанавливает Traefik, поэтому оно считает соединение небезопасным и воспринимает всех клиентов как один общий IP-адрес. Если этот параметр задан, приложение считывает эти заголовки и согласуется с браузером относительно используемой схемы.

Traefik проксирует WebSockets без дополнительной настройки, что является одной из причин предпочесть его в данном случае. В nginx прокси должен пересылать заголовки обновления, proxy_set_header Upgrade $http_upgrade и proxy_set_header Connection "upgrade", иначе вы получите тот же «зависший» индикатор загрузки, но по другой причине. Их можно разместить в общем блоке location /; отдельный блок для /socket.io также работает, но не является обязательным.

Перенос доски на новое имя хоста в дальнейшем означает изменение двух параметров одновременно: значения BASE_URL и правила Host() в Traefik. Измените один и забудете другой — и вы снова увидите индикатор загрузки. Размещение Planka по подпути, например https://example.com/planka, работает начиная с версии 2.1.0, выпущенной в марте 2026 года. Для более старых тегов используйте отдельный поддомен.

Где Planka хранит вложения и аватары

Planka 2 хранит все пользовательские загрузки по одному пути внутри контейнера: /app/data. Вложения, аватары пользователей и фоновые изображения досок находятся в этой директории. В версии 1 использовались три отдельные папки, поэтому Compose-файл, скопированный из старого руководства, монтирует пути, которых больше не существует, а реальная директория с данными остается несмонтированной.

Это единственное монтирование определяет разницу между доской, которая переживет обновление, и испорченным днем. Если /app/data не находится на томе (volume), загрузки попадают в записываемый слой контейнера. Этот слой уничтожается при пересоздании контейнера, а контейнер пересоздается каждый раз при смене тега образа. Доска после этого выглядит нормально, карточки на месте, но все ссылки на вложения не работают, так как записи в базе данных по-прежнему указывают на файлы, которых больше нет.

Именованный том в приведенном выше Compose-файле предотвращает эту проблему. Bind mount также подходит и упрощает резервное копирование файлов стандартными инструментами, но требует одного дополнительного шага. Процесс Node внутри контейнера работает от имени UID 1000, поэтому директория на хосте, принадлежащая root, приведет к ошибке прав доступа при первой же загрузке:

sudo chown -R 1000:1000 /opt/planka/data

Компромисс между этими двумя вариантами разобран в bind mounts против именованных томов.

Если объем вложений превышает доступное место на диске, Planka может записывать их в S3-совместимое хранилище через S3_ENDPOINT, S3_BUCKET и соответствующие переменные с ключами. Это может быть облачный бакет или собственное объектное хранилище MinIO на другом сервере. Определитесь с этим до того, как команда начнет заполнять доску, так как настройки применяются только к новым загрузкам.

Запуск стека и проверка работоспособности

docker compose pull
docker compose up -d
docker compose ps

docker compose ps должен показать postgres как healthy, а planka как running. Если Planka перезапускается в цикле, в первую очередь проверяйте подключение к базе данных, а не само приложение.

docker compose logs -f planka

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

docker compose exec postgres psql -U planka -d planka -c '\dt'

Список таблиц, включающий board и card, означает, что миграции прошли успешно. Сообщение "Did not find any relations" означает, что Planka не смогла подключиться; в этом случае сравните DATABASE_URL со значениями POSTGRES_USER и POSTGRES_PASSWORD в вашем .env.

Затем проверьте маршрут со своего локального компьютера, а не с VPS:

curl -I https://kanban.example.com

HTTP/2 200 означает, что Traefik использует сертификат и успешно обращается к контейнеру. Ошибка 404 от Traefik означает, что ни один маршрутизатор не подошел под запрос: правило Host() не соответствует запрошенному имени хоста, либо Traefik не считал метки. Ошибка 502 означает, что маршрутизатор сработал, но Traefik не смог связаться с контейнером, например, из-за того, что он не подключен к сети proxy. Теперь откройте сайт и войдите в систему под учетной записью администратора.

Выполняйте pg_dump перед каждым обновлением версии

Ваша доска использует два отдельных хранилища, поэтому резервная копия должна охватывать оба: базу данных Postgres и том planka-data. Выполняйте дамп базы данных, пока стек запущен.

docker compose exec -T postgres pg_dump -U planka -d planka > "planka-db-$(date +%F).sql"

Флаг -T обязателен. Без него Compose выделяет псевдотерминал, а терминальный уровень перезаписывает символы конца строки в потоке. В результате вы получите файл дампа, который будет поврежден при восстановлении. Ошибка проявится спустя недели, в самый неподходящий момент.

Затем сохраните загружаемые файлы. Сначала определите реальное имя тома, так как Compose добавляет к нему префикс в виде имени директории проекта.

docker volume ls | grep planka
docker run --rm -v planka_planka-data:/data -v "$PWD":/backup alpine \
  tar czf /backup/planka-files-$(date +%F).tgz -C /data .

Проект также содержит docker-backup.sh и docker-restore.sh в своем репозитории, а официальная документация рекомендует запускать их по ночному расписанию cron. Оба подхода допустимы. Недопустимо иметь резервную копию, которую вы никогда не восстанавливали. Восстановите её на тестовом VPS хотя бы раз и убедитесь, что можете войти в систему и открыть вложение. Та же пара хранилищ встречается в каждом приложении Compose, которое принимает загрузки. Поэтому, если позже вы разместите Chatwoot на том же сервере, что и вашу службу поддержки, отработанная здесь процедура будет применима с минимальными изменениями имен томов.

Выполняйте дамп непосредственно перед каждым изменением версии. Резервная копия, сделанная вчера ночью, не эквивалентна копии, сделанной перед миграцией, которую вы собираетесь запустить.

Закрепление тегов и чтение примечаний к выпуску

Оба тега образов в этом файле закреплены намеренно.

ghcr.io/plankanban/planka:2.2.1 — это конкретный выпуск, актуальный на октябрь 2026 года. latest меняется при каждом обновлении от разработчиков, поэтому обычная команда docker compose pull может привести к миграции схемы базы данных в самый неподходящий момент. Прочитайте примечания к выпуску перед тем, как менять этот номер, так как именно там описаны критические изменения и исправления безопасности. Версия 2.0.3 была выпущена как обновление безопасности; это именно тот случай, когда лучше ознакомиться с информацией заранее, чем столкнуться с последствиями случайно. То же самое касается версии 2.2.1, выпущенной в августе 2026 года: она исправляет уязвимость обхода пути (path traversal), которая позволяла авторизованному пользователю читать произвольные файлы на инстансах, использующих локальное хранилище (именно такая конфигурация описана в этом руководстве). В бюллетене указано, что версии 2.1.1 и более ранние подвержены этой уязвимости. Если вы переходите с версии 2.1.x, сначала прочитайте примечания к 2.2.0, так как этот выпуск деактивирует пользователей, которые входили только через SSO, пока администратор не назначит им пароль. Закрепление версий здесь удобно, так как разработчики публикуют образы. Если проект не предоставляет готовых образов, вы должны придерживаться той же дисциплины, но с дополнительным шагом, как в случае с сборкой openGym на сервере из проверенного git-тега.

postgres:16-alpine закреплен за мажорной версией по более веской причине. Postgres записывает данные в директорию в формате, привязанном к мажорной версии, и сервер отказывается открывать директорию, созданную другой версией. Если вы укажете postgres:latest и позволите тегу обновиться до версии выше 16, контейнер не запустится. Образ версии 17, например, завершит работу с ошибкой:

FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.

Данные не теряются, и перезапуск проблему не решит. Переход на новую мажорную версию Postgres означает либо создание дампа из старой версии и восстановление в новую директорию данных, либо выполнение pg_upgrade, что конвертирует данные без дампа, но требует наличия бинарных файлов старого и нового сервера одновременно. В любом случае это плановая работа при остановленном стеке, а не побочный эффект обновления образа.

Если вы переносите существующую установку Planka 1.x, а не начинаете с нуля, для этого обновления предусмотрена собственная процедура в документации проекта, и вернуться к версии 1 без предварительно созданной резервной копии невозможно.

Типовые сбои и сообщения в логах

Planka перезапускается в цикле, а в логе упоминается база данных. Учетные данные в DATABASE_URL не соответствуют переменным окружения Postgres. Учтите, что POSTGRES_PASSWORD применяется только при первой инициализации директории с данными, поэтому изменение переменной после неудачного первого запуска ничего не даст. Необходимо удалить том db-data и начать процесс заново.

Вход выполнен, но доска не загружается. BASE_URL не совпадает с адресом в адресной строке браузера или отсутствует TRUST_PROXY. В консоли браузера видны неудачные запросы к /socket.io/.

Загрузка файлов не работает, остальное функционирует нормально. Точка монтирования принадлежит пользователю root. Выполните sudo chown -R 1000:1000 для директории на хосте и перезапустите контейнер.

Вложения исчезли после обновления. /app/data не был вынесен на том, поэтому файлы находились в слое контейнера, который был заменен при обновлении. Восстановите файлы из резервной копии, затем добавьте том, прежде чем снова менять тег образа.

Traefik возвращает 404. Ни один маршрутизатор не подошел под запрос: правило Host() не соответствует вашей DNS-записи, либо метки не были переданы в Traefik. docker compose config показывает метки после подстановки, где становятся видны опечатки. Ошибка 502 означает, что маршрут совпал, но контейнер недоступен; проверьте, находится ли он в сети proxy.

Уведомления или вебхуки не приходят. Planka 2 отправляет исходящие HTTP-запросы через внутренний фильтр, и список блокировки по умолчанию включает localhost и postgres. Вебхук, направленный на localhost, блокируется намеренно (by design), и как только вы задаете OUTGOING_ALLOWED_HOSTS, любой хост, не входящий в этот список, также блокируется. Направьте вебхук на имя сервиса другого контейнера и добавьте это имя в OUTGOING_ALLOWED_HOSTS, если используете список разрешенных адресов, вместо того чтобы отключать фильтр.

После запуска нагрузка на систему невелика. Следите за примечаниями к выпускам и делайте дамп базы данных перед каждым обновлением. Перезагрузка автоматически поднимает стек благодаря restart: unless-stopped, если сервис Docker включен в автозагрузку, а Compose-стеки, которые восстанавливаются после перезагрузки описывает случаи, когда этого не происходит.

FAQ

Почему Planka бесконечно загружается после входа в систему?

Учетные данные были приняты, но соединение в реальном времени — нет. Planka формирует URL для WebSocket на основе BASE_URL. Если в этой переменной указано http://localhost:3000, а вы заходите на сайт по адресу https://kanban.example.com, браузер пытается открыть сокет по адресу, которого нет на вашей машине. В консоли разработчика будут видны неудачные запросы к /socket.io/. Установите BASE_URL в значение точного публичного адреса без слеша в конце, добавьте TRUST_PROXY=true, чтобы приложение учитывало заголовок X-Forwarded-Proto от вашего reverse proxy, затем выполните docker compose up -d.

Как создать первого администратора в Planka?

Начиная с версии 1.13 администратор не создается автоматически. Либо укажите DEFAULT_ADMIN_EMAIL вместе с соответствующими переменными для пароля, имени и имени пользователя и запустите стек, либо выполните docker compose run --rm planka npm run db:create-admin-user и ответьте на вопросы в интерактивном режиме. Интерактивная команда безопаснее на общем сервере, так как пароль не попадает в переменные окружения контейнера, где его может прочитать docker inspect. Если оставить DEFAULT_ADMIN_EMAIL установленной после этого, учетная запись будет заблокирована для редактирования и удаления через интерфейс.

Где Planka хранит вложения и аватары?

В Planka 2 все загруженные файлы находятся по пути /app/data внутри контейнера, включая вложения, аватары пользователей и фоны досок. Примонтируйте этот путь к именованному тому. Если том не примонтирован, файлы сохраняются в записываемом слое контейнера и будут удалены при следующем пересоздании контейнера, что происходит при каждом обновлении образа. Bind mount также подходит, но процесс Node работает от имени UID 1000, поэтому выполните sudo chown -R 1000:1000 для директории на хосте, иначе загрузка файлов завершится ошибкой доступа.

Сколько оперативной памяти нужно для self-hosted Planka?

Проект не устанавливает минимальных системных требований. Цифры 2 vCPU и 4 GB, которые часто встречаются на страницах хостинг-провайдеров, являются стандартными настройками, а не результатами измерений, и для небольшой доски это избыточно. Вся рабочая нагрузка состоит из одного процесса Node и сервера Postgres, который запускает один небольшой backend-процесс на каждое открытое соединение. Поэтому тарифа с 1 vCPU и 2 GB достаточно для команды из двух-пяти человек. Выполните docker stats --no-stream после обычной рабочей недели и подбирайте ресурсы на основе собственных показателей. Следите за диском внимательнее, чем за памятью, так как именно вложения занимают место.

Как обновить Planka без потери данных?

Сделайте дамп базы данных и заархивируйте том с загрузками непосредственно перед обновлением, а не по расписанию за прошлую ночь. Используйте docker compose exec -T postgres pg_dump -U planka -d planka > planka-db.sql, сохраняя -T, чтобы псевдотерминал не повредил перенаправленный вывод. Прочитайте примечания к выпуску для каждой версии, которую вы пропускаете, измените тег образа на конкретный релиз вместо latest, затем выполните docker compose pull и docker compose up -d и следите за логами процесса миграции. Оставьте тег Postgres зафиксированным на его мажорной версии, так как сервер откажется открывать директорию данных, созданную другой мажорной версией.