НейроАгент

Перенос Docker образов между хостами: Полное руководство

Узнайте несколько способов переноса Docker образов между хостами без использования репозитория. Полное руководство с пошаговыми инструкциями для docker save/load, export/import, сетевых передач и лучших практик.

Как перенести Docker-образы между хостами без использования репозитория?

Мне нужно скопировать Docker-образ с одной машины на другую без использования какого-либо репозитория (частного или публичного). Я создал кастомный образ в VirtualBox, который хочу развернуть на других машинах для использования в продакшене. Проблема в том, что этот образ основан на моем собственном кастомном базовом образе (похожем на Red Hat Linux), что означает, что его нельзя легко воссоздать из Dockerfile. Кроме того, мой Dockerfile не является переносимым между разными средами.

Какие простые команды или альтернативные методы я могу использовать для прямого переноса Docker-образов между хостами без использования репозитория?

НейроАгент

Вы можете передавать Docker-образы между хостами без использования репозитория, используя команду docker save для экспорта образа в виде tar-файла на исходной машине, затем передавая этот файл на целевую машину и, наконец, используя команду docker load для импорта образа. Этот метод сохраняет весь образ, включая все слои, историю и метаданные, что делает его идеальным для пользовательских образов со сложными зависимостями, которые нельзя легко пересобрать из Dockerfile.

Содержание

Понимание задачи

При работе с пользовательскими Docker-образами, особенно теми, что основаны на проприетарных базовых образах или имеют сложные зависимости, передача их между средами может быть сложной. Традиционные методы, такие как пересборка из Dockerfile, часто не работают, когда:

  • Базовый образ является проприетарным или недоступен в открытом доступе
  • Dockerfile содержит конфигурации, специфичные для среды
  • Образ включает скомпилированные бинарные файлы или пакеты, недоступные в стандартных репозиториях
  • Необходимо сохранить точную историю слоев и метаданные

Хорошая новость в том, что Docker предоставляет несколько встроенных методов для передачи полных образов без необходимости использования реестра или репозитория. Эти методы сохраняют всю структуру образа, делая их идеальными для производственных развертываний и пользовательских контейнерных сред.


Метод 1: Использование docker save и docker load

Наиболее надежный метод для передачи полных Docker-образов - использование команд docker save и docker load. Этот подход сохраняет весь образ, включая все слои, историю, метаданные и любые пользовательские настройки.

Как это работает

Команда docker save экспортирует один или несколько образов в архив tar, в то время как docker load импортирует этот архив обратно в Docker как полный образ.

Пошаговый процесс

На исходной машине:

  1. Сохраните образ в tar-файл:

    bash
    docker save -o my-custom-image.tar my-custom-image:tag
    
  2. Если вы хотите сохранить несколько образов одновременно:

    bash
    docker save -o images-collection.tar image1:tag1 image2:tag2
    
  3. Сжмите tar-файл для уменьшения размера передачи (опционально):

    bash
    gzip my-custom-image.tar
    

Передача файла:

Используйте любой метод передачи файлов для перемещения tar-файла на целевую машину:

  • scp my-custom-image.tar.gz user@destination:/path/to/save/
  • rsync -avz my-custom-image.tar.gz user@destination:/path/to/save/
  • Копирование через USB-накопитель, сетевую папку или другие физические носители

На целевой машине:

  1. Если файл сжат, распакуйте его:

    bash
    gunzip my-custom-image.tar.gz
    
  2. Загрузите образ в Docker:

    bash
    docker load -i my-custom-image.tar
    
  3. Проверьте загруженный образ:

    bash
    docker images | grep my-custom-image
    

Преимущества этого метода

  • Сохраняет полную структуру образа: Все слои, история и метаданные сохраняются
  • Работает с любым типом образов: Включая пользовательские базовые образы и многоэтапные сборки
  • Не требует сетевого подключения: Передача через физические носители при необходимости
  • Можно объединять несколько образов: Передача нескольких связанных образов одновременно
  • Сохранение версий: Поддерживаются точные теги и информация о версиях

Ограничения

  • Большие размеры файлов: Несжатые tar-файлы могут быть довольно большими, особенно для сложных образов
  • Время передачи: Может занять больше времени для больших образов по медленным соединениям
  • Место на диске: Требует временного дискового пространства для tar-файла на обеих машинах

Метод 2: Использование docker export и docker import

