Proxy reverso com Docker
Por que usar um proxy reverso com Docker?
Containers recebem IPs aleatórios, acessíveis apenas no hospedeiro. Você pode acessar o serviço do container mapeando a porta interna daquele serviço com uma porta no hospedeiro. Por exemplo, um container nginx
cuja porta interna é a 80, mapeada para a porta 80 do hospedeiro:
docker run --name container-nginx-php7.4 -d -p 80:80 webdevops/php-nginx-dev:7.4
E quando outros containers também usam a porta 80? Aí entra o proxy reverso. Considere 2 containers rodando nginx
, mas sem mapear a porta 80 com o hospedeiro:
docker run --name container-nginx-php7.4 -d -p 80:80 webdevops/php-nginx-dev:7.4
docker run --name container-nginx-php8.0 -d -p 80:80 webdevops/php-nginx-dev:8.0
As requisições externas chegarão ao proxy reverso instalado no hospedeiro usando o seguinte esquema:
nginx-php74.server.com --> redireciona o tráfego para o container container-nginx-php7.4
nginx-php80.server.com --> redireciona o tráfego para o container container-nginx-php8.0
Ao invés de acessar o serviço mapeando portas diferentes no hospedeiro, você acessará através do mapeamento de URLs. Porém, como os IPs dos containers não são fixos, como fazer este mapeamento automaticamente?
nginx-proxy
A solução é automatizar a configuração do proxy reverso.
nginx-proxy configura um container rodando nginx
e docker-gen
. docker-gen
gera um proxy reverso para nginx
e recarrega nginx
quando containers são iniciados ou encerrados no hospedeiro.
Requisitos
- Docker
- docker-compose
- Registros de DNS apontando para o hospedeiro
Como usar
Para o nosso exemplo, criaremos 3 serviços em arquivos docker-compose.yml
independentes. Nos links a seguir você poderá baixá-los:
Crie um diretório para cada docker-compose.yml
.
Rede Docker
Para que o container nginx-proxy
encontre os demais containers inicializados no hospedeiro, é preciso que compartilhem uma rede em comum. Isto é obtido através da seguinte diretiva do docker-compose.yml:
networks:
default:
external:
name: docker-production <=== rede em modo bridge
Para que os containers fiquem visíveis ao nginx-proxy
, também precisam ter acesso a rede docker-production
.
Para criar a rede, execute no hospedeiro:
$ docker network create docker-production
fdbacfcb063758665c0101c9eaf94cf908569eaa248b00438a429a2a341d088c <=== identificador da rede criada
Inicialização
Inicialize o docker-compose de cada projeto:
docker-compose up -d
Conectando projetos
Para que um projeto (e.g. container-nginx-php7.4, container-nginx-php8.0) utilize o proxy reverso nginx-proxy
, é necessário conectá-lo a rede docker-production
, incluindo ao final do seu docker-compose.yml
:
networks:
default:
external:
name: docker-production <=== rede em modo bridge
Ainda no docker-compose.yml
, defina uma variável de ambiente com o nome do host que os usuários utilizarão para acessar o serviço e a sua porta dentro do container (a porta não precisa ficar exposta no host):
services:
cms-web:
image: webdevops/php-nginx-dev:7.4
environment:
- VIRTUAL_HOST=nginx-php74.server.com
- VIRTUAL_PORT=80
Certificados SSL
acme-companion é um container que trabalha para nginx-proxy
, criando e renovando certificados SSL Let’s Encrypt dos serviços guarnecidos pelo proxy reverso, através do protocolo ACME (Ambiente de Gerenciamento de Certificados Automatizados).
É inicializado com o container nginx-proxy
.
Para que os containers guarnecidos pelo nginx-proxy
utilizem a criação e renovação automatizada de certificados SSL Let’s Encrypt, declare o nome do host na variável de ambiente LETSENCRYPT_HOST
, no docker-compose.yml
do projeto:
services:
cms-web:
image: webdevops/php-nginx-dev:7.4
environment:
- VIRTUAL_HOST=nginx-php74.server.com
- LETSENCRYPT_HOST=nginx-php74.server.com <== host para criação ou renovação do certificado SSL
- VIRTUAL_PORT=80
CI/CD
Crie projetos no Github, Gitlab ou a sua ferramenta de CI/CD e automatize a criação dos containers. ;)