如何将docker网络从旧容器移动到新容器?

时间:2017-03-02 16:15:51

标签: docker docker-networking dockerpy

我尝试升级容器基本映像,并且需要将网络从旧版本移动到新版本。所以我从旧容器中收集数据,其中

网络配置

creation_data.get('networking_config')看起来像:

{'EndpointsConfig': {'opt_network_4ba465': {'IPAMConfig': {'IPv4Address': '10.49.0.2'}}}}

启动旧容器

def pop_new_container(data, docker_client=None):
    container = docker_api.create_container(
        # todo: use config file
        image='docker.site.org:5000/coaxis/coaxisopt_daemon:latest',
        hostname=data.get('hostname'),
        ports=[80],
        host_config=docker_api.create_host_config(
            port_bindings={80: 80},
            restart_policy={"MaximumRetryCount": 0, "Name": "always"}
        ),
        networking_config=create_network_config(data, docker_client)
    )
    docker_api.start(container=container.get('Id'))
    return container

升级

启动新容器(基于旧的数据)。

def upgrade_daemon_container(old_container_id):
    old_container_data = docker_api.inspect_container(old_container_id)
    creation_data = get_upgrade_data(old_container_data)

    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"}
        ),
        networking_config=creation_data.get('networking_config'),
    )

    return new_container

问题

检查新容器时,网络配置不完整:

旧容器网络配置

{
    "opt_network_823dc9": {
        "Aliases": [
            "2387c3b6b2c2"
        ],
        "EndpointID": "f78a2f64d0eef09c8b965f9e53ea25e45ae5fc0ec977015982106d5a3e364de4",
        "Gateway": "10.49.0.202",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAMConfig": {
            "IPv4Address": "10.49.0.2"
        },
        "IPAddress": "10.49.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "Links": null,
        "MacAddress": "02:42:0a:31:00:02",
        "NetworkID": "474c3b5faa006bbed65d188143f0f34749f1f9e84b25ee0f9629e35b6f588c8a"
    }
}

新容器网络配置

{
    "opt_network_823dc9": {
        "Aliases": null,
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAMConfig": {
            "IPv4Address": "10.49.0.2"
        },
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "Links": null,
        "MacAddress": "",
        "NetworkID": ""
    }
}

1 个答案:

答案 0 :(得分:0)

github上的

Full codetests

解决方案

def upgrade_daemon_container(old_container_id):
    old_container_data = docker_api.inspect_container(old_container_id)
    creation_data = get_upgrade_data(old_container_data)

    network_id = creation_data.get('networking_config').get('EndpointsConfig').copy().popitem()[0]
    docker_api.disconnect_container_from_network(old_container_id, network_id)

    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"}
        ))

    docker_api.disconnect_container_from_network(new_container.get('Id'), 'bridge')
    docker_api.connect_container_to_network(new_container.get('Id'), network_id, ipv4_address=creation_data.get('networking_config').get('IPv4Address'))
    destroy(old_container_id)
    docker_api.start(container=new_container.get('Id'))

    return new_container

测试

def purge(self, containers=[]):
    for container in containers:
        self.docker_api.stop(container['Id'], 0)
        for network in self.docker_api.inspect_container(container['Id'])['NetworkSettings']['Networks']:
            if 'opt_network' in network:
                self.docker_api.remove_network(network)
            self.docker_api.remove_container(container['Id'])

def test_upgrade_container_pop_new_container(self):
    config = {'ip': '10.49.0.2', 'subnet': '10.49.0.0/16', 'gateway': '10.49.0.202', 'vlan': 102}
    container = container_services.pop_new_container(config, self.docker_api)

    new_container = container_services.upgrade_daemon_container(container.get('Id'))

    self.assertNotEqual(container.get('Id'), new_container.get('Id'))
    self.purge([new_container])

def test_upgrade_container_mount_volumes_from_old_to_new_container(self):
    config = {'ip': '10.49.0.2', 'subnet': '10.49.0.0/16', 'gateway': '10.49.0.202', 'vlan': 102}
    container = container_services.pop_new_container(config, self.docker_api)

    old_container_volumes = [volume['Name'] for volume in container_services.get_mounts(container['Id'])]
    new_container = container_services.upgrade_daemon_container(container.get('Id'))
    new_container_volumes = [volume['Name'] for volume in container_services.get_mounts(new_container['Id'])]

    self.assertSetEqual(set(old_container_volumes), set(new_container_volumes))
    self.purge([new_container])

def test_upgrade_container_bind_to_old_network(self):
    config = {'ip': '10.49.0.2', 'subnet': '10.49.0.0/16', 'gateway': '10.49.0.202', 'vlan': 102}
    container = container_services.pop_new_container(config, self.docker_api)

    old_name, old_network = container_services.get_networks(container['Id']).popitem()
    new_container = container_services.upgrade_daemon_container(container.get('Id'))
    new_name, new_network = container_services.get_networks(new_container['Id']).popitem()

    self.assertEqual(old_name, new_name)
    self.assertEqual(old_network['IPAMConfig'], new_network['IPAMConfig'])
    self.assertEqual(old_network['IPAddress'], new_network['IPAddress'])
    self.assertEqual(old_network['Gateway'], new_network['Gateway'])
    self.assertEqual(old_network['MacAddress'], new_network['MacAddress'])
    self.assertEqual(old_network['NetworkID'], new_network['NetworkID'])

    self.purge([new_container])