Como se conectar a um contêiner docker de fora do host (mesma rede) [Windows]

88

Eu criei meu primeiro contêiner do docker, ele está executando um servidor usando Go, mas não consigo acessá-lo de fora do computador host. Acabei de começar com docker, então estou um pouco perdido aqui.

Portanto, eu tenho um código Go muito simples que inicia um servidor, construí a imagem docker que instala Go e constrói o código em uma imagem base do Linux. Estou executando o servidor na porta 8080, então exponho essa porta para o host que executa o contêiner assim:

docker run -p 8080:8080 dockertest

Isso funciona e consigo acessar o servidor por meio do IP da máquina do docker (aquele que aparece no Terminal de início rápido do Docker quando iniciado), o problema é que não consigo acessar o site que estou hospedando de fora do host, então , se eu tentar para abrir o mesmo endereço IP no meu telefone só me dá um erro: Esta página da web não está disponível (ERR_CONNECTION_TIMED_OUT).

Também tentei especificar o IP desta forma:

docker run -p 192.168.0.157:8080:8080 dockertest

Mas, quando faço isso, não consigo acessar o site por meio do IP da máquina docker nem do IP especificado na linha de comando acima. Também não tenho certeza de qual IP devo escrever nesse comando, usei o IP do meu computador, também tentei 127.0.0.1 (localhost), mas me deu o mesmo resultado: não consegui acessar o site por meio de nenhum IP qualquer.

Pesquisei esse problema no Google e encontrei muitas perguntas sobre StackOverflow, mas nenhuma me ajudou a resolver meu problema, a maioria delas era orientada para Linux ou Mac, então a solução não se aplicava à minha situação.

Além disso, posso executar o código Go no meu computador e acessar o site de outro dispositivo na mesma rede através do IP do meu computador. Não entendo por que não consigo acessá-lo quando estou executando-o na máquina docker, ocorreu-me que pode ter algo a ver com encaminhamento de IP ou algo assim, mas sou um completo novato em rede, sou principalmente um desenvolvedor web e quase não tenho experiência em idioma nativo.

sal vermelho
fonte
você usou EXPOSE 8080 em seu Dockerfile em conjunto com a opção -p? Além disso, verifique se a porta 8080 na caixa em que seu contêiner está em execução não está bloqueada por suas regras de segurança.
keda de
@keda Sim, o Dockerfile contém EXPOSE 8080. Estou executando o contêiner localmente no meu computador através do Terminal Quickstart do Docker, também tentei desabilitar o firewall do Windows, mas também não funcionou, não sei se há alguma configuração.
estou

Respostas:

90

TL; DR Verifique o modo de rede de seu host VirtualBox - deve ser bridgedse você quiser que a máquina virtual (e o contêiner Docker que está hospedando) acessível em sua rede local.


Parece que sua confusão está em qual host se conectar para acessar seu aplicativo via HTTP. Você realmente não especificou qual é a sua configuração - vou fazer algumas suposições, com base no fato de que você tem "Windows" e "VirtualBox" em suas tags.

Suponho que você tenha o Docker rodando em algum tipo de Linux rodando no VirtualBox em um host Windows. Vou rotular os endereços IP da seguinte maneira:

D = o endereço IP do contêiner Docker

L = o endereço IP do host Linux em execução no VirtualBox

W = o endereço IP do host Windows

Quando você executa seu aplicativo Go em seu host Windows, pode se conectar a ele http://W:8080/de qualquer lugar em sua rede local. Isso funciona porque o aplicativo Go liga a porta 8080 na máquina Windows e qualquer pessoa que tentar acessar a porta 8080 no endereço IP Wserá conectada.

E é aqui que fica mais complicado:

O VirtualBox, ao configurar uma máquina virtual (VM), pode configurar a rede em um dos vários modos diferentes. Não me lembro quais são as diferentes opções, mas a que você quer é bridged. Neste modo, o VirtualBox conecta a máquina virtual à sua rede local como se fosse uma máquina autônoma na rede, como qualquer outra máquina conectada à sua rede. No bridgedmodo, a máquina virtual aparece em sua rede como qualquer outra máquina. Outros modos configuram as coisas de maneira diferente e a máquina não ficará visível na rede.

Portanto, supondo que você configurou a rede corretamente para o host Linux ( bridged), o host Linux terá um endereço IP em sua rede local (algo como 192.168.0.x) e você poderá acessar seu contêiner Docker em http://L:8080/.

Se o host Linux estiver configurado para algum modo diferente bridged, você poderá acessar do host Windows, mas isso dependerá exatamente do modo em que ele está.

EDITAR - com base nos comentários abaixo, parece muito que a situação que descrevi acima está correta.

