Como o título diz. Preciso recuperar o endereço IP que o docker hospeda e os mapas de porta do host para o contêiner, e fazer isso dentro do contêiner.
Como o título diz. Preciso recuperar o endereço IP que o docker hospeda e os mapas de porta do host para o contêiner, e fazer isso dentro do contêiner.
Respostas:
/sbin/ip route|awk '/default/ { print $3 }'
Como @MichaelNeale notou, não faz sentido usar esse método Dockerfile
(exceto quando precisamos desse IP apenas durante o tempo de compilação), porque esse IP será codificado durante o tempo de compilação.
A partir da versão 18.03, você pode usar host.docker.internal
como o IP do host.
Funciona no Docker para Mac , no Docker para Windows e talvez em outras plataformas também.
Esta é uma atualização específica do Mac docker.for.mac.localhost
, disponível desde a versão 17.06 e docker.for.mac.host.internal
disponível desde a versão 17.12, que também pode ainda funcionar nessa plataforma.
Observe que, como na documentação do Mac e Windows , isso é apenas para fins de desenvolvimento.
Por exemplo, tenho variáveis de ambiente definidas no meu host:
MONGO_SERVER=host.docker.internal
No meu docker-compose.yml
arquivo, eu tenho o seguinte:
version: '3'
services:
api:
build: ./api
volumes:
- ./api:/usr/src/app:ro
ports:
- "8000"
environment:
- MONGO_SERVER
command: /usr/local/bin/gunicorn -c /usr/src/app/gunicorn_config.py -w 1 -b :8000 wsgi
docker.for.mac..
é inútil, pois na maioria dos casos você não possui um ambiente somente Linux ou Mac em sua empresa. É misto, você tem desenvolvedores usando Linux, Mac e Windows. Esse domínio não faz sentido, já que em 99% é um ambiente misto do sistema operacional host. Não desenvolvo um contêiner no macOS e o implanto em um servidor macOS. Eu o implanto no Linux. É isso que todo mundo faz. Então, qual é o objetivo docker.for.mac..
?
docker.for.mac.host.internal
não importa se você está usando o Docker com ou sem docker-compose
. Eu quero usar um host fixo nos arquivos de configuração. IDK, por exemplo, docker.host.internal
que sempre aponta para o endereço IP do host. Independentemente de qual sistema host eu estou usando. Esse é o objetivo de usar o Docker: quero ser autônomo. Entendo que é ainda mais complicado no macOS porque você tem outra camada entre o sistema host e o contêiner. Mas de qualquer maneira, na minha opinião, docker.for.mac.host.internal
é inútil se você puder usá-lo apenas para o macOS.
host.docker.internal
também funciona no Docker for Windows , pelo menos no momento da redação deste comentário.
Atualização: No Docker para Mac , a partir da versão 18.03, você pode usar host.docker.internal como o IP do host. Veja a resposta de allanberry . Para versões anteriores do Docker for Mac, a seguinte resposta ainda pode ser útil:
No Docker para Mac, a docker0
ponte não existe, portanto outras respostas aqui podem não funcionar. Todo o tráfego de saída, no entanto, é roteado através do host pai; portanto, enquanto você tenta se conectar a um IP, ele reconhece como ele próprio (e o contêiner do docker não pensa que é ele próprio), você deve conseguir se conectar. Por exemplo, se você executar isso na máquina pai, execute:
ipconfig getifaddr en0
Isso deve mostrar o IP do seu Mac na rede atual e o contêiner do docker também deve se conectar a esse endereço. Obviamente, isso é problemático se esse endereço IP mudar, mas você pode adicionar um IP de loopback personalizado ao seu Mac que o contêiner não pense ser ele mesmo, fazendo algo assim na máquina pai:
sudo ifconfig lo0 alias 192.168.46.49
Em seguida, você pode testar a conexão no contêiner do docker com telnet. No meu caso, eu queria conectar-me a um servidor xdebug remoto:
telnet 192.168.46.49 9000
Agora, quando o tráfego chegar ao seu Mac endereçado a 192.168.46.49 (e todo o tráfego que sai do contêiner passa pelo Mac), o seu Mac assume que o IP é ele próprio. Quando você terminar de usar esse IP, poderá remover o alias de loopback assim:
sudo ifconfig lo0 -alias 192.168.46.49
Uma coisa a ter cuidado é que o contêiner do docker não enviará tráfego para o host pai se achar que o destino do tráfego é ele próprio. Portanto, verifique a interface de loopback dentro do contêiner se tiver problemas:
sudo ip addr show lo
No meu caso, isso mostrou o inet 127.0.0.1/8
que significa que eu não poderia usar nenhum IP no 127.*
intervalo. Por isso eu usei 192.168.*
no exemplo acima. Verifique se o IP que você usa não entra em conflito com algo em sua própria rede.
Para aqueles que executam o Docker na AWS, os metadados da instância para o host ainda estão disponíveis no contêiner.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Por exemplo:
$ docker run alpine /bin/sh -c "apk update ; apk add curl ; curl -s http://169.254.169.254/latest/meta-data/local-ipv4 ; echo"
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
v3.3.1-119-gb247c0a [http://dl-cdn.alpinelinux.org/alpine/v3.3/main]
v3.3.1-59-g48b0368 [http://dl-cdn.alpinelinux.org/alpine/v3.3/community]
OK: 5855 distinct packages available
(1/4) Installing openssl (1.0.2g-r0)
(2/4) Installing ca-certificates (20160104-r2)
(3/4) Installing libssh2 (1.6.0-r1)
(4/4) Installing curl (7.47.0-r0)
Executing busybox-1.24.1-r7.trigger
Executing ca-certificates-20160104-r2.trigger
OK: 7 MiB in 15 packages
172.31.27.238
$ ifconfig eth0 | grep -oP 'inet addr:\K\S+'
172.31.27.238
ifconfig eth0 | grep -oP 'inet \K\S+'
A única maneira de passar as informações do host como ambiente quando você cria um contêiner
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(usando a resposta aceita de unix.stackexchange.com/questions/87468/... )
A --add-host
poderia ser uma solução mais líquido de limpeza (mas sem a parte da porta, apenas o hospedeiro pode ser tratado com esta solução). Então, no seu docker run
comando, faça algo como:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
A prática recomendada padrão para a maioria dos aplicativos que desejam fazer isso automaticamente é: você não precisa . Em vez disso, a pessoa que está executando o contêiner injeta um nome de host / endereço IP externo como configuração, por exemplo, como uma variável de ambiente ou arquivo de configuração. Permitir que o usuário injete isso fornece o design mais portátil.
Por que isso seria tão difícil? Como os contêineres isolarão o aplicativo do ambiente host. A rede está no namespace apenas para esse contêiner por padrão, e os detalhes do host são protegidos do processo em execução no contêiner, que pode não ser totalmente confiável.
Existem opções diferentes, dependendo da sua situação específica:
Se o seu contêiner estiver sendo executado com a rede do host, você poderá olhar diretamente para a tabela de roteamento no host para ver a rota padrão. A partir desta pergunta, o seguinte funciona para mim, por exemplo:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Um exemplo mostrando isso com a rede do host em um contêiner é semelhante a:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Para algumas versões do Docker Desktop, eles injetaram uma entrada DNS na VM incorporada:
getent hosts host.docker.internal | awk '{print $1}'
Se você estiver executando em um ambiente de nuvem, poderá verificar o serviço de metadados do provedor de nuvem, por exemplo, o da AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Se você deseja seu endereço externo / Internet, pode consultar um serviço remoto como:
curl ifconfig.co
Cada um desses possui limitações e funciona apenas em cenários específicos. A opção mais portátil ainda é executar o contêiner com o endereço IP injetado como configuração, por exemplo, aqui está uma opção executando o ip
comando anterior no host e injetando-o como uma variável de ambiente:
export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP
curl ifconfig.co
Comando realmente útil .. Obrigado :)
Se você deseja um IP
endereço real (não uma ponte IP
) Windows
e possui uma janela de encaixe 18.03
(ou mais recente), faça o seguinte:
Execute o bash no contêiner do host em que o nome da imagem está nginx
(funciona Alpine Linux distribution
):
docker run -it nginx /bin/ash
Em seguida, execute dentro do contêiner
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
é o IP do host - não o IP da ponte, como na spinus
resposta aceita.
Estou usando aqui host.docker.internal :
O host tem um endereço IP alterado (ou nenhum, se você não tiver acesso à rede). A partir de 18.03, nossa recomendação é conectar-se ao nome DNS especial host.docker.internal, que resolve o endereço IP interno usado pelo host. Isso é para fins de desenvolvimento e não funcionará em um ambiente de produção fora do Docker for Windows.
Alpine Linux
? Caso contrário, verifique o equivalente para o seu específico linux distribution
.
linux containers
e não estou usando windows containers
. Você pode fazer isso clicando com o botão direito do mouse docker icon
e selecionando Switch to Linux containers
. Eu acho que isso pode ser importante quando você está baixando uma imagem. Se você tiver windows container
verificado se a exclusão da nginx
imagem antiga e o download novamente, você obterá outro contêiner. Se ainda assim não funcionar para você - você pode tentar instalar nslookup
no ash
.
host.docker.internal
) de dentro do recipiente
docker run -it --rm alpine nslookup host.docker.internal
... imprime o endereço IP do host ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
No Mac e Windows , você pode usar o nome DNS especial host.docker.internal
.
O host tem um endereço IP alterado (ou nenhum, se você não tiver acesso à rede). A partir de 18.03, nossa recomendação é conectar-se ao nome DNS especial host.docker.internal, que resolve o endereço IP interno usado pelo host. Isso é para fins de desenvolvimento e não funcionará em um ambiente de produção fora do Docker Desktop for Mac.
Docker para Mac Desejo conectar-me de um contêiner a um serviço no host
O host tem um endereço IP alterado (ou nenhum, se você não tiver acesso à rede). A partir de 18.03, nossa recomendação é conectar-se ao nome DNS especial host.docker.internal, que resolve o endereço IP interno usado pelo host.
O gateway também pode ser acessado como gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Se você ativou a API remota do docker (via, por exemplo) e sabe o nome do host ou o endereço IP da máquina host, isso pode ser feito com muito bash.-H
tcp://0.0.0.0:4243
Dentro do usuário do meu contêiner bashrc
:
export hostIP=$(ip r | awk '/default/{print $3}')
export containerID=$(awk -F/ '/docker/{print $NF;exit;}' /proc/self/cgroup)
export proxyPort=$(
curl -s http://$hostIP:4243/containers/$containerID/json |
node -pe 'JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).NetworkSettings.Ports["DESIRED_PORT/tcp"][0].HostPort'
)
A segunda linha pega o ID do contêiner do /proc/self/cgroup
arquivo local .
A terceira linha se desloca para a máquina host (supondo que você esteja usando 4243 como porta do docker) e depois usa o nó para analisar o JSON retornado para o DESIRED_PORT
.
HostPort
pode ser uma informação útil aqui, infelizmente o HostIp
poderia ser0.0.0.0
Eu tenho o Ubuntu 16.03. Para mim
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
se não trabalhar (ip errado estava gerando)
Minha solução de trabalho foi a seguinte:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Aqui está outra opção para aqueles que executam o Docker na AWS. Essa opção evita o uso de apk para adicionar o pacote curl e economiza os preciosos 7 MB de espaço. Use o wget interno (parte do binário monolítico do BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, no caso do Docker for Linux (distribuição padrão), o endereço IP do host sempre será 172.17.0.1
.
A maneira mais fácil de obtê-lo é via ifconfig
(interface docker0) do host:
ifconfig
De dentro de uma janela de encaixe, o seguinte comando de uma janela de encaixe: ip -4 route show default | cut -d" " -f3
Você pode executá-lo rapidamente em uma janela de encaixe com a seguinte linha de comando:
# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:19.10 bash -c "apt-get update && apt-get install iproute2 -y && ip -4 route show default | cut -d' ' -f3"
Espero que ajude.
No linux você pode executar
HOST_IP=`hostname -I | awk '{print $1}'`
No macOS, sua máquina host não é o host do Docker. O Docker instalará seu sistema operacional host no VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
adverte para não "fazer suposições sobre a ordem da saída".
Esta é uma implementação minimalista no Node.js para quem está executando o host nas instâncias do AWS EC2 , usando a instância de metadados do EC2 mencionada anteriormente .
const cp = require('child_process');
const ec2 = function (callback) {
const URL = 'http://169.254.169.254/latest/meta-data/local-ipv4';
// we make it silent and timeout to 1 sec
const args = [URL, '-s', '--max-time', '1'];
const opts = {};
cp.execFile('curl', args, opts, (error, stdout) => {
if (error) return callback(new Error('ec2 ip error'));
else return callback(null, stdout);
})
.on('error', (error) => callback(new Error('ec2 ip error')));
}//ec2
e usado como
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Se você estiver executando um contêiner do Windows em um cluster do Service Fabric, o endereço IP do host estará disponível por meio da variável de ambiente Fabric_NodeIPOrFQDN
. Variáveis de ambiente do Service Fabric
Aqui está como eu faço isso. Nesse caso, ele adiciona uma entrada de hosts em / etc / hosts na imagem do docker, apontando taurus-host para o IP da minha máquina local:
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Em seguida, no contêiner do Docker, o script pode usar o nome do host taurus-host para chegar à minha máquina local que hospeda o contêiner do Docker.
Talvez o contêiner que eu criei também seja útil https://github.com/qoomon/docker-host
Você pode simplesmente usar o nome do container dns para acessar o sistema host, por exemplo, enrolar http: // dockerhost: 9200 , para que não haja problemas com nenhum endereço IP.
A solução usada é baseada em um "servidor" que retorna o endereço externo do host do Docker quando recebe uma solicitação http.
No "servidor":
1) Inicie o jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Inicie o recipiente ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Agora, quando um contêiner envia uma solicitação http para o servidor, por exemplo,
# curl http://<external server name/address>:<external server port>
o endereço IP do host do Docker é retornado por ipify via cabeçalho http "X-Forwarded-For"
Exemplo (o servidor ipify tem o nome "ipify.example.com" e é executado na porta 80, o host do docker tem IP 10.20.30.40):
# docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
# docker run -e VIRTUAL_HOST=ipify.example.com --detach --name ipify osixia/ipify-api:0.1.0
Agora, dentro do contêiner, você pode ligar para:
# curl http://ipify.example.com
10.20.30.40
Tente isto
docker run --rm -i --net = host alpino ifconfig
No Ubuntu, o hostname
comando pode ser usado com as seguintes opções:
-i
, --ip-address
endereços para o nome do host-I
, --all-ip-addresses
todos os endereços para o hostPor exemplo:
$ hostname -i
172.17.0.2
Para atribuir à variável, a seguinte linha única pode ser usada:
IP=$(hostname -i)
Com https://docs.docker.com/machine/install-machine/
a) $ docker-machine ip
b) Obtenha o endereço IP de um ou mais computadores.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2