Migrate Docker container
Overview
Docker is an open-source containerization platform that uses OS-level virtualization. It allows developers to package applications in an isolated environment called a container. There are various use-cases for containers: a database server, a web application server, etc. The basic principles of working with Docker containers are well-known to the majority of developers, but sooner or later a developer needs to migrate Docker container and this tutorial explains how to make this process simple.
Reasons to migrate Docker container
Let’s imagine that an employer provided us with a new laptop and a previous one has various Docker containers we need. We definitely don’t want to repeat lots of actions to manually re-create Docker containers on a new machine. That’s why it would be useful to have a solution to migrate Docker container to another machine.
Docker terminology
Image is a read-only template with instructions for creating a Docker container.
Container is a runnable instance of an image.
Commit is a command to create a new image from a container.
Volumes are file systems mounted on Docker containers to preserve data generated by the running container. The volumes are stored on the host and are independent of the container life cycle. This allows users to back up data and share file systems between containers easily.
Automate Docker container migration
The migration process will consist of the following main parts:
- Create an image from the latest container’s state
- Save volumes of a container
- Send resulting archives to another machine
- Create a container with volumes on another machine
Here is a script to save a container image with volumes and send them to another machine:
#!/usr/bin/env bash CONTAINER=$1 USER=$2 HOST=$3 OUTPUT_PATH=$4 echo "Stopping a container '$CONTAINER'." # Stop the container docker stop $CONTAINER echo "Creating a new image of a container '$CONTAINER'." # Create a new image docker commit $CONTAINER $CONTAINER echo "Saving the container image to an archive '$CONTAINER'.tar" # Save image docker save -o $CONTAINER.tar $CONTAINER echo "Saving container volumes into '$CONTAINER-volumes.tar'" # Save the volumes (use ".tar.gz" if you want compression) ./docker-volumes.sh $CONTAINER save $CONTAINER-volumes.tar echo "Sending container image and volumes to $HOST/$OUTPUT_PATH" # Copy image and volumes to another host scp $CONTAINER.tar $CONTAINER-volumes.tar $USER@$HOST:$OUTPUT_PATH
Docker volume migration script found on Github.
#!/bin/bash # v1.8 by Ricardo Branco if [[ $1 == "-v" || $1 == "--verbose" ]] ; then v="-v" shift fi if [[ $# -ne 3 || ! $2 =~ ^(save|load)$ ]] ; then echo "Usage: $0 [-v|--verbose] CONTAINER [save|load] TARBALL" >&2 exit 1 fi IMAGE="ubuntu:18.04" # Set DOCKER=podman if you want to use podman.io instead of docker DOCKER=${DOCKER:-"docker"} get_volumes () { cat <($DOCKER inspect --type container -f '{{range .Mounts}}{{printf "%v\x00" .Destination}}{{end}}' "$CONTAINER" | head -c -1) | sort -uz } save_volumes () { if [ -f "$TAR_FILE" ] ; then echo "ERROR: $TAR_FILE already exists" >&2 exit 1 fi umask 077 # Create a void tar file to avoid mounting its directory as a volume touch -- "$TAR_FILE" tmp_dir=$(mktemp -du -p /) get_volumes | $DOCKER run --rm -i --volumes-from "$CONTAINER" -e LC_ALL=C.UTF-8 -v "$TAR_FILE:/${tmp_dir}/${TAR_FILE##*/}" $IMAGE tar -c -a $v --null -T- -f "/${tmp_dir}/${TAR_FILE##*/}" } load_volumes () { if [ ! -f "$TAR_FILE" ] ; then echo "ERROR: $TAR_FILE doesn't exist in the current directory" >&2 exit 1 fi tmp_dir=$(mktemp -du -p /) $DOCKER run --rm --volumes-from "$CONTAINER" -e LC_ALL=C.UTF-8 -v "$TAR_FILE:/${tmp_dir}/${TAR_FILE##*/}":ro $IMAGE tar -xp $v -S -f "/${tmp_dir}/${TAR_FILE##*/}" -C / --overwrite } CONTAINER="$1" TAR_FILE=$(readlink -f "$3") set -e case "$2" in save) save_volumes ;; load) load_volumes ;; esac
Here is a script to create a container with volumes on another machine from received archives:
#!/usr/bin/env bash CONTAINER=$1 # On the other host: docker load -i $CONTAINER.tar docker create --name $CONTAINER $CONTAINER # Load the volumes ./docker-volumes.sh $CONTAINER load $CONTAINER-volumes.tar # Start container docker start $CONTAINER
Let’s imagine we need to migrate Docker container called “db-container” to a machine with IP address 192.168.0.65 and a user “dbuser” to “/home/dbuser/Downloads” location.
In such a case, execute the following command providing the mentioned information as parameters. It will generate two archives (container and volumes) and will send them to a specified host via SCP (it may ask for a password).
./send-container.sh db-container john 192.168.0.65 /home/dbuser/Downloads
After the resulting archives are sent successfully, execute the following command on another machine:
./load-container.sh db-container
As a result, the migrated Docker container should be ready to use on another machine. Note that some container options may be missing (e.g. exposed ports). Then they should either be added manually or the provided load-container script can be adjusted to pass additional options while running a new container.