Alisson Machado
05 June 2016

Redirect de Portas, Redes e IP Fixo no Docker

Eae Galera! Os comandos para definir o IP fixo no Docker só funcionam a partir da versão 1.10 do docker-engine Esse post tem como objetivo mostrar os comandos necessários para administrar redes no Docker e como criar os seus containers com IP Fixo. Bom, o Docker por padrão vem com uma bridge default em uma interface chamada docker0 que possui o range 172.17.0.0/16, quando são criados containers nessa rede, eles pegam o próximo endereço de IP que estiver disponível, porém quando o container é desligado e ligado, é realizado o mesmo processo, então os seus containers ficam com IPs dinâmicos impossibilitando configurações com IP Fixo, como por exemplo fazer o redirecionamento de um proxy reverso como no caso do Nginx para um container. Uma alternativa a isso seria o redirecionamento de portas, ou criar uma rede onde você possa definir o IP fixo para o container. Para ver essa interface padrão do Docker, é só digitar a seguinte instrução:

ip a show dev docker0

4: docker0:  mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:95:f1:d1:ef brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Para fazer o redirecionamento de portas no Docker, você pode utilizar a instrução abaixo:

docker run -ti -p 1234:80 ubuntu /bin/bash

Com essa instrução foi criado um novo container e a porta 1234 do host foi redirecionada para a porta 80 do container, então quando acessarmos http://localhost:1234 você na verdade vai acessar o seu container na porta 80. Parece ser uma coisa de outro mundo, mas na verdade isso nada mais é do que uma regra de iptables. Para provar isso você pode executar a seguinte instrução:

iptables -t nat -L -n

E a saída será parecida com essa:

Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:1234 to:172.17.0.2:80

Na saída do comando é possível ver que existe uma regra de DNAT que faz o redirect da porta 1234 para a porta 80 do ip 172.17.0.2 do container. Uma vez que o container estiver sendo executado você pode ir criado novas regras de iptables e ir direcionando as portas. Para criar um novo redirecionamento você pode criar uma regra da seguinte maneira:

iptables -t nat -A DOCKER -s 0.0.0.0/0 -d 0.0.0.0/0 -p tcp --dport 6543 -j DNAT --to 172.17.0.2:6543

Assim foi redirecionada a porta 6543 do host para a porta 6543 do container cujo o ip é igual a 172.17.0.2. Então se eu listar as regras novamente é possível ver que a nova regra foi adicionada:

iptables -t nat -L -n

Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:1234 to:172.17.0.2:1234
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:6543 to:172.17.0.2:6543

Bom, agora indo para a parte de gerenciamento de redes no Docker. Para visualizar as redes existentes no Docker é necessário executar a seguinte instrução:

docker network ls

NETWORK ID          NAME                DRIVER
557d5241a110        bridge              bridge              
44426ff59dfd        none                null                
1deb1bfeca8e        host                host   

A saída do comando será parecida com a saída acima. Para ver informações sobre uma rede em específico, você pode executar a instrução abaixo:

docker network inspect bridge

O retorno será um json parecido com esse:

[
    {
        "Name": "bridge",
        "Id": "557d5241a110cc126b6974776036f45fc13a7bbbd471c57e3bd88a53227c596e",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {
                    "Subnet": "172.17.0.0/16"
                }
            ]
        },
        "Containers": {
            "8ec3bd237a51362c34e932036f0f84144cc495f3e620164168d088150a26347c": {
                "EndpointID": "dd129bd3e4cb30d5ad275b57d60b851817c09b573460351a2ff61e8de527aefb",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/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"
        }
    }
]

Para criar a sua própria rede você precisa de dois parâmetros, o primeiro é o nome da rede o segundo é a rede em notação CIDR para que o Docker saiba o tamanho da rede. Assim você pode executar a seguinte instrução:

docker network create --subnet 172.18.0.0/16 rede_teste

Após executado o comando será retornado o ID da rede, agora você pode criar nessa rede os containers com IP fixo. A instrução abaixo vai criar um container nessa rede e definir o ip 172.18.0.43 para o container, vou passar também um parâmetro --always=True, assim quando o Docker for reiniciado o container sempre será iniciado junto com o Docker.

docker run -ti --net rede_teste --ip 172.18.0.43 --always=true ubuntu /bin/bash

Agora você tem um container sendo executado com IP fixo. Caso você não precise mais da rede é só deletada com a instrução abaixo:

docker network rm rede_teste

Valeu!