How to Copy Docker images from one host to another host?

Docker uses prebuilt images to run containers. If there's a need to run a particular container on multiple hosts, we first need to ensure that the required container image is present on all hosts. The container images can vary in size and their actual size depends upon the type of packages present in the container.

If we’re working with large sized images in an environment with low network bandwidth, pulling container images from online registries can be time consuming. In such cases, we need to avoid accessing external registries frequently and find a way to copy images locally between hosts.

Pulling and saving docker images

When running containers through docker, we specify the image to be used. The image is downloaded from a container image registry and is then stored locally on the host. This gives us two major benefits.

  1. First, we avoid downloading the same image repeatedly.
  2. Secondly, as we have a local copy of the image available, we can minimize the deployment time for a container. Any custom container images we build are also stored in the same local storage.

When working in a production environment, we can often come across scenarios where a developer finishes testing a custom container image and needs to transfer this image to another developer in either a development or production environment. This can be achieved in multiple ways. We’ll discuss these methods one by one.

Copying docker images between hosts

The following methods can be used to copy docker images between hosts:

  1. Using docker save
  2. Using docker save with native ssh command
  3. Using docker-push-ssh utility
  4. Using docker machine save
  5. Using docker machine scp
  6. Conclusion

Prerequisites

Any Linux distribution with docker and docker machine installation will work for the following tutorial. Docker machine can be installed by following this link. The docker-push-ssh utility can be installed by following this link.


1. Using docker save

Once an image has been pulled from an external registry and saved on local storage. These images from the local storage can be saved to a tar file using the docker save command. The generated file is not a regular TAR archive; it contains image metadata and preserves the original image layers. Using this file, docker can recreate the original image exactly as it was.

Example

In the following example, we’re going to save the alpine image to a tar file using "docker save" and copy it to a remote host using the native SCP command.

1docker save -o alpine.tar alpine
2
3scp alpine.tar user@node2:~/
1user@node1:~$ docker images
2REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
3alpine       latest    e66264b98777   6 weeks ago   5.53MB
4user@node1:~$
5user@node1:~$ docker save -o alpine.tar alpine
6user@node1:~$
7user@node1:~$ scp alpine.tar user@node2:~/
8alpine.tar                                    100% 5684KB  10.0MB/s   00:00
9user@node1:~$ 

On the remote host, you can load the image using the “docker load" command.

1docker load -i alpine.tar 
1user@node2:~$ docker load -i alpine.tar
224302eb7d908: Loading layer [==================================================>]  5.811MB/5.811MB
3Loaded image: alpine:latest
4user@node2:~$ 

2. Using docker save with native ssh command

We can also save and transfer docker images by combining "docker save" with the Linux native SSH command. If the image size is large, we can also perform compression on the image to save bandwidth while the image is being transferred over the network. Any compression method can be used for this purpose. The "docker load" command can decompress images saved in bzip2, gzip, and gz. Therefore, it is recommended to save the image in any one of these three formats.

Example

In the following example, we’re going to save the alpine image, compress it using the bzip2 utility on node1, and copy it to node2 using ssh.

1docker save alpine | bzip2 | pv | ssh user@node2 docker load
1user@node1:~$ docker save alpine | bzip2 | pv | ssh user@node2 docker load
22.65MiB 0:00:01 [2.50MiB/s] [   <=>                                                                                ]
3Loaded image: alpine:latest
4user@node1:~$
5
6user@node2:~$ docker images
7REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
8alpine       latest    e66264b98777   6 weeks ago   5.53MB
9user@node2:~$ 

3. Using docker-push-ssh utility

docker-push-ssh is a command line utility to push docker images from local to a remote system through an ssh tunnel. It creates a private docker registry on the host, establishes an ssh tunnel and uploads the image over this tunnel. The ssh tunnel is used so that the registry is not exposed to the outside environment.

Example

In the following example, we’re going to push the alpine image using the docker-push-ssh utility. The utility requires that "localhost:5000" is added to the insecure registries list. For connecting to the remote host, key based authentication is required.

