Sua idéia de resolver o docker.for.mac.localhost é muito bem-alvo, você só precisa encontrar algo capaz de resolvê-lo em praticamente qualquer contêiner. Isso deve ser feito (e tem, de acordo com meus testes):
grep dockerhost /etc/hosts || echo $( (ping -c1 docker.for.mac.localhost || (ip r | grep ^default)) | grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts
Você pode colocar isso como parte de seu entrypoint ( sh -c
) ou em algum script de init.
Para mais informações, uma versão comentada mais completa e as advertências, continue a ler.
Tudo o que estamos fazendo é fazer com que o Linux resolva o nome. O ping é a escolha mais fácil, embora o nc e o traceroute existam em praticamente todos os lugares. Se tudo mais falhar, você pode realmente fazer isso com um moderno (mas não BusyBox) bash ou syslog. Por padrão, o Docker configura um pequeno servidor DNS que responde aos nomes de quaisquer outros contêineres na mesma rede (ou, em versões mais antigas, contêineres vinculados). E então docker.for.mac.localhost
é adicionado a isso.
Se nada resolver, então o servidor dns não resolveu, e nós recebemos o host normalmente. Você pode querer usar o método / proc / net, mas eles parecem ser equivalentes em meus contêineres de teste.
Agora, algumas ressalvas. Primeiro, um grande problema: se você não tiver conexão de rede, isso levará uma eternidade para o tempo limite - até 30 segundos. Existem algumas correções no script maior abaixo. Você também não pode (bem, por padrão - existem maneiras de sobrescrever isso) executar isso durante a compilação do contêiner. Em vez disso, você pode, simplesmente não fará nada: o Docker monta um novo / etc / hosts quando você inicia o container.
Uma versão melhor usaria timeout
, mas você se depara com um problema - há (pelo menos) duas versões incompatíveis e um terceiro caso, se você quiser supor que pode não estar lá:
grep dockerhost /etc/hosts || echo $( (
(if timeout -t1 env >/dev/null; then \
timeout -t1 ping -c1 docker.for.mac.localhost; \
elif timeout 1s env >/dev/null; then
timeout 1s ping -c1 docker.for.mac.localhost; \
else \
ping -c1 docker.for.mac.localhost; \
fi) \
|| (ip r | grep ^default)) \
| grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts
Usamos env porque quase certamente existe uma versão que não é integrada ao shell ( /usr/bin/env
na maioria dos casos), tem uma interface bem conhecida (ou seja, será executada sem nenhuma entrada) e é improvável que ele falhe por motivos ambientais, ao contrário de comandos irritantes como ls
, que dependem de um sistema de arquivos.
E, finalmente, uma versão completa comentada semelhante ao que estou usando (para que as pessoas que vêm atrás de mim entendam o que está acontecendo):
add_dockerhost_address() {
# The name we're checking for - in case this technique is useful on Windows
# if we get a Windows version instead of a cross-platform one
local MACHOST="docker.for.mac.localhost"
# The name we want to insert into /etc/hosts
local DOCKERHOSTNAME="dockerhost"
# Don't insert the name twice
if grep "$DOCKERHOSTNAME" /etc/hosts >/dev/null 2>&1; then
return 0
fi
# A command string we'll be building
local COMMAND=""
# Check for the ability to limit the timeout
if command -v timeout >/dev/null 2>&1; then
# We still have a problem - there are two widely used incompatible
# variants of timeout. Let's see which one we have.
# env should not be a builtin, doesn't require a pipe,
# has a consistent command line test, and is unlikely to fail
if timeout -t1 env >/dev/null 2>&1; then
COMMAND="timeout -t1 "
else
COMMAND="timeout 1s "
fi
fi
local IS_NOT_MAC=1
local IP=""
if command -v ping >/dev/null 2>&1; then
COMMAND="$COMMAND ping -c1 $MACHOST"
# Otherwise, BusyBox shows terminated.
IP=$(sh -c "$COMMAND" 2>&1)
# Exit codes: 0 - found the host, 1/2 failed to find, 124/143 terminated
IS_NOT_MAC="$?"
fi
if [ "$IS_NOT_MAC" -eq 0 ]; then
IP=$(echo "$IP" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
else
IP=$(ip r | grep ^default | cut -d" " -f3)
fi
echo "$IP $DOCKERHOSTNAME" >> /etc/hosts
}
add_dockerhost_address
exec "/usr/sbin/apachectl" "-DFOREGROUND"