Migrate Docker container

Migrate Docker container

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.

Leave a Reply

Your email address will not be published. Required fields are marked *