1docker-push-ssh -i /user/.ssh/id_rsa user@node2 alpine
 1user@node1:~$ docker-push-ssh -i /user/.ssh/id_rsa user@node2 alpine
 2[REQUIRED] Ensure localhost:5000 is added to your insecure registries.
 3Setting up secure private registry... 
 4Establishing SSH Tunnel...
 5Waiting for SSH Tunnel Initialization...
 6Tagging image(s) for push...
 7Pushing Image(s) from local host...
 8Pushed Image alpine Successfully...
 9Pulling and Retagging Image on remote host...
10Pulled Image alpine Successfully...
11Cleaning up...
12user@node1:~$

The image will already be imported on the remote node.

1user@node2:~$ docker images
2REPOSITORY              TAG       IMAGE ID       CREATED       SIZE
3registry                latest    773dbf02e42e   6 weeks ago   24.1MB
4alpine                  latest    e66264b98777   7 weeks ago   5.53MB
5localhost:5000/alpine   latest    e66264b98777   7 weeks ago   5.53MB
6user@node2:~$ 

4. Using docker machine save

If you’re using docker machine and need to copy images between two machines, this can also be done using the save and load commands.

Example

In the following example, we’ll copy the alpine image available on machine1 to machine2.

1docker-machine ls
2
3docker $(docker-machine config machine1) save alpine | docker $(docker-machine config machine2) load
4
5docker-machine ssh machine1 
 1user@node1:~$ docker-machine ls
 2NAME       ACTIVE      DRIVER       STATE     URL                         SWARM   DOCKER      ERRORS
 3machine1   *           virtualbox   Running   tcp://192.168.99.100:2376           v19.03.12
 4machine2   -           virtualbox   Running   tcp://192.168.99.101:2376           v19.03.12
 5user@node1:~$
 6user@node1:~$ docker-machine ssh machine1
 7   ( '>')
 8  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
 9 (/-_--_-\)           www.tinycorelinux.net
10
11docker@machine1:~$ docker images
12REPOSITORY          TAG                 IMAGE ID            CREATED          SIZE
13alpine              latest              e66264b98777        7 weeks ago     5.53MB
14docker@machine1:~$ 
1user@node1:~$ docker-machine ssh machine2
2   ( '>')
3  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
4 (/-_--_-\)           www.tinycorelinux.net
5docker@machine2:~$ docker images
6REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
7docker@machine2:~$ exit 

To copy the image from machine1 to machine2, run the following command. This will also load the image on macine2.

1docker $(docker-machine config machine1) save alpine | docker $(docker-machine config machine2) load
1user@node1:~$ docker $(docker-machine config machine1) save alpine | docker $(docker-machine config machine2) load
224302eb7d908: Loading layer [==================================================>]  5.811MB/5.811MB
3Loaded image: alpine:latest
4user@node1:~$ 

Verify that the image has been copied and loaded on machine2.

1user@node1:~$ docker-machine ssh machine2
2   ( '>')
3  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
4 (/-_--_-\)           www.tinycorelinux.net 
1docker@machine2:~$ docker images
2REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
3alpine              latest              e66264b98777        7 weeks ago         5.53MB 

5. Using docker machine scp

You can also use scp with docker machine. If you’ve saved an image using "docker save", you can use the "docker-machine scp" command to copy it to a machine.

Example In the following example, we’ll use "docker-machine scp" to copy image from the local host to machine1.

1docker-machine scp alpine.tar machine1:/tmp 
1user@node1:~$ docker-machine ls
2NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER      ERRORS
3machine1   *        virtualbox   Running   tcp://192.168.99.100:2376                 v19.03.12
4user@node1:~$
5user@node1:~$ docker-machine scp alpine.tar machine1:/tmp
6alpine.tar                                                                       100% 5684KB  32.3MB/s   00:00
7user@node1:~$ 

We’ll now import the image.

1docker-machine ssh machine1 docker load -i alpine.tar 
1user@node1:~$ docker-machine ssh machine1 docker load -i alpine.tar
224302eb7d908: Loading layer [==================================================>]  5.811MB/5.811MB
3Loaded image: alpine:latest
4user@node1:~$ 

6. Conclusion

There are several approaches available for copying docker images between hosts. By using any of these methods, we can avoid the recurring use of external registries and reduce container deployment times.

Posts in this Series