Vamos recuar um pouco: é assim que o Docker funciona no meu computador (Ubuntu Linux).

Imagine que eu executar o mesmo comando que você tem: docker run -p 8080:8080 dockertest. O que isso faz é iniciar um novo contêiner com base na dockertestimagem e encaminhar (conectar) a porta 8080 no host Linux (meu PC) para a porta 8080 no contêiner. O Docker configura sua própria rede interna (com seu próprio conjunto de endereços IP) para permitir que o daemon do Docker se comunique e que os contêineres se comuniquem uns com os outros. Então, basicamente o que você está fazendo com isso -p 8080:8080é conectar a rede interna do Docker com a rede "externa" - ou seja, o adaptador de rede do host - em uma porta específica.

Comigo até agora? OK, agora vamos dar um passo atrás e olhar para o seu sistema. Sua máquina está executando o Windows - o Docker (atualmente) não é executado no Windows, portanto, a ferramenta que você está usando configurou um host Linux em uma máquina virtual VirtualBox. Quando você faz isso docker runem seu ambiente, ocorre exatamente a mesma coisa - a porta 8080 no host Linux é conectada à porta 8080 no contêiner. A grande diferença aqui é que seu host Windows não é o host Linux no qual o contêiner está sendo executado, portanto, há outra camada aqui e é a comunicação através desta camada onde você está tendo problemas.

O que você precisa é de duas coisas:

  1. para conectar a porta 8080 no VirtualBox VM à porta 8080 no host do Windows, da mesma forma que você conecta o contêiner do Docker à porta do host.

  2. para conectar o VirtualBox VM diretamente à sua rede local com o bridgedmodo de rede que descrevi acima.

Se você escolher a primeira opção, poderá acessar o contêiner em http://W:8080que Westá o endereço IP ou o nome do host do Windows. Se você optar pelo segundo, poderá acessar o contêiner em http://L:8080que Lestá o endereço IP ou nome do host da VM Linux.

Portanto, essa é toda a explicação de nível superior - agora você precisa descobrir como alterar a configuração do VirtualBox VM. E é aqui que não posso ajudá-lo - não sei qual ferramenta você está usando para fazer tudo isso em sua máquina Windows e não estou familiarizado com o uso do Docker no Windows.

Se você conseguir acessar a janela de configuração do VirtualBox, poderá fazer as alterações descritas a seguir. Também existe um cliente de linha de comando que modificará as VMs, mas não estou familiarizado com isso.

Para o bridgedmodo (e esta realmente é a escolha mais simples), desligue sua VM, clique no botão "Configurações" na parte superior e altere o modo de rede para bridged, reinicie a VM e pronto. A VM deve obter um endereço IP em sua rede local via DHCP e deve ser visível para outros computadores na rede naquele endereço IP.

Kryten
fonte
1
Só consigo encontrar 2 IPs, aquele que o Docker mostra quando abro o Terminal Quickstart (192.168.99.100) e o que meu computador tem (192.168.0.157), usando docker run -p 8080:8080 dockertestPosso acessar meu site usando, http://192.168.99.100:8080mas apenas do meu computador Windows (o host) e não do meu telefone. Se eu usar, docker run -p 192.168.0.157:8080:8080 dockertestnão consigo acessar o site com nenhum IP de nenhum lugar. Não tenho certeza de como configurar a rede, tentei usar, --net=bridgemas também não funcionou. Devo abrir o VirtualBox? Não posso fazer isso usando o terminal do Docker?
redsalt de
O problema não é com o Docker, então não, o Docker não pode ajudá-lo. Vou adicionar algumas edições para ilustrar o que acho que está acontecendo.
Kryten de
Ok, obrigado! Agora que entendi, estava ficando confuso com toda a parte da máquina virtual Linux. Eu tinha a impressão de que o Docker estava usando o Virtual Box para coisas internas que eu não deveria tocar. Na verdade foi muito fácil, só tive que mudar para o bridgedVirtual Box e agora funciona muito bem, muito obrigado.
redsalt de
Não há nenhuma maneira de ter contêineres do windows e docker na mesma rede, para que pudéssemos acessar contêineres diretamente sem o encaminhamento de porta?
Vituel
Tropecei nisso ao pesquisar por servidor Jupyter em execução no docker e tentar acessá-lo via LAN. Existe alguma maneira de descobrir o que L é depois de mudar o modo para com ponte?
PaulDong
121
  1. Abra o Oracle VM VirtualBox Manager
  2. Selecione a VM usada pelo Docker
  3. Clique em Configurações -> Rede
  4. O adaptador 1 deve (padrão?) Ser "Conectado a: NAT"
  5. Clique em Advanced -> Port Forwarding
  6. Adicionar regra: protocolo TCP, porta do host 8080, porta do convidado 8080 (deixe o IP do host e o IP do convidado vazios)
  7. Guest é seu contêiner docker e Host é sua máquina

