web-dev-qa-db-fra.com

Modifier la route par défaut dans le conteneur de menu fixe

J'ai un conteneur Docker connecté à deux réseaux, le pont par défaut et un pont personnalisé. Par défaut, il est lié à un autre conteneur uniquement dans le réseau par défaut et via le pont personnalisé, il obtient une adresse IP dans le réseau local.

LAN -- [homenet] -- container1 -- [bridge] -- container2

Sudo docker network inspect homenet
[{  "Name": "homenet",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
        "Driver": "default",
        "Options": {},
        "Config": [{ "Subnet": "192.168.130.0/24",
                     "Gateway": "192.168.130.8",
                     "AuxiliaryAddresses": { "DefaultGatewayIPv4": "192.168.130.3" }}]
    },
    "Internal": false,
    "Containers": {
        "$cid1": { "Name": "container",
                   "EndpointID": "$eid1_1",
                   "MacAddress": "$mac1_1",
                   "IPv4Address": "192.168.130.38/24", }
    },
    "Options": { "com.docker.network.bridge.name": "br-homenet" },
    "Labels": {}}]

et pont:

Sudo docker network inspect bridge

[{
    "Name": "bridge",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
        "Driver": "default",
        "Options": null,
        "Config": [{ "Subnet": "172.17.0.0/16" }]
    },
    "Internal": false,
    "Containers": { 
      "$cid2": {
            "Name": "container2",
            "EndpointID": "$eid2",
            "MacAddress": "$mac2",
            "IPv4Address": "172.17.0.2/16",
            "IPv6Address": "" }, 
      "$cid1": {
            "Name": "container1",
            "EndpointID": "$eid1_2",
            "MacAddress": "$mac1_2",
            "IPv4Address": "172.17.0.3/16",
            "IPv6Address": "" }
    },
    "Options": {
        "com.docker.network.bridge.default_bridge": "true",
        "com.docker.network.bridge.enable_icc": "true",
        "com.docker.network.bridge.enable_ip_masquerade": "true",
        "com.docker.network.bridge.Host_binding_ipv4": "0.0.0.0",
        "com.docker.network.bridge.name": "docker0",
        "com.docker.network.driver.mtu": "1500"
    },
    "Labels": {}
}]

Cela fonctionne plutôt bien à partir du réseau interne, cependant, j'ai un problème de routage:

Sudo  docker exec -it container1 route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
192.168.130.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1

Comment puis-je changer la route par défaut en 192.169.130.3 de telle sorte que le redémarrage persiste?

Je peux le changer lorsque container1 est en cours d'exécution avec

 pid=$(Sudo docker inspect -f '{{.State.Pid}}' container1)
 Sudo mkdir -p /var/run/netns
 Sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
 Sudo ip netns exec $pid ip route del default 
 Sudo ip netns exec $pid ip route add default via 192.168.130.3

mais cela a disparu après un redémarrage. Comment puis-je changer cela?

Mise à jour: Apparemment, l'ordre lexicographique des réseaux pourrait également faire partie du problème. Je le testerai quand j'en aurai l'occasion.

17
martin

nsenter -n -t $ (docker inspecter --format {{.State.Pid}} $ dockername) route ip ajouter quelque chose.

nsenter -n -t $ (docker inspect --format {{.State.Pid}} $ dockername) ip route del quelque chose.

0
Yeats Raw

@ Silicium14

Merci beaucoup pour votre 2ème solution. Il m'a fallu beaucoup de temps pour trouver un moyen de définir des itinéraires au début du conteneur. J'ai un peu modifié vos lignes en fonction de mes besoins car je dois fournir un nom de conteneur de docker events au script.

Je commence d'abord l'auditeur pour mes événements.

docker events --filter 'container=box1' --filter 'container=box2' --filter 'event=start' --filter 'event=stop' --format '{{.Actor.Attributes.name}}'|awk '{ system("/work/route_setting.sh " $1) }'

J'utilise plusieurs filtres car j'ai besoin des événements pour deux conteneurs de type start ou stop Utiliser --format one permet de contrôler très efficacement la sortie. Ainsi, seul le nom du conteneur est affecté à awk. Ce qui déclenche ensuite mon script de routage avec le nom de conteneur correct.

#!/bin/bash

# exit if no container name provided as $1
[ "x$1" = 'x' ] && exit 1
# holds pid of the docker container
pid=''
# read the pid for container
pid=$(docker inspect -f '{{.State.Pid}}' "${1}" 2>/dev/null)
# if for whatevery reason we get pid 0 avoid setting routes
[ "x$pid" = 'x0' ] && pid=''
if [ "x$pid" != 'x' ] ; then
  # let the routing happen 
  mkdir -p /var/run/netns
  ln -s /proc/$pid/ns/net /var/run/netns/$pid
  ip netns exec $pid ip route add 10.0.0.0/8 via 10.66.101.1
  ip netns exec $pid ip route add 192.168.0.0/16 via 10.66.101.1
fi
# clean up broken symlinks which occur when a container is stopped
# verify that your find supports -xtype l
find /var/run/netns -xtype l -exec rm -f '{}' \;
0
jahlives