Acesse seus serviços Docker Compose por meio de nomes fáceis de lembrar


“Pilha, pilha, matriz!”

Você sabia que pode disponibilizar contêineres de aplicativos da web Docker por meio de nomes simples, em vez de números de porta difíceis de lembrar?

Ursos venceram Battlestar Galactica

Um urso marrom inferior ataca um Cylon

Ursos venceram Battlestar Galactica

O Docker Compose torna possível ativar todo um ambiente de desenvolvimento em sua máquina local com apenas um único comando, mesmo que esse ambiente consista em uma dúzia de front-ends, back-ends e serviços de apoio diferentes.

Como desenvolvedor, não basta que o sistema funcione – você também precisa de alguma forma de interagir com ele. A maneira mais fácil de fazer isso é expondo as portas do contêiner, para que você possa, por exemplo, acessar sua aplicação web em http://localhost:8080 ou sua instância do Elasticsearch em http://localhost:9200.

Aqui está um anúncio de serviço público: não precisa ser assim. Você pode (pedir à IA) usar nomes de domínio que realmente façam sentido, mesmo para o desenvolvimento local.

O problema

Primeiro, deixe-me ilustrar qual problema estamos tentando resolver aqui. Para simplificar, usarei hashicorp/http-echo em vez de um aplicativo da web real. http-echo é um pequeno servidor web que pode ser configurado para retornar uma string estática.

No compose.yaml abaixo, eu configurei http-echo para retornar a string Bears e porta encaminhada 5678 do host, já que é isso que http-echo escuta por padrão:

image: hashicorp/http-echo

command: ("-text", "Bears")

Enquanto este projeto do Compose está em execução, abrindo http://localhost:5678 no seu navegador deve mostrar uma página da web simples contendo o texto Bears.

Um projeto típico de desenvolvimento web terá mais do que apenas um contêiner em execução. Além de um frontend, você pode ter uma API ou algo como o Storybook.

Vamos adicionar um segundo http-echo instância para nosso projeto Compose. Desta vez, faremos com que retorne a string Beets. Porque porto 5678 já está tomado pelo bears container, escolheremos “aleatoriamente” outro número de porta. Neste caso, fui para 5679.

image: hashicorp/http-echo

command: ("-text", "Bears")

image: hashicorp/http-echo

command: ("-text", "Beets")

Agora, temos dois servidores web rodando nas portas 5678 e 5679retornando respectivamente as strings Bears e Beets.

Esta configuração obviamente funciona bem o suficiente para pequenos projetosmas sofre de vários problemas:

  1. Isto força você a usar números de porta, mas a maioria das pessoas não é boa em lembrar sequências numéricas, especialmente se elas forem mais longas (por exemplo 15672, 27017, 61616) ou parecidos entre si (80, 8080, 8081, 8888etc.).
  2. Todos os aplicativos da web são servidos diretamente em localhost. Não há nada no endereço da web que diga a você (ou ao navegador) algo sobre o que está sendo servido. Na verdade, a mesma porta pode ser reutilizada em projetos, potencialmente causando problemas difíceis de depurar com cookies, entre outras coisas.

Seria bom se esses aplicativos da web pudessem ser disponibilizados por meio de endereços mais fáceis de lembrar e que realmente tivessem alguma relação com os aplicativos aos quais se referem.

Uma solução básica

Este é um problema bastante comum e, conseqüentemente, existem várias maneiras comuns de resolvê-lo.

A maioria envolve algum tipo de proxy reverso, onde os aplicativos da web não são mais expostos diretamente, mas apenas por meio de um servidor de “ponto de entrada” que encaminha solicitações para o aplicativo da web correto, geralmente com base no (sub)domínio e/ou no caminho da solicitação.

O compose.yaml abaixo usa nginxproxy/nginx-proxy como proxy reverso. Este contêiner lida com todas as solicitações de porta 80 (a porta HTTP padrão), que inclui não apenas localhostmas o mais importante também é tudo o que está abaixo dele, como example.localhost e longer.example.localhost.