Альтернативный подход - использование docker export и docker import. Этот метод работает по-другому, экспортируя файловую систему контейнера, а не полные метаданные образа.

Ключевые отличия от save/load

Хотя docker save сохраняет полный образ со всеми слоями и историей, docker export создает архив tar только с файловой системой контейнера. Это приводит к меньшему размеру файла, но с потерей некоторых метаданных.

Когда использовать этот метод

Используйте docker export/import, когда:

  • Вам нужна только файловая система контейнера
  • Размер файла является критически важным фактором
  • Вам не нужно сохранять точную историю образа
  • Вы готовы воссоздать некоторые метаданные

Пошаговый процесс

На исходной машине:

  1. Сначала создайте контейнер из вашего образа (если он еще не запущен):

    bash
    docker create -it my-custom-image:tag /bin/bash
    
  2. Экспортируйте файловую систему контейнера:

    bash
    docker export container-id > my-custom-filesystem.tar
    
  3. Передайте экспортированный файл на целевую машину.

На целевой машине:

  1. Импортируйте файловую систему как новый образ:

    bash
    docker import my-custom-filesystem.tar my-custom-image:new-tag
    
  2. Проверьте импортированный образ:

    bash
    docker images | grep my-custom-image
    

Опционально: Импорт с пользовательскими метаданными

Вы можете указать репозиторий, тег и описание во время импорта:

bash
docker import \
  --change "LABEL maintainer=Ваше Имя" \
  --change "LABEL version=1.0" \
  my-custom-filesystem.tar \
  my-company/my-custom-image:v1.0

Преимущества

  • Меньший размер файла: Нет истории слоев, только файловая система
  • Проще процесс: Меньше шагов в некоторых случаях
  • Гибкие опции импорта: Можно добавлять пользовательские метки и метаданные

Ограничения

  • Потеря истории образа: Информация о слоях и история сборки не сохраняются
  • Один слой: Импортированный образ становится одним слоем, что потенциально увеличивает использование хранилища
  • Требуется промежуточный контейнер: Необходимо сначала создать контейнер (если не используется существующий)

Метод 3: Методы сетевой передачи

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

Использование netcat (nc)

На целевой машине (получатель):

bash
nc -l -p 12345 | docker load

На исходной машине (отправитель):

bash
docker save my-custom-image:tag | nc destination-ip 12345

Использование SSH piping

Прямая передача через SSH:

bash
# Исходная машина
docker save my-custom-image:tag | ssh user@destination "docker load"

С сжатием для лучшей производительности:

bash
# Исходная машина
docker save my-custom-image:tag | gzip | ssh user@destination "gunzip | docker load"

Использование встроенной системы распределения Docker

Для более сложных сценариев можно временно настроить локальное распределение:

  1. На исходной машине:

    bash
    docker run -d -p 5000:5000 --name local-registry registry:2
    
  2. Присвойте тег и отправьте в локальный реестр:

    bash
    docker tag my-custom-image:tag localhost:5000/my-custom-image:tag
    docker push localhost:5000/my-custom-image:tag
    
  3. На целевой машине, вытяните с исходной:

    bash
    docker pull source-ip:5000/my-custom-image:tag
    docker tag source-ip:5000/my-custom-image:tag my-custom-image:tag
    
  4. Очистка:

    bash
    docker stop local-registry
    docker rm local-registry
    

Преимущества сетевых методов

  • Нет промежуточных файлов: Прямая потоковая передача уменьшает использование диска
  • Потенциально более быстрая передача: Особенно с сжатием
  • Автоматизированные процессы: Можно интегрировать в CI/CD конвейеры
  • Масштабируемость: Может обрабатывать несколько образов одновременно

Ограничения

  • Зависимость от сети: Требуется надежное сетевое подключение
  • Вопросы безопасности: Метод передачи становится доступным в сети
  • Требования к файрволу: Может потребоваться открыть конкретные порты
  • Обработка ошибок: Сложнее реализовать надежное восстановление после ошибок

Метод 4: Использование docker cp для конкретных файлов

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

  • Вам нужны только файлы конфигурации
  • Вы хотите извлечь конкретные артефакты
  • Контейнер уже запущен на обеих машинах

Пошаговый процесс