Agora você deve conseguir navegar para o seu contêiner via localhost: 8080 e your-internal-ip: 8080.

Davey Chu
fonte
10
Confirmado, bom e fácil.
Dirk
2
melhor resposta, sem grande descrição como a selecionada
Amir Qayyum Khan
2
para usuários vagrant, adicione isso em vagrantfile: config.vm.network "forwarded_port", guest: 8080, host: 8080, protocol: "tcp"
Vince Verhoeven
3
Ei! Isso funcionou como um encanto! Obrigado!!!! Eu passo horas tentando descobrir isso.
Joseph Freeman
2
Esta é uma solução fantástica para qualquer pessoa que execute o Docker através do VBox!
Mirodinho,
7

Depois de tentar várias coisas, isso funcionou para mim:

  • use a sinalização docker --publish = 0.0.0.0: 8080: 8080
  • defina o modo de rede da caixa virtual para NAT e não use nenhum encaminhamento de porta

Com endereços diferentes de 0.0.0.0eu não tive sucesso.

mnieber
fonte
4

TLDR: se você tiver o Firewall do Windows habilitado, certifique-se de que haja uma exceção para "vpnkit" em redes privadas.

Para o meu caso específico, descobri que o Firewall do Windows estava bloqueando minha conexão quando tentei visitar a porta publicada do meu contêiner de outra máquina na minha rede local, porque desabilitá-lo fazia tudo funcionar.

No entanto, eu não queria desabilitar o firewall totalmente apenas para acessar o serviço do meu contêiner. Isso levantou a questão de qual "app" estava ouvindo em nome do serviço do meu contêiner. Depois de encontrar outro segmento de SO que me ensinou a usar netstat -a -bpara descobrir os aplicativos por trás dos soquetes de escuta em minha máquina, descobri que era vpnkit.exe, que já tinha uma entrada nas configurações do Firewall do Windows: mas "redes privadas" foram desabilitadas nele, e assim que o habilitei, consegui visitar o serviço do meu contêiner de outra máquina sem ter que desabilitar completamente o firewall.

Atul Varma
fonte
Senhor, você me salvou de horas e horas de frustração. Obrigado.
Behdad
2

Este é o problema mais comum enfrentado por usuários do Windows para executar Docker Containers. IMO, esta é a "pergunta de um milhão de dólares no Docker"; @ "Rocco Smit" apontou corretamente "o tráfego de entrada foi desabilitado por padrão no firewall da minha máquina host"; no meu caso, meu software antivírus McAfee. Acrescentei portas adicionais para permitir o tráfego de entrada de outros computadores na mesma LAN Wifi nas configurações de firewall da McAfee; então foi mágico. Eu tinha lutado por mais de uma semana navegando em toda a internet, SO, documentações do Docker, Tutoriais após tutoriais relacionados à rede do Docker e as muitas ilustrações de "não suportado no Windows" para "macvlan", "ipvlan", "usuário ponte definida "e até mesmo este mesmo segmento SO algumas vezes. Até comecei a navegar no google com "alguém usando Docker em produção?", (Sim, eu sei que o Linux é mais popular para cargas de trabalho Prod em comparação com servidores Windows), pois não consegui acessar (do meu celular no mesmo wi-fi doméstico) um nginx aplicativo implantado no Docker Container no Windows. Afinal, que bom é se você não pode acessar o aplicativo (implantado em um Docker Container) de outros computadores / dispositivos na mesma LAN, pelo menos; Em última análise, no meu caso, o problema era apenas com um firewall bloqueando o tráfego de entrada; se você não puder acessar o aplicativo (implantado em um Docker Container) de outros computadores / dispositivos na mesma LAN, pelo menos; Em última análise, no meu caso, o problema era apenas com um firewall bloqueando o tráfego de entrada; se você não puder acessar o aplicativo (implantado em um Docker Container) de outros computadores / dispositivos na mesma LAN, pelo menos; Em última análise, no meu caso, o problema era apenas com um firewall bloqueando o tráfego de entrada;

Banarasi
fonte
0

Descobri que, junto com a configuração dos valores da porta -p, o Docker para Windows usa vpnkit e o tráfego de entrada para ele foi desabilitado por padrão no firewall da minha máquina host. Depois de habilitar as regras TCP de entrada para vpnkit, consegui acessar meus contêineres de outras máquinas na rede local.

Rocco Smit
fonte