Docker: Roteamento HTTPS
Como gerir o roteamento HTTP e a encriptação TLS (HTTPS) nos seus contentores Docker
👋 Bem-vindo à documentação da Stackhero!
A Stackhero oferece uma solução Docker cloud CaaS (Containers as a Service) pronta a usar que proporciona uma série de benefícios, incluindo:
- Implemente facilmente os seus containers em produção com apenas um
docker-compose up.- Nome de domínio personalizável seguro com HTTPS (por exemplo, https://api.sua-empresa.com, https://www.sua-empresa.com, https://backoffice.sua-empresa.com).
- Desempenho ótimo e segurança robusta alimentados por uma VM privada e dedicada.
- Atualizações sem esforço com apenas um clique.
Poupe tempo e simplifique a sua vida: são necessários apenas 5 minutos para experimentar a solução de hospedagem cloud Docker CaaS da Stackhero e implementar os seus containers em produção!
Cada instância do Stackhero para Docker inclui um servidor Traefik dedicado e pré-configurado que gere o tráfego HTTP e o encripta automaticamente usando certificados TLS. Esta configuração simplificada torna o roteamento simples e eficiente. Por exemplo:
- Enviar tráfego de
https://www.my-company.com(com ou sem o prefixo www) para o seu contentorfrontend. - Roteie
https://www.my-company.com/documentationspara o seu contentordocumentations. - Direcione
https://api.my-project.iopara o seu contentorapi.
Pode gerir um número ilimitado de domínios com criação e renovação automática de certificados TLS. O melhor de tudo é que pode configurar tudo isto com apenas três linhas!
Configuração base do Traefik
Em todos os exemplos de configuração seguintes, terá de substituir
<XXXXXX>.stackhero-network.compelo nome de domínio da sua instância Stackhero para Docker.
Abaixo está um exemplo básico de um ficheiro docker-compose.yml:
services:
test:
image: nginx
labels:
- "traefik.enable=true" # Ativar Traefik para rotear tráfego para este contentor
- "traefik.http.routers.test.rule=Host(`<XXXXXX>.stackhero-network.com`)" # Definir o host
- "traefik.http.routers.test.tls.certresolver=letsencrypt" # Usar 'letsencrypt' como o resolvedor de certificado TLS
Neste exemplo, um contentor chamado test funciona com a imagem Nginx. A configuração chave é fornecida na secção de labels. Apenas precisa de copiar estas linhas para o seu ficheiro docker-compose.yml e substituir <XXXXXX>.stackhero-network.com pelo seu domínio de serviço.
Pode implantar o contentor usando:
docker context use <XXXXXX>.stackhero-network.com
docker-compose up
Após o arranque do contentor, visite https://<XXXXXX>.stackhero-network.com/ para ver a página "Welcome to nginx!".
Página de boas-vindas do Nginx
Se não vir a página de boas-vindas do Nginx, verifique o painel de controlo do Traefik para possíveis erros!
Com esta configuração, os pedidos HTTP enviados para <XXXXXX>.stackhero-network.com são roteados para o seu contentor test e o Traefik cria e gere automaticamente os certificados TLS para HTTPS.
Gerir domínios personalizados com Traefik
No exemplo anterior, utilizámos o domínio padrão <XXXXXX>.stackhero-network.com. Na prática, provavelmente usará os seus próprios domínios de empresa ou projeto, como www.my-company.com ou api.my-project.io. A secção abaixo explica como configurar domínios personalizados.
Configurar o seu primeiro domínio com Traefik
Neste exemplo, irá configurar o domínio api.my-project.io. Substitua my-project.io por um domínio que possua e api pelo subdomínio desejado.
Primeiro, atualize as definições DNS do seu domínio para que api.my-project.io aponte para o seu domínio <XXXXXX>.stackhero-network.com.
- Inicie sessão no seu fornecedor de domínio e aceda à sua configuração DNS.
- Crie uma nova entrada chamada
api(ou outro subdomínio à sua escolha), defina o seu tipo comoCNAMEe defina o seu destino como<XXXXXX>.stackhero-network.com.
Exemplo de configuração DNS na interface DNS do Cloudflare
Uma vez configurado o DNS, pode validá-lo executando:
host api.my-project.io
Deverá ver uma resposta semelhante a:
api.my-project.io is an alias for <XXXXXX>.stackhero-network.com
A propagação DNS pode demorar até 24 horas, dependendo do seu fornecedor. Se o comando
hostnão devolver a resposta esperada, aguarde e tente novamente mais tarde.
Em seguida, atualize o seu ficheiro docker-compose.yml com a seguinte configuração:
services:
api:
image: traefik/whoami
hostname: api
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.my-project.io`)" # Adicione o seu domínio aqui
- "traefik.http.services.api.loadbalancer.server.port=<PORT>" # Substitua "<PORT>" pelo porto em que a sua API está a ouvir
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
Não se esqueça de substituir
api.my-project.iopelo seu domínio real no label TraefikHost.
Implante o seu contentor com:
docker-compose up -d
Depois visite https://api.my-project.io. Deverá ver uma página de texto exibindo o nome do host do seu contentor api.
Prova de que o Traefik está a gerir o nosso tráfego HTTP com encriptação TLS para o nosso novo domínio
Na primeira criação do contentor, os certificados TLS podem demorar alguns segundos a serem gerados. Se encontrar um erro TLS, aguarde alguns segundos e atualize a página para permitir tempo para os certificados serem gerados.
Parabéns, configurou agora o seu primeiro domínio personalizado!
Como redirecionar um subdomínio "www" para o seu domínio raiz usando Traefik
Ao definir um URL de site como my-company.com, é uma boa ideia configurar também um subdomínio "www". Isto garante que os utilizadores que se conectam via www.my-company.com são redirecionados para o seu site principal e ajuda a evitar problemas de conteúdo duplicado.
No exemplo abaixo, tanto my-company.com como www.my-company.com são geridos. Os utilizadores que acedem a www.my-company.com são redirecionados para my-company.com:
services:
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # Adicione ambos os domínios aqui
- "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Substitua "<PORT>" pelo porto em que o seu frontend está a ouvir
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Redirecionar 'www.my-company.com' para 'my-company.com':
- 'traefik.http.routers.frontend.middlewares=redirect-www'
- "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
- "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
- "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"
Roteie um caminho para um contentor específico com Traefik
Suponha que tem um contentor dedicado ao seu site de documentação. Pode querer rotear https://my-company.com/docs para este contentor enquanto envia outros pedidos, como https://my-company.com/, para o seu contentor frontend. O exemplo abaixo mostra como isto é feito:
services:
documentations:
image: traefik/whoami
hostname: documentations
labels:
- "traefik.enable=true"
- "traefik.http.routers.documentations.rule=Host(`my-company.com`) && PathPrefix(`/docs`)" # Defina o prefixo do caminho aqui
- "traefik.http.services.documentations.loadbalancer.server.port=<PORT>" # Substitua "<PORT>" pelo porto em que o seu contentor de documentação está a ouvir
- "traefik.http.routers.documentations.tls.certresolver=letsencrypt"
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)"
- "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Substitua "<PORT>" pelo porto em que o seu frontend está a ouvir
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Redirecionar 'www.my-company.com' para 'my-company.com':
- 'traefik.http.routers.frontend.middlewares=redirect-www'
- "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
- "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
- "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"
Agora, visitar https://my-company.com/docs (ou qualquer subcaminho como https://my-company.com/docs/something) exibirá conteúdo do contentor documentations. Outros caminhos, por exemplo https://my-company.com/help, serão servidos pelo contentor frontend.
Definir uma porta de contentor personalizada no Traefik
Por padrão, o Traefik conecta-se à primeira porta exposta do contentor. Em alguns casos, pode precisar de especificar uma porta particular. O exemplo abaixo demonstra como definir uma porta personalizada:
services:
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`)"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Roteie o tráfego de 'https://my-company.com' para o contentor 'frontend' na porta 80
- "traefik.http.services.frontend.loadbalancer.server.port=80"
Boas práticas de nomeação Traefik e Docker Compose
Ao definir um contentor no seu ficheiro docker-compose.yml, alguns campos são importantes para melhor consistência e facilidade de gestão. Considere usar a seguinte configuração recomendada:
services:
<CONTAINER_NAME>:
image: traefik/whoami
hostname: <CONTAINER_NAME>
container_name: <CONTAINER_NAME>
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.<CONTAINER_NAME>.rule=Host(`my-company.com`)"
- "traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=letsencrypt"
Basta substituir <CONTAINER_NAME> pelo nome desejado para o seu contentor, por exemplo frontend.
Erro Let's Encrypt "Domain name contains an invalid character"
Ao criar um subdomínio, o Let's Encrypt segue as RFC 952 e 1123, que permitem apenas caracteres no conjunto [a-zA-Z0-9-].
Embora os underscores ('_') sejam permitidos nos nomes de registos DNS, não são aceitáveis em nomes de host. Como resultado, o Let's Encrypt rejeita subdomínios como "my_subdomain.example.com" e exibe o erro "Domain name contains an invalid character".
Para resolver este problema, basta remover quaisquer underscores dos seus subdomínios.