Atribuir IP estático ao contêiner do Docker


205

Agora estou tentando atribuir um IP estático 172.17.0.1 quando um contêiner do Docker for inicializado.

Eu uso a porta 2122 como a porta ssh deste contêiner para permitir que esse contêiner escute a porta 2122.

sudo docker run -i -t -p 2122:2122 ubuntu

Este comando executará um contêiner do Docker com um IP aleatório como 172.17.0.5, mas preciso atribuir um IP específico ao contêiner.

O script de shell a seguir é o que eu refiro à documentação do Docker em configurações avançadas de rede.

pid=$(sudo docker inspect -f '{{.State.Pid}}' <container_name> 2>/dev/null)
sudo rm -rf /var/run/netns/*
sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
sudo ip link add A type veth peer name B
sudo brctl addif docker0 A
sudo ip link set A up
sudo ip link set B netns $pid
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link delete eth0
sudo ip netns exec $pid ip link set dev B name eth0
sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link set eth0 up
sudo ip netns exec $pid ip addr add 172.17.0.1/16 dev eth0
sudo ip netns exec $pid ip route add default via 172.17.42.1

Esse script de shell atribuirá um IP estático 172.17.0.1 e um link para o mundo. Mas sempre que tento ssh neste contêiner do meu local, ele não funciona. Qual é o problema que eu encontrei?


Receio que não haja uma resposta simples para essa pergunta, consulte github.com/docker/docker/issues/6743 e github.com/docker/docker/issues/1179 e leia github.com/jpetazzo/pipework
user2915097

@larrylo, você pode confirmar que iniciou um sshd dentro do contêiner?
Bryan

5
Você está desfazendo todo o roteamento que o daemon do docker faz por você. Contêineres não são VMs.
user2105103

Sim, eu confirmo que eu possa começar sshd dentro do recipiente
LarryLo

Respostas:


291

Fácil com o Docker versão 1.10.1, build 9e83765.

Primeiro, você precisa criar sua própria rede docker (mynet123)

docker network create --subnet=172.18.0.0/16 mynet123

do que simplesmente executar a imagem (vou usar o ubuntu como exemplo)

docker run --net mynet123 --ip 172.18.0.22 -it ubuntu bash

então no shell ubuntu

ip addr

Além disso, você pode usar

  • --hostname especificar um nome de host
  • --add-host para adicionar mais entradas ao / etc / hosts

Documentos (e por que você precisa criar uma rede) em https://docs.docker.com/engine/reference/commandline/network_create/


1
Grande resposta - Basta adicionar algumas informações adicionais: blog.jessfraz.com/post/ips-for-all-the-things
Ole

@cantSleepNow, por algum motivo, só preciso usar minha própria ponte criada br0 padrão, criada no arquivo de interfaces durante a inicialização do sistema (para que NÃO seja criada usando a criação de rede docker), você pode me sugerir como posso obter o mesmo efeito de - -ip parâmetro (obter endereço IP fixo para um contêiner) sem criar minha ponte usando o docker?
Mohammed Noureldin 15/10

@MohammedNoureldin Eu não entendo completamente - também soa como uma nova pergunta, acho que você deveria fazer isso como tal.
cantSleepNow

@cantSleepNow Quero dizer, preciso corrigir o endereço IP do contêiner, embora NÃO use ponte personalizada (portanto, o parâmetro --ip não pode ser usado), você sugere alguma maneira de obtê-lo?
Mohammed Noureldin 15/10

@MohammedNoureldin Não tenho certeza. Como eu disse, poste sua pergunta como pergunta e não como um comentário - talvez haja alguém que saiba a resposta.
cantSleepNow

89

Para docker-composevocê pode usar o seguintedocker-compose.yml

version: '2'
services:
  nginx:
    image: nginx
    container_name: nginx-container
    networks:
      static-network:
        ipv4_address: 172.20.128.2
networks:
  static-network:
    ipam:
      config:
        - subnet: 172.20.0.0/16
          #docker-compose v3+ do not use ip_range
          ip_range: 172.28.5.0/24

do host, você pode testar usando:

docker-compose up -d
curl 172.20.128.2

Moderno docker-composenão altera o endereço IP com tanta frequência.

Para encontrar ips de todos os contêineres no seu docker-composeem uma única linha, use:

for s in `docker-compose ps -q`; do echo ip of `docker inspect -f "{{.Name}}" $s` is `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $s`; done

Se você deseja automatizar, pode usar algo como este exemplo gist


2
Parece que isso funcionará apenas na compatibilidade com o docker-compose v2, v3.
Andrzej Rehmann 27/03

4
Ao usar o docker-compose v3 + removeip_range
Andrzej Rehmann 27/03

Eu não entendo o ip_range embora. isso não é coberto pela sub-rede? De qualquer forma, obrigado! Que fixa o meu "Eu tenho que procurar o ip do meu recipiente mongo novamente" - tema
Ben

1
existe uma maneira de especificar o endereço IP no compor versão 3?
ealeon

2
A solução funciona bem para mim sem ip_range. Estou usando a versão: '3.4'.
Mikhail Morfikov

24

Não é uma resposta direta, mas poderia ajudar.

Eu executo a maioria dos meus serviços dockerized vinculados aos próprios ips estáticos usando a próxima abordagem:

  1. Crio aliases de ip para todos os serviços no host do docker
  2. Em seguida, executo cada serviço redirecionando portas deste IP para o contêiner, para que cada serviço tenha um IP estático próprio, que pode ser usado por usuários externos e outros contêineres.

Amostra:

docker run --name dns --restart=always -d -p 172.16.177.20:53:53/udp dns
docker run --name registry --restart=always -d -p 172.16.177.12:80:5000 registry
docker run --name cache --restart=always -d -p 172.16.177.13:80:3142 -v /data/cache:/var/cache/apt-cacher-ng cache
docker run --name mirror --restart=always -d -p 172.16.177.19:80:80 -v /data/mirror:/usr/share/nginx/html:ro mirror
...

Obrigado ~ eu sei disso. Assim como github.com/brandon-rhodes/fopnp/tree/m/playground do. Eu vou tentar isso.
LarryLo

1
Esta é uma solução muito boa, gostaria apenas de anexar este link para os novos usuários para aprender sobre aliasing cyberciti.biz/faq/...
Mohammed Noureldin

Obrigado pela boa solução.
precisa

4

Isso funciona para mim.

Crie uma rede com docker network create --subnet=172.17.0.0/16 selnet

Executar imagem do Docker docker run --net selnet --ip 172.18.0.2 hub

No começo eu consegui

docker: Error response from daemon: Invalid address 172.17.0.2: It does not belong to any of this network's subnets.
ERRO[0000] error waiting for container: context canceled

Solução: Aumento do 2º quadruplo do IP [.18. em vez de 0,17.]


3
Há uma resposta semelhante / idêntica 2 anos mais velho em outros lugares desta página: stackoverflow.com/a/35359185/694469
KajMagnus

2

Eu me deparei com esse problema durante a tentativa de encaixar o Avahi, que precisa estar ciente de seu IP público para funcionar corretamente. A atribuição de IP estático ao contêiner é complicada devido à falta de suporte à atribuição de IP estático no Docker.

Este artigo descreve a técnica de como atribuir IP estático ao contêiner no Debian :

  1. O serviço Docker deve ser iniciado com DOCKER_OPTS="--bridge=br0 --ip-masq=false --iptables=false". Presumo que a br0ponte já esteja configurada.

  2. O contêiner deve ser iniciado com --cap-add=NET_ADMIN --net=bridge

  3. Recipiente dentro pre-up ip addr flush dev eth0no /etc/network/interfacespode ser usada para descartar o endereço IP atribuído pelo Docker como no exemplo a seguir:


auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    pre-up ip addr flush dev eth0
    address 192.168.0.249
    netmask 255.255.255.0
    gateway 192.168.0.1
  1. O script de entrada do contêiner deve começar com /etc/init.d/networking start. O script de entrada também precisa editar ou preencher o /etc/hostsarquivo para remover referências ao IP atribuído ao Docker.

2

Você pode definir o IP enquanto o executa.

docker run --cap-add=NET_ADMIN -dit imagename /bin/sh -c "/sbin/ip addr add 172.17.0.12 dev eth0; bash"

Veja meu exemplo em https://github.com/RvdGijp/mariadb-10.1-galera


infelizmente isso acrescenta mais um endereço de IP, se um endereço IP foi atribuído no processo antes, isso resulta em ter dois endereços IP
Davey

1

Você pode acessar o serviço de outros contêineres pelo nome ( ping apacheobterá o ip ou acessaria curl http://apacheo serviço http). E isso pode ser uma alternativa a um IP estático.


3
Na versão docker do 1.8, isso funciona diretamente. Na versão mais recente, você deve vincular esses contêineres.
Guisong He 03/03

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.