Para fazer o proxy encaminhar solicitações para o contêiner certo, basta adicionar um VIRTUAL_HOST variável contendo o nome de domínio desejado para seu environment.

image: nginxproxy/nginx-proxy

- /var/run/docker.sock:/tmp/docker.sock:ro

image: hashicorp/http-echo

command: ("-text", "Bears")

VIRTUAL_HOST: bears.localhost

image: hashicorp/http-echo

command: ("-text", "Beets")

VIRTUAL_HOST: beets.localhost

Agora você pode simplesmente ir para http://bears.localhost e http://beets.localhost para ver os textos Bears e Beets respectivamente. Chega de números de porta!

Bom saber

É certo que o exemplo acima é um pouco artificial e seus requisitos podem ser diferentes dos meus. Aqui estão algumas coisas que você pode precisar.

Roteamento baseado em caminho

Com nginxproxy/nginx-proxyvários contêineres podem compartilhar o mesmo nome de host, desde que escutem caminhos diferentes, que você pode definir usando o comando VIRTUAL_PATH variável de ambiente:

image: nginxproxy/nginx-proxy

- /var/run/docker.sock:/tmp/docker.sock:ro

image: hashicorp/http-echo

command: ("-text", "What kind of bear is best?")

VIRTUAL_HOST: bears.localhost

image: hashicorp/http-echo

command: ("-text", "Black bears are the best.")

VIRTUAL_HOST: bears.localhost

Grandes solicitações HTTP

Fora da caixa, nginxproxy/nginx-proxy permite apenas solicitações HTTP de até 1 MB. Se precisar oferecer suporte a uploads de arquivos ou outros tipos de cargas de solicitação grandes, você precisará substituir manualmente o nginx client_max_body_size.

A maneira idiomática de fazer isso é criando um arquivo de configuração personalizado que define o client_max_body_size para o valor desejado (ou desativa totalmente o limite) e montando-o no contêiner:

image: nginxproxy/nginx-proxy

- ./path/to/your/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro

- /var/run/docker.sock:/tmp/docker.sock:ro

Alternativamente, você pode simplesmente substituir o ponto de entrada para que o arquivo de configuração seja criado dinamicamente durante a inicialização:

image: nginxproxy/nginx-proxy

echo 'client_max_body_size 0;' > /etc/nginx/conf.d/proxy.conf

&& exec /app/docker-entrypoint.sh forego start -r

- /var/run/docker.sock:/tmp/docker.sock:ro

Domínios não locaishost

Todos os exemplos até agora usaram *.localhost endereços. Você pode ficar tentado a usar algum outro domínio, mas localhost tem alguns benefícios importantes em relação a muitas alternativas comuns:

  • .localhost é um nome de domínio de uso especial com uma finalidade específica. Nunca será causar conflitos com domínios reais, agora ou no futuro.

  • .localhost é automaticamente resolvido para 127.0.0.1para que você não precise editar manualmente seu /etc/hosts arquivo.
  • Navegadores modernos tratam .localhost diferentemente de outros domínios. Você terá menos problemas com cookies, WebSockets e certificados.

Eu recomendaria que você “namespace” seus hosts virtuais para evitar conflitos com outros projetos. Por exemplo, se você trabalha para uma empresa chamada Contosouse hosts virtuais como foo.contoso.localhost e api.foo.contoso.localhost.

Rede interna

É importante ter em mente que o proxy reverso existe para tornar os contêineres mais facilmente acessíveis a partir do hospedar.

