Перенос Docker Compose на другой сервер вместе с данными
Контейнер запустился — ещё не значит, что проект переехал. Разберём перенос базы, пользовательских файлов и настроек с проверкой до переключения.
Compose-файл не содержит все данные проекта
Разберём Linux-сервер с Docker Compose, приложением web, фоновым сервисом worker и PostgreSQL в сервисе db. Пользовательские загрузки лежат в named volume uploads. Это имена примера: сначала посмотрите, как устроен ваш проект.
Образ содержит программу, но не данные подключённых томов. Важные файлы могут оказаться и в bind mount, и в writable layer контейнера. Проверьте каждый mount и список зависимостей до переноса. Копирование только compose.yaml не перенесёт базу, фотографии и секреты.
Составьте список сервисов, томов и настроек
docker compose config --services
docker compose config --volumes
docker compose config --quiet
docker inspect "$(docker compose ps -q web)" --format '{{json .Mounts}}'
docker inspect "$(docker compose ps -q db)" --format '{{json .Mounts}}'
В Mounts смотрите Type, Name, Source и Destination. Для named volume нужен его фактический Name, для bind mount — каталог на хосте. Имя часто зависит от имени Compose-проекта, но его могут переопределить через name или external.
Сохраните версию образа приложения, желательно digest, и убедитесь, что новая площадка может его получить. Если образ собирается из исходников, нужны код, Dockerfile и доступ к зависимостям. Проверьте архитектуру процессора, свободное место и доступ к registry.
Отдельно учтите .env, env_file, secrets, сертификаты, ключи шифрования, DNS и настройки внешних сервисов. Сам .env используется Compose для подстановки значений и не передаёт автоматически все переменные внутрь контейнера. Не публикуйте итоговый docker compose config с секретами в чат или Git.
Остановите запись и получите согласованную копию
Сначала отрепетируйте перенос. Для финальной копии остановите все процессы, которые могут менять данные. В этом примере это web и worker. Если есть другие писатели, импорты или прямые подключения к базе, остановить только эти два сервиса недостаточно.
docker compose stop web worker
umask 077
mkdir -p transfer
docker compose exec -T db pg_dump --username=app --dbname=app \
--format=custom > transfer/app.dump
База остаётся запущенной для согласованного дампа. Проверьте завершение команды и файл. Если настроена парольная аутентификация, используйте предусмотренный для проекта доступ, не добавляйте пароль в эту строку. Пример предполагает PostgreSQL 16 и одну роль app. Подробности и ограничения прав — в переносе PostgreSQL.
Ниже oldapp_uploads — фактическое имя тома из Mounts. Замените его своим. Тома с файлами архивируем после остановки записи, а каталог работающего PostgreSQL таким способом не копируем:
docker volume inspect oldapp_uploads >/dev/null && \
docker run --rm \
--mount type=volume,src=oldapp_uploads,dst=/data,readonly \
--mount type=bind,src="$PWD/transfer",dst=/transfer \
alpine:3.22 tar -C /data -czf /transfer/uploads.tar.gz .
cd transfer
sha256sum app.dump uploads.tar.gz > SHA256SUMS
cd ..
Проверка хеша обнаруживает изменение файла при передаче, но не доказывает, что исходная копия была правильной. Новые записи в старый проект пока не включаем.
Передайте конфигурацию и копии
На новом сервере заранее создайте каталог /srv/app с доступом для нужного пользователя. Передавайте файлы по защищённому соединению. Список ниже подходит только проекту, у которого действительно есть эти файлы и каталоги:
rsync -a -- compose.yaml .env app.env secrets transfer ops@new-server:/srv/app/
Если используются override-файлы, другие env_file или bind mounts, добавьте их явно. Важные данные вне перечисленных путей сами не появятся. Секреты должны быть доступны только нужным пользователям и не попадать в репозиторий.
На новой стороне проверьте хеши и конфигурацию:
cd /srv/app/transfer
sha256sum --check SHA256SUMS
cd ..
docker compose -p app-next config --quiet
Поднимите базу и восстановите файлы до запуска приложения
В примере новая площадка использует отдельный Compose-проект app-next. Сначала запускаем только db. Проверьте, что он использует новый пустой том и ту же основную версию PostgreSQL. Готовность pg_isready означает приём подключений, а не готовность восстановленных данных.
docker compose -p app-next up -d db
docker compose -p app-next exec -T db pg_isready --username=app --dbname=app
docker compose -p app-next exec -T db pg_restore \
--username=app --dbname=app --no-owner --no-acl \
--exit-on-error --single-transaction < transfer/app.dump
Если pg_isready ещё не подтверждает готовность, дождитесь её и проверьте логи перед следующим шагом. База app и роль app в этом примере создаются настройками образа PostgreSQL. Для другого проекта сначала подготовьте их отдельно. Не восстанавливайте поверх уже используемой базы.
Создайте контейнер приложения без запуска и ещё раз посмотрите имя его тома:
docker compose -p app-next create web
docker inspect "$(docker compose -p app-next ps --all --quiet web)" \
--format '{{json .Mounts}}'
Далее app-next_uploads — проверенное имя нового тома загрузок. Команда специально требует пустой каталог. Если образ уже положил туда файлы, сначала выясните, что это, вместо автоматического удаления:
docker volume inspect app-next_uploads >/dev/null && \
docker run --rm \
--mount type=volume,src=app-next_uploads,dst=/data \
--mount type=bind,src="$PWD/transfer",dst=/transfer,readonly \
alpine:3.22 sh -c 'test -z "$(ls -A /data)" && tar -C /data -xzf /transfer/uploads.tar.gz'
Проверьте владельца и права файлов под пользователем приложения. Совпадение пути не гарантирует совпадение UID/GID. Не исправляйте эту проблему выдачей прав 777 на весь каталог.
Проверьте приложение и переключите пользователей
До запуска web и worker отключите внешние действия тестовой копии: реальные письма, списания, вебхуки и повторную обработку очередей. Запуск нового фонового сервиса до проверки может повторить уже выполненные операции.
docker compose -p app-next up -d web
docker compose -p app-next ps
docker compose -p app-next logs --tail=100 web db
Проверьте вход, чтение и запись, загрузку старого и нового файла, подключение именно к новой базе. Проверьте перезапуск контейнера: сохранённые данные должны остаться. Логи перед передачей кому-либо просматривайте на секреты и персональные данные.
После проверки включите фоновые задачи и внешние действия в согласованном порядке, переключите трафик. Учтите сертификаты, reverse proxy, DNS и сети. Если на новом сервере запись уже пошла, простой возврат DNS на старый сервер разойдётся с новыми данными.
Старые тома и копии сохраняйте до приёмки. Команды docker compose down --volumes и docker volume prune в план переезда не входят: они могут удалить нужные данные. Общий порядок переключения и отката — в плане переноса проекта.
Как отработать это без риска для рабочего проекта
Возьмите учебное приложение с базой и загрузкой файлов. Создайте запись с вложением, перенесите проект под другим Compose-именем, проверьте её и создайте новую. Затем перезапустите контейнеры и убедитесь, что обе записи и оба файла сохранились.
Отдельно проверьте неправильный пароль, недостающий файл и ошибку в имени тома. Запишите, по какому признаку нашли причину. Учебная проверка полезнее привычки считать успешный docker compose up доказательством готовности.
Источники
Устройство томов и их копирование описаны в документации Docker Volumes. Подстановка переменных и env_file — в руководстве Docker Compose. Для другого состава сервисов, внешних томов или способа хранения базы порядок нужно адаптировать.
Частые вопросы
Достаточно ли скопировать compose.yaml?
Нет. Нужны доступные образы или исходники для сборки, конфигурация, секреты, базы и файлы подключённых томов. Состав зависит от проекта.
Можно ли архивировать том работающего PostgreSQL?
Обычный архив файлов работающей базы не заменяет предусмотренную для неё резервную копию. В этом примере PostgreSQL переносится через согласованный дамп, а отдельный том загрузок — после остановки записи.
Почему после переноса пропали загруженные файлы?
Проверьте фактические имена томов, bind mounts, пути и права. Новый Compose-проект может подключить новый пустой том вместо перенесённого.
Если нужна помощь с проектом
С переносом приложения, базы и файлов можно обратиться ко мне. С командой разберём зависимости и проверим работу на новой площадке. Обсудить перенос проекта.