Exporting and importing Docker things

TL;DR: The "export" command gives you a flattened tarball of a container's file system, and it can't be used to recreate a running container alone as information is dropped (eg: RUN, USER, etc). The "save" command saves an image of layers, and also things like RUN and USER commands. If you want to move images from one host to another without a Docker registry, use "save" and "load", not "export" and "import".

Meaning: save, load, export, import

  • Docker images are layers of file system tarballs applied one on top of another.
  • A container is a specific instance of an image (created by docker run or docker create).
  • The "save", "load", and "import" commands are related to images.
  • The "export" command is related to containers.

You can not "import an exported container" because information is lost, for example what command to run on startup. Let's go ahead and export a container:

Find an image

$ docker images
REPOSITORY        TAG             IMAGE ID       CREATED        SIZE
minperl           latest          c265df3173ad   9 months ago   67MB
minperl-builder   latest          25287931efbf   9 months ago   1.01GB
perl              5.32.0-buster   2c9e278d16c6   9 months ago   859MB

Create container without starting it

Create an instance of an image (a specific container called "minperl0"):

docker create --name minperl0 minperl:latest

Make sure it was created

Here the "--all" is required because the container is not running, and "ls" by default hides stopped containers.

$ docker container ls --all
CONTAINER ID   IMAGE            COMMAND                  CREATED              STATUS    PORTS     NAMES
658d6314bdef   minperl:latest   "/usr/bin/perl -Iloc…"   About a minute ago   Created             minperl0

Export it

$ docker export minperl0 > minperl0.tar

Delete the container

$ docker container rm 658d6314bdef

Investigate it

$ tar -tf minperl0.tar
.dockerenv
app.psgi
cpanfile
cpanfile.snapshot
...

When I did this .dockerenv was an empty file. As you can see it is simply a tarball of a directory - there is no information there about what command to run, what ports are exposed, what user to run as, etc - that has all been lost.

Importing

Now if you want to take that tarball and move it somewhere else, you have to treat it as an image. You load the image and then create/run containers off that.

$ docker import minperl0.tar minperl2:latest

Here I gave the repository name as "minperl2" to avoid a clash with the original "minperl". Now you can create containers from this image:

$ docker create --name minperl20 minperl2:latest
Error response from daemon: No command specified

Errp! Makes sense right? Because we exported a container and not an image we lost information about the entry point. Docker can not create a container because it doesn't know what command is supposed to be run.

Conclusion

I guess you could say that "export" + "import" is kind of a way of flattening your image into a single layer. Using "save" will preserve those layers and also preserve the RUN command etc. So "export" is actually kinda useless...

Grokking this means you will understand for realz the difference between images and containers.