Atualização II
Agora é 16 de julho de 2015 e as coisas mudaram novamente. Eu descobri este contêiner automagical de Jason Wilder :
https://github.com/jwilder/nginx-proxy
e ele resolve esse problema no tempo que leva paradocker run
o contêiner. Esta é agora a solução que estou usando para resolver este problema.
Atualizar
Agora é julho de 2015 e as coisas mudaram drasticamente com relação aos contêineres Docker de rede. Existem agora muitas ofertas diferentes que resolvem esse problema (de várias maneiras).
Você deve usar esta postagem para obter uma compreensão básica da
docker --link
abordagem da descoberta de serviço, que é o mais básico possível, funciona muito bem e, na verdade, requer menos danças fantasiosas do que a maioria das outras soluções. Ele é limitado porque é bastante difícil conectar containers em hosts separados em qualquer cluster, e os containers não podem ser reiniciados depois de conectados em rede, mas oferece uma maneira rápida e relativamente fácil de conectar containers no mesmo host. É uma boa maneira de ter uma ideia do que o software que você provavelmente usará para resolver esse problema está realmente fazendo nos bastidores.Além disso, você provavelmente vai querer verificar também o nascente do Docker
network
, o Hashicorpconsul
, o Weaveworksweave
, o Jeff Lindsay'sprogrium/consul
&gliderlabs/registrator
e o GoogleKubernetes
.Há também os CoreOS ofertas que utilizam
etcd
,fleet
eflannel
.E se você realmente deseja dar uma festa, pode montar um cluster para executar
Mesosphere
, ouDeis
, ouFlynn
.Se você é novo em networking (como eu), deve pegar seus óculos de leitura, colocar "Paint The Sky With Stars - O Melhor da Enya" no Wi-Hi-Fi e abrir uma cerveja - vai ser um pouco antes de você realmente entender exatamente o que está tentando fazer. Dica: você está tentando implementar um
Service Discovery Layer
em seuCluster Control Plane
. É uma maneira muito legal de passar uma noite de sábado.É muito divertido, mas gostaria de ter dedicado tempo para me educar melhor sobre redes em geral antes de mergulhar de cabeça. Acabei encontrando alguns posts dos deuses do Tutorial do Oceano Digital:
Introduction to Networking Terminology
eUnderstanding ... Networking
. Eu sugiro que você os leia algumas vezes antes de mergulhar.Diverta-se!
Postagem Original
Não consigo entender o mapeamento de portas para Docker
contêineres. Especificamente como passar solicitações do Nginx para outro contêiner, ouvindo em outra porta, no mesmo servidor.
Eu tenho um Dockerfile para um contêiner Nginx assim:
FROM ubuntu:14.04
MAINTAINER Me <[email protected]>
RUN apt-get update && apt-get install -y htop git nginx
ADD sites-enabled/api.myapp.com /etc/nginx/sites-enabled/api.myapp.com
ADD sites-enabled/app.myapp.com /etc/nginx/sites-enabled/app.myapp.com
ADD nginx.conf /etc/nginx/nginx.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80 443
CMD ["service", "nginx", "start"]
E então o api.myapp.com
arquivo de configuração fica assim:
upstream api_upstream{
server 0.0.0.0:3333;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.mypp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_pass http://api_upstream;
}
}
E depois outro app.myapp.com
também.
E então eu corro:
sudo docker run -p 80:80 -p 443:443 -d --name Nginx myusername/nginx
E está tudo bem, mas as solicitações não estão sendo repassadas para os outros contêineres / portos. E quando eu ssh no contêiner Nginx e inspeciono os logs, não vejo erros.
Qualquer ajuda?
Respostas:
A resposta de @T0xicCode está correta, mas pensei em expandir os detalhes, já que na verdade levei cerca de 20 horas para finalmente implementar uma solução funcional.
Se você deseja executar o Nginx em seu próprio contêiner e usá-lo como um proxy reverso para balancear a carga de vários aplicativos na mesma instância do servidor, as etapas que você precisa seguir são as seguintes:
Vincule seus contêineres
Ao usar
docker run
seus contêineres, normalmente inserindo um script de shell noUser Data
, você pode declarar links para qualquer outro contêiner em execução . Isso significa que você precisa iniciar seus contêineres em ordem e apenas os últimos contêineres podem se vincular aos anteriores. Igual a:Portanto, neste exemplo, o
API
contêiner não está vinculado a nenhum outro, mas oApp
contêiner está vinculado aAPI
eNginx
está vinculado aAPI
eApp
.O resultado disso são as alterações nos
env
vars e nos/etc/hosts
arquivos que residem nos containersAPI
eApp
. Os resultados são assim:/ etc / hosts
Executar
cat /etc/hosts
dentro de seuNginx
contêiner produzirá o seguinte:ENV Vars
Executar
env
dentro de seuNginx
contêiner produzirá o seguinte:Trunquei muitos dos vars reais, mas os valores acima são os valores-chave de que você precisa para fazer proxy do tráfego para seus contêineres.
Para obter um shell para executar os comandos acima em um contêiner em execução, use o seguinte:
sudo docker exec -i -t Nginx bash
Você pode ver que agora você tem
/etc/hosts
entradas de arquivo eenv
vars que contêm o endereço IP local para qualquer um dos contêineres vinculados. Até onde posso dizer, isso é tudo o que acontece quando você executa contêineres com opções de link declaradas. Mas agora você pode usar essas informações para configurarnginx
em seuNginx
contêiner.Configurando o Nginx
É aqui que fica um pouco complicado e há algumas opções. Você pode escolher configurar seus sites para apontar para uma entrada no
/etc/hosts
arquivo quedocker
criou, ou você pode utilizar oENV
vars e executar uma substituição de string (eu useised
) em seunginx.conf
e em qualquer outro arquivo conf que possa estar em sua/etc/nginx/sites-enabled
pasta para inserir o IP valores.OPÇÃO A: Configurar Nginx usando ENV Vars
A principal diferença entre esta opção e usar a
/etc/hosts
opção de arquivo é como você escreve seuDockerfile
para usar um script de shell como oCMD
argumento, que por sua vez lida com a substituição da string para copiar os valores IP deENV
para seu (s) arquivo (s) conf.Este é o conjunto de arquivos de configuração que terminei:
Dockerfile
nginx.conf
api.myapp.conf
Nginx-Startup.sh
Vou deixar você fazer sua lição de casa sobre a maior parte do conteúdo de
nginx.conf
eapi.myapp.conf
.A mágica acontece
Nginx-Startup.sh
quando usamossed
para fazer a substituição da string noAPP_IP
placeholder que escrevemos noupstream
bloco de nossos arquivosapi.myapp.conf
eapp.myapp.conf
.Esta pergunta ask.ubuntu.com explica muito bem: Encontre e substitua texto dentro de um arquivo usando comandos
Portanto, docker lançou nosso contêiner e acionou a
Nginx-Startup.sh
execução do script, que costumavased
alterar o valorAPP_IP
para aENV
variável correspondente que fornecemos nosed
comando. Agora temos arquivos conf em nosso/etc/nginx/sites-enabled
diretório com os endereços IP dosENV
vars que o docker definiu ao iniciar o contêiner. Em seuapi.myapp.conf
arquivo, você verá que oupstream
bloco mudou para este:O endereço IP que você vê pode ser diferente, mas percebi que geralmente é
172.0.0.x
.Agora você deve ter todo o roteamento adequado.
OPÇÃO B: usar
/etc/hosts
entradas de arquivoEsta deveria ser a maneira mais rápida e fácil de fazer isso, mas não consegui fazer funcionar. Aparentemente, você acabou de inserir o valor da
/etc/hosts
entrada em seus arquivosapi.myapp.conf
eapp.myapp.conf
, mas não consegui fazer esse método funcionar.Aqui está a tentativa que fiz em
api.myapp.conf
:Considerando que há uma entrada em meu
/etc/hosts
arquivo assim:172.0.0.2 API
Achei que apenas puxaria o valor, mas não parece ser.Eu também tive alguns problemas auxiliares com meu
Elastic Load Balancer
sourcing de todos os AZ, então esse pode ter sido o problema quando tentei essa rota. Em vez disso, tive que aprender como lidar com a substituição de strings no Linux, o que foi divertido. Vou tentar isso daqui a pouco e ver no que dá.fonte
Tentei usar o proxy reverso popular Jason Wilder, que funciona como um passe de mágica para todos e aprendi que não funciona para todos (ou seja, eu). E sou totalmente novo no NGINX e não gostei de não entender as tecnologias que estava tentando usar.
Queria adicionar meus 2 centavos, porque a discussão acima sobre
linking
contêineres juntos agora está desatualizada, pois é um recurso obsoleto. Então aqui está uma explicação de como fazer isso usandonetworks
. Esta resposta é um exemplo completo de configuração do nginx como proxy reverso para um site paginado estaticamente usando umaDocker Compose
configuração do nginx.TL; DR;
Adicione os serviços que precisam se comunicar entre si em uma rede predefinida. Para uma discussão passo a passo sobre redes Docker, aprendi algumas coisas aqui: https://technologyconversations.com/2016/04/25/docker-networking-and-dns-the-good-the-bad-and- o feio/
Defina a rede
Em primeiro lugar, precisamos de uma rede na qual todos os seus serviços de back-end possam se comunicar. Liguei para o meu,
web
mas pode ser o que você quiser.Crie o aplicativo
Faremos apenas um aplicativo de site simples. O site é uma página index.html simples servida por um contêiner nginx. O conteúdo é um volume montado para o host em uma pasta
content
DockerFile:
default.conf
docker-compose.yml
Observe que não precisamos mais de mapeamento de porta aqui. Simplesmente expomos a porta 80. Isso é útil para evitar colisões de portas.
Execute o aplicativo
Abra este site com
Algumas verificações divertidas sobre os mapeamentos de dns para seu contêiner:
Este ping deve funcionar, dentro do seu container.
Crie o proxy
Proxy reverso Nginx:
Dockerfile
Reinicializamos toda a configuração do host virtual, já que iremos customizá-la.
docker-compose.yml
Execute o proxy
Abra o proxy usando nosso confiável
Presumindo que não haja problemas, você terá dois contêineres em execução que podem se comunicar usando seus nomes. Vamos testar.
Configurar Host Virtual
O último detalhe é configurar o arquivo de hospedagem virtual para que o proxy possa direcionar o tráfego com base em como você deseja configurar sua correspondência:
sample-site.conf para nossa configuração de hospedagem virtual:
Com base em como o proxy foi configurado, você precisará desse arquivo armazenado em sua
conf.d
pasta local, que montamos por meio davolumes
declaração nodocker-compose
arquivo.Por último, mas não menos importante, diga ao nginx para recarregar sua configuração.
Essa sequência de etapas é o culminar de horas de fortes dores de cabeça enquanto eu lutava com o sempre doloroso erro 502 Bad Gateway e aprendia nginx pela primeira vez, já que a maior parte da minha experiência foi com o Apache.
Esta resposta é para demonstrar como eliminar o erro 502 Bad Gateway que resulta da impossibilidade de comunicação entre os contêineres.
Espero que essa resposta poupe horas de dor para alguém, já que fazer os containers falarem entre si era realmente difícil de descobrir por algum motivo, apesar de ser o que eu esperava ser um caso de uso óbvio. Mas, novamente, meu idiota. E, por favor, deixe-me saber como posso melhorar essa abordagem.
fonte
502 Gateway Error
, um clássico infame nos dias de hoje. Obrigado @gdbj por gastar tempo para avançar a conversa e fornecer uma solução tão detalhada.Usando links do docker , você pode vincular o contêiner upstream ao contêiner nginx. Um recurso adicionado é que o docker gerencia o arquivo host, o que significa que você poderá se referir ao contêiner vinculado usando um nome em vez do ip potencialmente aleatório.
fonte
"Opção B" de AJB pode ser feita para funcionar usando a imagem base do Ubuntu e configurando o nginx por conta própria. (Não funcionou quando usei a imagem Nginx do Docker Hub.)
Aqui está o arquivo Docker que usei:
Minha configuração nginx (também conhecida como: conf / mysite.com):
E, finalmente, como inicio meus contêineres:
Isso me colocou em funcionamento, então meu nginx apontou o rio acima para o segundo contêiner docker que expôs a porta 3000.
fonte
upstream website {
define o valor do site para nginx. Isso é o que você usa no seuproxy_pass
. A parte docker disso usa apenas o mesmo nome para consistência, mas não tem nada a ver com a configuração do nginx. Para deixar um pouco mais claro, a senha do proxy deve ser:upstream website { server localhost:3000; }
A resposta de @gdbj é uma ótima explicação e a resposta mais atualizada. No entanto, aqui está uma abordagem mais simples.
Portanto, se você deseja redirecionar todo o tráfego do nginx que escuta para
80
a exposição de outro contêiner8080
, a configuração mínima pode ser tão pequena quanto:nginx.conf:
docker-compose.yml
Docs Docker
fonte
Acabei de encontrar um artigo de Anand Mani Sankar que mostra uma maneira simples de usar o proxy upstream nginx com o docker composer.
Basicamente, deve-se configurar a vinculação da instância e as portas no arquivo docker-compose e atualizar o upstream em nginx.conf de acordo.
fonte
links
que estão obsoletos. Use redes agora: docs.docker.com/engine/userguide/networking