1

I'm working to implement a mechanism to upgrade the base image of a container. In order to do so I need to:

  1. get the list of volumes from the current container ;
  2. create a new container with configuration from the old container (volume, network, etc.)

Create new container

I tried to do it like:

docker_api.create_container(
        image=creation_data.get('image'),
        hostname=creation_data.get('hostname'),
        volumes=creation_data.get('volumes'),
        host_config=docker_api.create_host_config(
            binds=creation_data.get('volume_bindings'),
            port_bindings={80: 80},
            restart_policy={"MaximumRetryCount": 0, "Name": "always"}
        ))

Creation data

where creation_data are gathered from the old container and look like:

 {
    'image': 'docker.akema.fr:5000/coaxis/coaxisopt_daemon:latest',
    'hostname': "test-01",
    'volumes': [
        "/home/mast/.ssh",
        "/etc/mast"
    ],
    'volumes_bindings': {
        "841d6a1709b365763c85fb4b7400c87f264d468eb1691a660fe81761da6e374f": {
            'bind': "/home/mast/.ssh",
            'mode': 'rw'
        },
        "002730cbb4dd9b37ad808915a60081508885d533fe003b529b8d0ab4fa46e92e": {
            'bind': "/etc/mast",
            'mode': 'rw'
        }
    },
    'networking_config': {
        'EndpointsConfig': {'opt_network_508be7': {'IPAMConfig': {'IPv4Address': '10.0.0.1'}}}
    }
}

Question

When inspecting the new container the Mounts section doesn't seems to have the correct volume, Source fields is a different path.

How do I mount a volume to a new container based on the old container information?

Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178

2 Answers2

3

I don't know how much control you have on how the first container is started, but if you do :

docker run --name container1 --volume vol1:/my/vol1/dir --volume vol2:/my/vol2/dir image1

to run container1, you just need to do this to reuse container1 volumes for container2 :

docker run --name container2 --volume vol1:/my/vol1/dir --volume vol2:/my/vol2/dir image2

And then remove container1 which won't remove volumes (even if they were not already reused by an other container).

vol1 and vol2 data will be stored under /var/lib/docker/volumes/vol1/_data/ and /var/lib/docker/volumes/vol2/_data/ on your host.

So, the answer would be : don't use anonymous volumes for this need, use named volumes. And if u have a legacy container with anonymous volumes you need to reuse, I guess u can just copy them by hand into the named volumes of the new container for this time.

Tristan
  • 8,733
  • 7
  • 48
  • 96
  • I'm working with `docker-py` to [build my container as follow](https://github.com/Coaxis-ASP/opt/blob/7704f46ecb1ccc93ff9a84c3e7d3e34b5c1f447f/backend/api/container_services.py#L14..L27) based on this [Dockerfile](https://github.com/Coaxis-ASP/opt/blob/7704f46ecb1ccc93ff9a84c3e7d3e34b5c1f447f/daemon/Dockerfile#L157). As my dockerfile already specify volumes for those mount point maybe the one from the image take precedence. – Édouard Lopez Feb 28 '17 at 21:26
  • In a Dockerfile, volumes are always anonymous and you can (should) override this when instanciating your container. For example mysql official Dockerfile says "VOLUME /var/lib/mysql", but when you create a container for this image, you should use "-v mysql-data:/var/lib/mysql" to get a reusable named volume. Docker-py had issues with this not long ago, it should be fixed in v2.1.0 : https://github.com/docker/docker-py/issues/1380 – Tristan Mar 01 '17 at 14:12
0

Tristan answer help me getting a working setup, I then declined it to docker-py. The solution is to use the volume Name value (e.g. a87bdc07881fcf139a29…) as source for the mount point.

N.B.: also had a pretty annoying typo: volumes_bindings vs volume_bindings.

Inspect

$ docker inspect my_container  --format "{{ json .Mounts }}" | python -m json.tool
[
    {
        "Destination": "/etc/mast",
        "Driver": "local",
        "Mode": "",
        "Name": "a87bdc07881fcf139a29…",
        "Propagation": "",
        "RW": true,
        "Source": "/var/lib/docker/volumes/a87bdc07881fcf139a29…/_data",
        "Type": "volume"
    }
]

Mount to new container

docker create  \
    --name container \
    --volume a87bdc07881fcf139a29…:/etc/mast \
    docker.site.org:5000/coaxis/coaxisopt_daemon:latest

docker-py

new_container = docker_api.create_container(
    image=creation_data.get('image'),
    hostname=creation_data.get('hostname'),
    volumes=creation_data.get('volumes'),
    host_config=docker_api.create_host_config(
        binds=creation_data.get('volumes_bindings'),
        port_bindings={80: 80},
        restart_policy={"MaximumRetryCount": 0, "Name": "always"}
    ))

with data:

{
            'image': 'docker.akema.fr:5000/coaxis/coaxisopt_daemon:latest',
            'hostname': "test-01",
            'volumes': ["/etc/mast"],
            'volumes_bindings': {
                "a87bdc07881fcf139a29…": {
                    'bind': "/etc/mast",
                    'mode': 'rw'
                }
            },
            'networking_config': {}
        }
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178