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