На исходной машине:

  1. Создайте контейнер из вашего образа (если он еще не запущен):

    bash
    docker run -d --name temp-container my-custom-image:tag
    
  2. Скопируйте конкретные файлы из контейнера на хост:

    bash
    # Копирование одного файла
    docker cp temp-container:/path/to/file /local/path/
    
    # Копирование всего каталога
    docker cp temp-container:/path/to/directory /local/path/
    
  3. Удалите временный контейнер:

    bash
    docker stop temp-container
    docker rm temp-container
    
  4. Передайте скопированные файлы на целевую машину.

На целевой машине:

  1. Создайте контейнер из вашего базового образа:

    bash
    docker run -d --name target-container my-base-image:tag
    
  2. Скопируйте файлы в контейнер:

    bash
    # Копирование одного файла
    docker cp /path/to/file target-container:/destination/path/
    
    # Копирование всего каталога
    docker cp /path/to/directory target-container:/destination/path/
    
  3. Зафиксируйте контейнер с новыми файлами:

    bash
    docker commit target-container my-custom-image:new-tag
    
  4. Очистка:

    bash
    docker stop target-container
    docker rm target-container
    

Когда использовать этот метод

  • Частичная передача образов: Когда вам нужны только определенные файлы
  • Управление конфигурацией: Для обновления конфигураций в разных средах
  • Извлечение артефактов: Когда контейнеры генерируют файлы, которые нужно сохранить
  • Инкрементальные обновления: Для внесения небольших изменений в существующие образы

Ограничения

  • Ручной процесс: Больше шагов и возможностей для ошибок
  • Специфично для файлов: Передает только указанные файлы, а не полный образ
  • Зависит от состояния: Требует понимания внутренней структуры контейнера
  • Контроль версий: Сложно отслеживать, какие файлы были изменены

Лучшие практики и рекомендации

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

Оптимизация размера образа

Перед передачей больших образов оптимизируйте их для уменьшения времени передачи и требований к хранилищу:

  1. Очистите ненужные слои:

    bash
    # Удалите промежуточные контейнеры
    docker system prune -a
    
    # Очистите неиспользуемые образы
    docker image prune -a
    
  2. Используйте многоэтапные сборки в вашем Dockerfile для уменьшения конечного размера образа.

  3. Сжимайте образы при передаче:

    bash
    # Сохранение и сжатие за один шаг
    docker save my-image:tag | gzip > my-image.tar.gz
    

Вопросы безопасности

  1. Проверяйте целостность образа после передачи:

    bash
    # Проверьте слои образа
    docker history my-custom-image:tag
    
    # Проверьте контрольные суммы образа
    docker save my-image:tag | sha256sum > checksum.txt
    
  2. Используйте безопасные методы передачи для чувствительных образов:

    bash
    # Зашифрованная передача с gpg
    docker save my-image:tag | gpg -c -o my-image.tar.gz.gpg
    
  3. Сканируйте образы на уязвимости перед развертыванием:

    bash
    docker scan my-custom-image:tag
    

Документирование и контроль версий

  1. Ведите журналы передачи:

    bash
    # Записывайте информацию о передаче
    echo "Передан my-custom-image:tag $(date)" > transfer.log
    
  2. Документируйте зависимости образа и требования.

  3. Отслеживайте версии образов и даты передачи.

Оптимизация производительности

  1. Тестируйте скорости передачи с разными методами:

    bash
    # Замерьте время операции сохранения
    time docker save my-image:tag > /dev/null
    
    # Замерьте время сетевой передачи
    time docker save my-image:tag | nc localhost 12345
    
  2. Используйте параллельные передачи для нескольких образов:

    bash
    # Сохраняйте несколько образов одновременно
    docker save image1:tag1 image2:tag2 | gzip > combined.tar.gz
    

Обработка ошибок и восстановление

  1. Проверяйте успешность импорта:

    bash
    # Проверьте целостность образа после загрузки
    docker load -i my-image.tar
    docker inspect my-image:tag
    
  2. Реализуйте механизмы повтора для сетевых передач:

    bash
    # Повторите неудачную передачу
    until docker save my-image:tag | ssh user@destination "docker load"; do
      echo "Передача не удалась, повторяю..."
      sleep 5
    done
    

Пошаговые примеры

Вот полные примеры для разных сценариев, с которыми вы можете столкнуться при передаче Docker-образов.

Пример 1: Базовая передача образа

Сценарий: Передача пользовательского образа веб-сервера с разработки на производство.

Машина разработки:

bash
# Сохраните образ
docker save -o web-server.tar my-company/web-server:v1.0

# Сожмите для более быстрой передачи
gzip web-server.tar

# Передайте на производство
scp web-server.tar.gz production-server:/tmp/

Машина производства:

bash
# Распакуйте
gunzip /tmp/web-server.tar.gz

# Загрузите образ
docker load -i /tmp/web-server.tar

# Проверьте
docker images | grep web-server

Пример 2: Передача нескольких образов

Сценарий: Передача многосервисного приложения с несколькими зависимыми образами.

Исходная машина:

bash
# Сохраните все связанные образы
docker save \
  my-app/frontend:v2.1 \
  my-app/backend:v1.3 \
  my-app/database:v3.0 \
  -o app-stack.tar

# Сожмите и передайте
gzip app-stack.tar && scp app-stack.gz destination:/tmp/

Целевая машина:

bash
# Загрузите все образы
gunzip /tmp/app-stack.tar.gz && docker load -i /tmp/app-stack.tar

# Проверьте, что все образы загружены
docker images | grep my-app

Пример 3: Автоматизированный скрипт передачи

Создайте скрипт для автоматизации процесса передачи:

bash
#!/bin/bash
# transfer-image.sh

SOURCE_IMAGE=$1
DEST_HOST=$2
IMAGE_NAME=$(echo $SOURCE_IMAGE | cut -d: -f1)
IMAGE_TAG=$(echo $SOURCE_IMAGE | cut -d: -f2)

echo "Начинаю передачу $SOURCE_IMAGE на $DEST_HOST"

# Сохраните и сожмите на исходной машине
echo "Сохраняю образ..."
docker save $SOURCE_IMAGE | gzip > /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar.gz

# Передайте на целевую машину
echo "Передаю файл..."
scp /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar.gz $DEST_HOST:/tmp/

# Очистите на исходной машине
rm /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar.gz

# Загрузите на целевой машине
ssh $DEST_HOST "gunzip /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar.gz && docker load -i /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar && rm /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar"

echo "Передача успешно завершена!"

Пример 4: Работа с большими образами

Для очень больших образов (>1GB) используйте эти стратегии:

bash
# Разделите большие tar-файлы на части
split -b 100M -d my-large-image.tar my-large-image.tar.

# Передайте части
for chunk in my-large-image.tar.*; do
  scp $chunk user@destination:/tmp/
done

# Соберите и загрузите на целевой машине
ssh user@destination "cat /tmp/my-large-image.tar.* > /tmp/my-large-image.tar && docker load -i /tmp/my-large-image.tar"

Пример 5: Проверка и валидация

После передачи проверьте целостность образа:

bash
# Сравните размеры образов
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep my-custom-image

# Проверьте слои образа
docker history my-custom-image:tag

# Проверьте функциональность контейнера
docker run --rm my-custom-image:tag --version

# Сравните контрольные суммы (если доступны)
docker save my-custom-image:tag | sha256sum > current_checksum.txt
diff original_checksum.txt current_checksum.txt

Заключение

Передача Docker-образов между хостами без использования репозитория является простой задачей с правильными инструментами и техниками. Комбинация docker save и docker load обеспечивает наиболее надежный метод для сохранения полной целостности образа, в то время как альтернативы, такие как docker export/import, предлагают меньшие размеры файлов, когда сохранение метаданных не является критически важным.

Для вашей конкретной ситуации с пользовательским базовым образом и непереносимым Dockerfile я рекомендую использовать docker save/load как основной метод. Этот подход гарантирует, что все слои, зависимости и метаданные сохранены точно так, как они были созданы в вашей среде VirtualBox.

Ключевые выводы:

  1. Используйте docker save/load для полного сохранения образа - Это лучший выбор для пользовательских образов со сложными зависимостями
  2. Сжимайте большие образы для уменьшения времени передачи и требований к хранилищу
  3. Проверяйте целостность образа после передачи для обеспечения успешного развертывания
  4. Документируйте процесс передачи для воспроизводимости и устранения неполадок
  5. Рассмотрите автоматизированные скрипты для частых или масштабных передач

Следуя этим методам, вы можете надежно развертывать ваши пользовательские Docker-образы в разных средах, сохраняя точные спецификации и функциональность, которые вы разработали.