Os contêineres dentro de um projeto Docker Compose não podem alcançar outros contêineres por meio do proxy reverso, apenas por meio do nome de serviço interno (por exemplo, http://bears).

Porque localhost por definição resolve para a máquina local, você não pode nem mesmo fazer com que seus contêineres se conectem ao proxy modificando seu /etc/hosts arquivo, já que a maioria dos clientes HTTP não se preocupará em verificá-lo.

Se você realmente quer usar .localhost endereços dentro do seu contêiner também, você pode executar um proxy reverso dentro de o contêiner que encaminha todas as solicitações de *.localhost para http://proxyque encaminhará a solicitação para o contêiner correto:

&& echo 'http://*.localhost' >> proxy.Caddyfile

&& echo 'reverse_proxy http://proxy' >> proxy.Caddyfile

CMD ("bash", "-c", "caddy run --config proxy.Caddyfile & exec npm run dev")

Vários projetos

Provavelmente, você tem mais de um projeto Docker Compose que deseja executar simultaneamente. Vamos supor que você tenha dois projetos, bears e bsgcada um com seu compose.yaml:

Ainda precisamos de um proxy reverso que escute na porta 80 e encaminhe solicitações para os contêineres certos, mas agora os contêineres fazem parte de dois projetos diferentes que normalmente estariam completamente isolados um do outro. Além disso, ainda queremos que cada projeto do Compose possa funcionar de forma independente.

A solução mais limpa é mover o proxy reverso para seu próprio projeto do Compose. Este projecto não deverá apenas declarar a proxy serviço, mas também o proxy rede:

image: nginxproxy/nginx-proxy

- /var/run/docker.sock:/tmp/docker.sock:ro

O compose.yaml arquivos para bears e bsg pode ser bastante mínimo:

image: hashicorp/http-echo

command: ("-text", "Bears")

image: hashicorp/http-echo

command: ("-text", "Battlestar Galactica")

Você pode notar dois problemas principais aqui:

  1. Todos os três projetos agora declaram um mapeamento portuário 80:5678. Isso nos permite iniciar cada um desses projetos de forma independente e torná-los acessíveis em http://localhost sem número de porta, mas não ao mesmo tempo.
  2. Não dizemos mais ao Docker como conectar esses projetos, então nosso código legível por humanos .localhost endereços não funcionam mais.

Podemos corrigir ambas as regressões adicionando um compose.proxy.yaml arquivo que adiciona configuração específica de proxy ao bears e bsg projetos. A estrutura de diretórios resultante poderia ser assim:

O compose.proxy.yaml arquivos para bsg e bears faça quatro coisas:

  1. Declare uma dependência em uma rede Docker externa chamada proxy. Se você tentar iniciar qualquer um desses projetos antes do proxy projeto, eles se recusarão a começar.
  2. Defina o VIRTUAL_HOST. Poderíamos ter deixado isso no original compose.yaml arquivos, mas isso é um pouco mais limpo.
  3. O bears e bsg os serviços devem estar vinculados ao proxy rede. Isso permite que o proxy reverso os encontre.
  4. Desative os mapeamentos de portas definidos no original compose.yaml arquivos, já que eles não são mais necessários (e teriam causado um conflito de porta de qualquer maneira).

VIRTUAL_HOST: bears.localhost

VIRTUAL_HOST: bsg.localhost

Configurar tudo agora requer duas etapas.

Primeiro, inicie o proxy projeto. Caso contrário, as etapas abaixo falharão com a seguinte mensagem de erro: network proxy declared as external, but could not be found.

Em seguida, inicie todos os projetos restantes com o -f (--file) que informa explicitamente ao Docker Compose quais configurações ele deve usar:

docker compose -f compose.yaml -f compose.proxy.yaml up -d

Agora, você deve ser capaz de acessar ambos http://bears.localhost e http://bsg.localhost através do seu navegador!

Tempere a gosto

Dependendo do seu caso de uso, você pode querer fazer algumas modificações nesta configuração:

  • Se você nunca precisar executar esses projetos (localmente ou em CI) sem o proxy, sinta-se à vontade para simplificar a configuração mesclando nosso software personalizado compose.proxy.yaml para o normal compose.yaml.
  • Se você não quiser cometer o compose.proxy.yaml arquivos, você deve adicioná-los a um .gitignore arquivo.
  • Alternativamente, se você renomeá-lo para compose.override.yamla configuração será aplicada automaticamente sobre o normal compose.yaml arquivo, então você não precisa usar -f mais ao iniciar projetos.

Este artigo aparece em



Source link

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Botão Voltar ao Topo