https://bobcares.com/blog/move-docker-container-to-another-host/
https://stackoverflow.com/questions/28734086/how-to-move-docker-containers-between-different-hosts
Задача
Нужно мигрировать контейнеры docker (инсталляцию AWX) на новый хост. Инсталляция содержит 5 контейнеров, развернутых с помощью docker compose.
Контейнеры имеют смонтированные volumes, а также имеют файлы, установленные непосредственно в контейнер.
Переносим **Volumes**
Предварительно, на целевом хосте настроена аутентификация по ключу, пользователь добавлен в группу sudo, а в /etc/sudoers прописано %sudo ALL=(ALL) NOPASSWD:ALL.
Скрипт просматривает конфигурацию контейнеров awx, берет оттуда настройки mounts, создает на удаленном хосте такие же и копирует данные.
#!/bin/bash
remote_host=awx
user=usik.ma
#pass=password
rsync_path="sudo rsync"
containers=`docker container ls --format "{{json .Names}}" | grep awx_ | sed 's/\"//g'`
for container in $(echo $containers)
do
echo "container - $container"
docker container stop $container
mounts=`docker container inspect $container --format "{{ range .Mounts }}{{ .Type }}:{{ .Name }}:{{ .Source }}:{{ .Destination }} {{ end }}"`
for mount in `echo $mounts`
do
mount_type=`echo $mount | cut -d: -f1`
case $mount_type in
bind)
echo "type - bind"
echo $mount
bind_src=`echo $mount | cut -d: -f3`
echo "Bind SRC - $bind_src"
rsync -aRvvP --rsync-path="$rsync_path" $bind_src $user@$remote_host:/
;;
volume)
echo "type - Volume"
echo $mount
vol_name=`echo $mount | cut -d: -f2`
# echo $pass | ssh -tt $user@$remote_host "sudo docker volume create $vol_name"
ssh $user@$remote_host "sudo docker volume create $vol_name"
vol_local_mountpoint=`docker volume inspect $vol_name --format "{{json .Mountpoint}}" | sed 's/\"//g'`
# vol_remote_mountpoint=`echo $pass | ssh -tt $user@$remote_host "sudo docker volume inspect $vol_name --format '{{json .Mountpoint}}' | sed 's/\"//g'"`
vol_remote_mountpoint=`ssh $user@$remote_host "sudo docker volume inspect $vol_name --format '{{json .Mountpoint}}' | sed 's/\"//g'"`
vol_remote_mountpoint=`echo $vol_remote_mountpoint | sed 's/^[^\/]*\//\//'`
echo "local mountpoint - $vol_local_mountpoint; remote mountpoint - $vol_remote_mountpoint"
rsync -avvP --rsync-path="$rsync_path" $vol_local_mountpoint $user@$remote_host:$vol_remote_mountpoint
;;
esac
done
docker container start $container
done
Создаем коммит с текущим состоянием контейнеров
while read -r line; do docker commit $line; done < <(docker container ls --format "{{json .ID}} {{json .Names}}_current" | grep awx_ | sed 's/\"//g')
Переносим images на новый хост и загружаем их
#while read -r line; do docker save $line | ssh -C awx docker load; done < <(docker images --format "{{json .Repository}}" | grep _current | sed 's/\"//g') while read -r line; do docker save $line | ssh -C awx docker load; done < <(docker images --format "{{json .Repository}}" | sed 's/\"//g')
Удаляем коммиты имиждей на исходном хосте
while read -r line; do docker image rm $line; done < <(docker images --format "{{json .Repository}}" | grep _current | sed 's/\"//g')
Создаем контейнеры на новом хосте
А теперь можно создать контейнеры из скопированных имиджей с помощью команды docker create, либо воспользоваться docker compose. Файл лежит тут: /opt/awx/awxcompose/docker-compose.yml. Переносим его на новый хост:
rsync -avvP --rsync-path="rsync sudo" /opt/awx/awxcompose/docker-compose.yml $user@$remote_host:/opt/awx/awxcompose/docker-compose.yml
Редактируем его, указывая в качестве имиджей - те, что были созданы, а также указывая restart: always. У меня пролучилось примерно так:
version: '2' services: web: image: awx_web_current container_name: awx_web depends_on: - rabbitmq - memcached - postgres ports: - "80:8052" hostname: awxweb user: root restart: always volumes: - "/opt/awx/awxcompose/SECRET_KEY:/etc/tower/SECRET_KEY" - "/opt/awx/awxcompose/environment.sh:/etc/tower/conf.d/environment.sh" - "/opt/awx/awxcompose/credentials.py:/etc/tower/conf.d/credentials.py" environment: http_proxy: https_proxy: no_proxy: task: image: awx_task_current container_name: awx_task depends_on: - rabbitmq - memcached - web - postgres hostname: awx user: root restart: always volumes: - "/opt/awx/awxcompose/SECRET_KEY:/etc/tower/SECRET_KEY" - "/opt/awx/awxcompose/environment.sh:/etc/tower/conf.d/environment.sh" - "/opt/awx/awxcompose/credentials.py:/etc/tower/conf.d/credentials.py" environment: http_proxy: https_proxy: no_proxy: rabbitmq: image: awx_rabbitmq_current container_name: awx_rabbitmq restart: always environment: RABBITMQ_DEFAULT_VHOST: "awx" RABBITMQ_DEFAULT_USER: "guest" RABBITMQ_DEFAULT_PASS: "PTB4h5Zt1m1BSu8J" RABBITMQ_ERLANG_COOKIE: cookiemonster http_proxy: https_proxy: no_proxy: memcached: image: "awx_memcached_current" container_name: awx_memcached restart: always environment: http_proxy: https_proxy: no_proxy: postgres: image: awx_postgres_current container_name: awx_postgres restart: always volumes: - /opt/awx/pgsql_db:/var/lib/postgresql/data:Z environment: POSTGRES_USER: awx POSTGRES_PASSWORD: aZKX3FzQ7RdIfGGM POSTGRES_DB: awx PGDATA: /var/lib/postgresql/data/pgdata http_proxy: https_proxy: no_proxy:
После этого переходим в папку c файликом docker-compose.yml и запускаем наши контейнеры:
cd /opt/awx/awxcompose/ docker-compose up -d
После запуска остановим контейнеры и перезагрузимся, чтобы убедиться, что они нормально стартуют:
docker stop $(docker ps -a -q) sudo reboot
Discussion