До основного вмісту

Перенесення Docker-контейнерів між серверами

Міграція · 03.02.2025 · 5 хв читання
Ілюстрація до статті «Перенесення Docker-контейнерів між серверами»

Перенесення Docker-контейнерів між серверами зводиться до трьох речей: образів, томів з даними та конфігурації середовища. Контейнер сам по собі не зберігає стан — усе важливе лежить у volume та в змінних .env, тому «перенести контейнер» на практиці означає перенести образ і дані, а потім підняти його заново на новому хості. Якщо Docker на новому сервері ще не встановлено, почніть із базового встановлення Docker на VPS, а для багатоконтейнерних проєктів знадобиться стаття про Docker Compose.

Метод 1: docker save + docker load

Підходить, коли між серверами немає спільного Registry і потрібно передати образ одним файлом — наприклад, під час разового переїзду на новий VPS.

# На старому сервері — зберігаємо образ з усіма шарами
docker save myapp:latest | gzip > myapp.tar.gz

# Передаємо на новий сервер
scp myapp.tar.gz root@NEW_SERVER:/tmp/

# На новому сервері — завантажуємо образ
docker load < /tmp/myapp.tar.gz

# Перевіряємо, що образ на місці і з тим самим ID
docker images | grep myapp

Мінус методу — розмір файлу: образ із товстим базовим шаром (наприклад, повний Ubuntu замість Alpine) легко виходить за кілька гігабайтів, і передавання повільним каналом займає години.

Метод 2: через Docker Registry (рекомендується)

Registry передає лише відсутні шари, підтримує відкат на попередній тег і не вимагає тримати файл образу на диску між серверами.

# Тегуємо і пушимо в Registry
docker tag myapp:latest registry.example.com/myapp:latest
docker push registry.example.com/myapp:latest

# На новому сервері
docker login registry.example.com
docker pull registry.example.com/myapp:latest

Якщо використовуєте docker-compose, для перенесення достатньо скопіювати docker-compose.yml і томи даних — образи перезберуться локально або завантажаться з Registry командою docker compose up -d.

Розбір типових помилок при перенесенні

  • Error response from daemon: conflict: unable to delete ... (must be forced) — образ використовується іншим тегом чи запущеним контейнером; спершу зупиніть контейнери, що використовують образ, або додайте прапорець -f до docker rmi.
  • open /tmp/myapp.tar.gz: no such file or directory — scp перервався посередині передавання або вказано не той шлях; перевірте розмір файлу з обох боків командою ls -la і звірте контрольну суму sha256sum.
  • unauthorized: authentication required — на новому сервері не виконано docker login до приватного Registry або сплив токен доступу.
  • Error: No such image: myapp:latest — описка в тегу під час docker tag або образ не було запушено до спроби pull на іншому сервері.
  • toomanyrequests: You have reached your pull rate limit — анонімні запити до Docker Hub обмежені за IP; виконайте docker login з обліковим записом або використовуйте власний Registry.

Перенесення томів (volumes)

Образ переносить лише код і залежності застосунку. База даних, завантажені файли та логи живуть у volume і переносяться окремо.

# Експорт тому в тимчасовий архів
docker run --rm -v myapp_data:/data -v $(pwd):/backup \
  alpine tar czf /backup/volume_backup.tar.gz -C /data .

# Імпорт на новому сервері у заздалегідь створений том
docker volume create myapp_data
docker run --rm -v myapp_data:/data -v $(pwd):/backup \
  alpine tar xzf /backup/volume_backup.tar.gz -C /data

Порівняння способів перенесення

Критерійdocker save/loadDocker Registry
Що передаєтьсяПовний архів образуЛише нові шари
Чи потрібен окремий сервісНіТак, Registry
Відкат на попередню версіюТреба зберігати старі архіви вручнуПроста зміна тегу
Підходить дляРазового переїзду одного сервераРегулярних деплоїв і кількох серверів

Коли ці способи не підходять

  • Контейнер тримає відкрите мережеве з'єднання зі станом (наприклад, підняту WebSocket-сесію) — перенесення завжди рве такі з'єднання, потрібен маршрут із graceful shutdown на рівні застосунку.
  • Контейнер прив'язаний до пристроїв хоста через --device (GPU, USB-токен) — образ переїде, але без такого самого пристрою на новому сервері частина функціональності не запрацює.
  • Дані змінюються під час експорту тому — якщо застосунок не зупинено, tar на живому volume бази даних може забрати файл у неузгодженому стані; для СУБД переносьте не файли тому, а дамп засобами самої бази.

Чеклист міграції Docker

КрокСтатус
Встановити Docker на новому сервері⬜
Перенести docker-compose.yml⬜
Перенести образи або налаштувати pull з Registry⬜
Перенести томи даних⬜
Оновити .env файли⬜
Перевірити на новому сервері⬜
Перемкнути DNS⬜

Перевірка після перенесення

Перед перемиканням DNS переконайтеся, що стек працює на новому сервері так само, як на старому.

# Усі контейнери підняті і без перезапусків
docker compose ps

# Логи без помилок за останні 5 хвилин
docker compose logs --since=5m

# Застосунок відповідає на внутрішньому порту
curl -I http://127.0.0.1:8080/health

# Дані збігаються: звіряємо кількість рядків у ключовій таблиці
docker exec -it myapp_db psql -U app -c "SELECT count(*) FROM orders;"

Якщо лічильники й логи збігаються зі старим сервером, перемикайте DNS і лише після цього зупиняйте контейнери на старій машині.

Перед зупинкою контейнерів на старому сервері переконайтеся, що всі дані синхронізовані — особливо якщо використовуються persistent volumes з базою даних: останній запис, зроблений після зняття дампу, на новому сервері відсутній.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці