Eu tenho um contêiner docker executando jenkins. Como parte do processo de compilação, preciso acessar um servidor Web que é executado localmente na máquina host. Existe uma maneira de o servidor Web host (que pode ser configurado para ser executado em uma porta) ser exposto ao contêiner jenkins?
Edição: Estou executando docker nativamente em uma máquina Linux.
ATUALIZAR:
Além da resposta do @larsks abaixo, para obter o endereço IP do IP do host da máquina host, faça o seguinte:
ip addr show docker0 | grep -Po 'inet \K[\d.]+'
docker
docker-container
Tri Nguyen
fonte
fonte
curl: (7) Failed to connect to 172.17.1.78 port 7000: No route to host
Respostas:
Ao executar o Docker nativamente no Linux, você pode acessar os serviços de host usando o endereço IP da
docker0
interface. De dentro do contêiner, essa será sua rota padrão.Por exemplo, no meu sistema:
E dentro de um contêiner:
É bastante fácil extrair esse endereço IP usando um simples script de shell:
Pode ser necessário modificar as
iptables
regras do seu host para permitir conexões de contêineres do Docker. Algo assim fará o truque:Isso permitiria o acesso a qualquer porta no host a partir de contêineres do Docker. Observe que:
As regras do iptables são ordenadas, e essa regra pode ou não fazer a coisa certa, dependendo de outras regras que vierem antes dela.
você só poderá acessar serviços de host que (a) estão ouvindo
INADDR_ANY
(também conhecido como 0.0.0.0) ou que estão ouvindo explicitamente nadocker0
interface.fonte
docker.for.mac.localhost
vez delocalhost
ou127.0.0.1
. Aqui está o doc .Para macOS e Windows
Docker v 18.03 e superior (desde 21 de março de 2018)
Use seu endereço IP interno ou conecte-se ao nome DNS especial
host.docker.internal
que resolverá o endereço IP interno usado pelo host.Suporte para Linux pendente https://github.com/docker/for-linux/issues/264
MacOS com versões anteriores do Docker
Docker para Mac v 17.12 a v 18.02
O mesmo que acima, mas use em seu
docker.for.mac.host.internal
lugar.Docker para Mac v 17.06 a 17.11
O mesmo que acima, mas use em seu
docker.for.mac.localhost
lugar.Docker para Mac 17.05 e abaixo
Para acessar a máquina host a partir do contêiner do docker, você deve anexar um alias de IP à sua interface de rede. Você pode vincular o IP que desejar, apenas certifique-se de não usá-lo com mais nada.
sudo ifconfig lo0 alias 123.123.123.123/24
Em seguida, verifique se o servidor está ouvindo o IP mencionado acima ou
0.0.0.0
. Se estiver ouvindo no host local127.0.0.1
, não aceitará a conexão.Em seguida, basta apontar o contêiner do docker para esse IP e você poderá acessar a máquina host!
Para testar, você pode executar algo como
curl -X GET 123.123.123.123:3000
dentro do contêiner.O alias será redefinido a cada reinicialização, portanto, crie um script de inicialização, se necessário.
Solução e mais documentação aqui: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
fonte
docker.for.mac.localhost
que resolverá o endereço IP interno usado pelo host! ... Eu testei e está realmente funcionando! :)ip route show | awk '/default/ {print $3}'
dar um IP edocker.for.mac.localhost
outro.host.docker.internal
docs.docker.com/docker-for-mac/networking/…host.docker.internal
no contêiner do docker e a configuração127.0.0.1 host.docker.internal
no arquivo hosts .Use
--net="host"
em seudocker run
comando e,localhost
em seguida, em seu contêiner de docker apontará para o host do docker.fonte
network_mode: "host"
Solução com docker-compose: Para acessar o serviço baseado em host, você pode usar o
network_mode
parâmetro https://docs.docker.com/compose/compose-file/#network_modeEDIT 2020-04-27: recomendado para uso somente em ambiente de desenvolvimento local.
fonte
Atualmente, a maneira mais fácil de fazer isso no Mac e no Windows é usando o host
host.docker.internal
, que resolve o endereço IP da máquina. Infelizmente ainda não funciona no linux (a partir de abril de 2018).fonte
Criei um contêiner de docker para fazer exatamente isso https://github.com/qoomon/docker-host
Você pode simplesmente usar o nome do container dns para acessar o sistema host, por exemplo
curl http://dockerhost:9200
fonte
Descobrimos que uma solução mais simples para todo esse lixo de rede é usar apenas o soquete do domínio para o serviço. Se você estiver tentando se conectar ao host de qualquer maneira, basta montar o soquete como um volume e estará a caminho. Para o postgresql, isso era tão simples quanto:
Depois, configuramos nossa conexão com o banco de dados para usar o soquete em vez da rede. Literalmente tão fácil.
fonte
Eu explorei as várias soluções e considero a solução menos hacky:
extra_hosts
diretiva.A única desvantagem é que, se você tiver várias redes ou projetos, precisará garantir que o intervalo de endereços IP deles não entre em conflito.
Aqui está um exemplo do Docker Compose:
Você pode acessar as portas no host de dentro do contêiner usando o nome do host "dockerhost".
fonte
Para sistemas Linux, você pode - a partir da versão principal
20.04
- agora também se comunicar com o host viahost.docker.internal
. Isso não funcionará automaticamente , mas você precisará fornecer o seguinte sinalizador de execução:Vejo
fonte
Você pode acessar o servidor da web local que está sendo executado em sua máquina host de duas maneiras.
Abordagem 1 com IP público
Use o endereço IP público da máquina host para acessar o servidor da web no contêiner do docker Jenkins.
Abordagem 2 com a rede host
Use "--net host" para adicionar o contêiner da janela de encaixe Jenkins na pilha de rede do host. Os contêineres implantados na pilha do host têm acesso completo à interface do host. Você pode acessar o servidor da web local no contêiner do docker com um endereço IP privado da máquina host.
Inicie um contêiner com a rede host
Eg: docker run --net host -it ubuntu
e executeifconfig
para listar todos os endereços IP de rede disponíveis acessíveis a partir do contêiner de docker.Por exemplo: iniciei um servidor nginx na minha máquina host local e posso acessar os URLs do site nginx a partir do contêiner do docker do Ubuntu.
docker run --net host -it ubuntu
Acessando o servidor da web Nginx (em execução na máquina host local) a partir do contêiner do docker do Ubuntu com o endereço IP da rede privada.
fonte
Para
docker-compose
usar a rede em ponte para criar uma rede privada entre contêineres, a solução aceitadocker0
não funciona porque a interface de saída dos contêineres não é,docker0
mas sim um ID de interface gerado aleatoriamente, como:Infelizmente, esse ID aleatório não é previsível e será alterado sempre que a composição for necessária para recriar a rede (por exemplo, em uma reinicialização do host). Minha solução para isso é criar a rede privada em uma sub-rede conhecida e configurar
iptables
para aceitar esse intervalo:Redigir fragmento de arquivo:
Você pode alterar a sub-rede se o seu ambiente exigir. Selecionei arbitrariamente
192.168.32.0/20
usandodocker network inspect
para ver o que estava sendo criado por padrão.Configure
iptables
no host para permitir a sub-rede privada como uma fonte:Esta é a
iptables
regra mais simples possível . Você pode querer adicionar outras restrições, por exemplo, pela porta de destino. Não se esqueça de manter as regras do iptables quando estiver feliz que elas estejam funcionando.Essa abordagem tem a vantagem de ser repetível e, portanto, automatizável. Uso o
template
módulo da ansible para implantar meu arquivo de composição com substituição de variável e, em seguida, uso os módulosiptables
eshell
para configurar e manter as regras de firewall, respectivamente.fonte
iptables -A INPUT -i docker0 -j ACCEPT
, mas isso não me ajudou, enquanto asiptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPT
sugeridas aqui resolveram meu problema.Esta é uma pergunta antiga e tinha muitas respostas, mas nenhuma delas se encaixa bem o suficiente no meu contexto. No meu caso, os contêineres são muito enxutos e não contêm nenhuma das ferramentas de rede necessárias para extrair o endereço IP do host de dentro do contêiner.
Além disso, o uso da
--net="host"
abordagem é muito aproximado e não é aplicável quando se deseja ter uma configuração de rede bem isolada com vários contêineres.Portanto, minha abordagem é extrair o endereço dos hosts no lado do host e depois passá-lo para o contêiner com o
--add-host
parâmetro:ou salve o endereço IP do host em uma variável de ambiente e use a variável posteriormente:
E então, ele
docker-host
é adicionado ao arquivo de hosts do contêiner e você pode usá-lo nas cadeias de conexão do banco de dados ou nos URLs da API.fonte
Quando você tem duas imagens do docker "já" criadas e deseja colocar dois contêineres para se comunicar um com o outro.
Para isso, você pode executar convenientemente cada contêiner com seu próprio nome - e usar o sinalizador --link para ativar a comunicação entre eles. Você não consegue isso durante a construção do docker.
Quando você está em um cenário como eu, e é o seu
Isso quebra quando você tenta
e você fica preso no "curl / wget", retornando nenhuma "rota para o host".
O motivo é a segurança estabelecida pelo docker que, por padrão, está banindo a comunicação de um contêiner para o host ou outros contêineres em execução no host. Isso foi bastante surpreendente para mim, devo dizer, que você esperaria que o ecossistema de máquinas docker rodando em uma máquina local simplesmente pudesse acessar uma à outra sem problemas demais.
A explicação para isso é descrita em detalhes na documentação a seguir.
http://www.dedoimedo.com/computers/docker-networking.html
São fornecidas duas soluções rápidas que ajudam você a se mover diminuindo a segurança da rede.
Espero que esta informação te ajude.
fonte
--link
agora está obsoleta.Para mim (Windows 10, Docker Engine v19.03.8), foi uma mistura de https://stackoverflow.com/a/43541732/7924573 e https://stackoverflow.com/a/50866007/7924573 .
por exemplo: LOGGER_URL = " http: //host.docker.internal: 8085 / log "
version: '3.7' services: server: build: . ports: - "5000:5000" network_mode: bridge
ou alternativamente: Use--net="bridge"
se você não estiver usando o docker-compose (semelhante a https://stackoverflow.com/a/48806927/7924573 )Conforme indicado nas respostas anteriores: Isso deve ser usado apenas em um ambiente de desenvolvimento local .
Para obter mais informações, leia: https://docs.docker.com/compose/compose-file/#network_mode e https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds
fonte