When a container is running, it is possible to export its filesystem to a tar file, using the command docker export <mycontainer>
. Later, it is possible to import that filesystem into Docker to be used as a Docker image, using a command like docker import <mytarfile>
. The problem is that the new container has lost all the parameters from the original image (i.e. ENTRYPOINT, USER, CMD, etc.).
importcon is a script that enables to import a filesystem exported using docker export
into Docker, and to copy the parameters from the original image (i.e. ENTRYPOINT, USER, CMD, VOLUME, etc.)
If you create a minimal application filesystem (i.e. using minicon), you will get a tarfile that contains the minified filesystem. Then you will probably import it into Docker using the command docker import
(as in the examples). The problem is that the new container will not keep the settings such as ENTRYPOINT, CMD, WORKDIR, etc.
Using importcon, you will be able to import the obtainer tarfile into Docker, but it is possible to provide the name of an existing image as a reference, to copy its parameters (ENV, ENTRYPOINT, CMD, WORKDIR, etc.).
You can get the proper package (.deb o .rpm) from the Releases page and install it using the appropriate package manager.
Ubuntu/Debian
$ apt update
$ apt install ./minicon-1.2-1.deb
CentOS/Fedora/RedHat
$ yum install epel-release
$ yum install ./minicon-1.2-1.noarch.rpm
importcon is a bash script that deals with docker commands. importcon is part of the minicon package, and so you just simply need to have a working linux with bash installed and get the code:
$ git clone https://github.com/grycap/minicon
In that folder you'll have the importcon application. I would suggest to put it in the /opt folder. Otherwise leave it in a folder of your choice:
$ mv minicon /opt
importcon depends on the commands jq. So, you need to install the proper packages in your system.
Ubuntu
$ apt-get install jq
CentOS
$ yum install jq
importcon has a lot of options. You are advised to run ./importcon --help
to get the latest information about the usage of the application.
The basic syntax is
$ ./importcon <options> <container filesystem in tar file>
- --image | -i : Name of the existing image to copy the parameters.
- --tag | -t : Tag for the image that will be created from the tarfile (random if not provided)
- --env | -E: Copy ENV settings
- --entrypoint | -e: Copy ENTRYPOINT settings
- --expose | -x: Copy EXPOSE settings
- --onbuild | -o: Copy ONBUILD settings
- --user | -u: Copy USER settings
- --volume | -V: Copy VOLUME settings
- --workdir | -w: Copy WORKDIR settins
- --cmd | -c: Copy CMD settings
- --all | -A: Copy all the previous settings: ENV, ENTRYPOINT, EXPOSE, ONBUILD, USER, VOLUME, WORKDIR and CMD.
- --help | -h: Shows this help and exits.
If we take the next Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
and we build it using the command
docker build . -t tests:apache
Sending build context to Docker daemon 37.89kB
Step 1/5 : FROM ubuntu
---> 20c44cd7596f
Step 2/5 : RUN apt-get update && apt-get install -y --force-yes apache2
...
Successfully built ff6f2573d73b
Successfully tagged tests:apache
Then we can run a container
$ docker run --rm -id -p 10000:80 tests:apache
54cd115ab56afc0446b796336ffbfe4415a27f27c6379d0f3d526d79b7e0396b
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54cd115ab56a tests:apache "/usr/sbin/apache2..." 4 seconds ago Up 2 seconds 443/tcp, 0.0.0.0:10000->80/tcp hungry_payne
And export its filesystem to a file:
$ docker export hungry_payne -o myapache.tar
If we import the file back to a Docker image
$ docker import myapache.tar tests:myapache
sha256:397cc8e14785e4b5819348f99850cca6b641602bac319457d539ec51ec468a9e
Now we can check the differences between the configuration of each image for the new containers:
$ docker inspect tests:apache | jq '.[0].Config'
{
"Hostname": "85a5c35750d6",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"443/tcp": {},
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": null,
"ArgsEscaped": true,
"Image": "sha256:9bd5b7f04adcd3b7c8fce216e7c3b190abb8941e62acbba72a9172b0b50adf00",
"Volumes": {
"/etc/apache2": {},
"/var/log/apache2": {},
"/var/www": {}
},
"WorkingDir": "",
"Entrypoint": [
"/usr/sbin/apache2ctl",
"-D",
"FOREGROUND"
],
"OnBuild": [],
"Labels": {}
}
$ docker inspect tests:myapache | jq '.[0].Config'
{
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
}
We can see that our new image has all the setting set to empty. So if we run the container from our new image, the command will fail (because of the lack of the ENTRYPOINT setting):
$ docker run --rm -id -p 10001:80 tests:myapache
docker: Error response from daemon: No command specified.
See 'docker run --help'.
If we import the image using importcon and we inspect the configuration:
$ ./importcon -t tests:apacheimportcon -i tests:apache myapache.tar -A
tests:apacheimportcon
sha256:2319eb385a2be7be1e7f0409ec923643b3273427963ecc0e33f2d067f969a66a
$ docker inspect tests:apacheimportcon | jq '.[0].Config'
{
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"443/tcp": {},
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": null,
"Image": "",
"Volumes": {
"/etc/apache2": {},
"/var/log/apache2": {},
"/var/www": {}
},
"WorkingDir": "",
"Entrypoint": [
"/usr/sbin/apache2ctl",
"-D",
"FOREGROUND"
],
"OnBuild": null,
"Labels": null
}
We see that the settings (in special, the ENTRYPOINT) have been copied from the original tests:apache image. And now we are able to run the container as we did in the original one:
$ docker run --rm -id -p 10001:80 tests:apacheimportcon
6081218d246e0106915a876374a276378912335d3a843f09305939bdd4cd4832
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6081218d246e tests:apacheimportcon "/usr/sbin/apache2..." 7 seconds ago Up 6 seconds 443/tcp, 0.0.0.0:10001->80/tcp naughty_brattain