Como rodar dois (ou mais) sites no mesmo servidor usando docker

Matheus Vellone
stonetech
Published in
4 min readMay 3, 2019

TL;DR com o código completo no final do artigo

Com a popularização da internet, se tornou muito comum para qualquer pessoa/empresa possuir um site, seja ele um a landing page ou um sistema completo. Dado esse crescimento, o interesse das pessoas em possuirem sites/sistemas web também cresceu, e muita gente (eu incluso) precisa hospedar mais de um site em um mesmo servidor, porém, a mesma máquina não consegue executar duas aplicações operando na mesma porta (80 para HTTP e 443 para HTTPS), e é por isso que esse artigo pode te ajudar.

Uma prática muito comum no mercado é a utilização de containers para rodar as aplicações devido à facilidade de se configurar o servidor e garantir a mesma configuração para a aplicação entre várias máquinas. Este artigo utiliza a tecnologia Docker, mais especificamente o docker-compose para gerenciar os containers.

Vamos supor que precisamos ter um blog (meu_blog.com.br) e uma API (minha_api.com.br), escrita em qualquer linguagem, rodando no mesmo servidor.

A ideia é que o servidor receba uma request (seja HTTP ou HTTPS) e seja capaz de redirecioná-la para o container correto de acordo com o seu domínio. Isso pode ser feito com a configuração correta no apache, no nginx ou até mesmo via NAT, mas como queremos algo prático, simples e rápido de fazer, vamos utilizar a imagem jwilder/nginx-proxy, e com um pouco de configuração (sério, é uma linha) tudo estará funcionando.

Provided your DNS is setup to forward foo.bar.com to the host running nginx-proxy, the request will be routed to a container with the VIRTUAL_HOST env var set.

Ou seja, basta adicionar uma variável de ambiente VIRTUAL_HOST com o domínio que deseja o redirecionamento na recepção das requests e tudo já estará funcionando!

Se seu container expõe mais de uma porta, o nginx-proxy irá redirecionar requests para a porta 80. Se você precisar de uma porta diferente, você pode configurar uma variável de ambiente VIRTUAL_PORT para selecionar a porta da sua aplicação. Se seu container expõe apenas uma porta e possui a variável VIRTUAL_HOST, a porta exposta será utilizada.

Vou abordar o assunto assumindo que cada aplicação possui sua própria pasta/repositório, assim, teremos mais de um docker-compose.yml.

Vamos supor que temos o blog na pasta ~/home/user/meu_bloge a api na pasta ~/home/user/minha_api. Nesse caso, precisamos colocar tanto o container do blog, quando o da API na mesma network do docker. Para deixar bem organizado, podemos criar uma network externa e referenciá-la em cada container.

Arquivo~/home/user/meu_blog/docker-compose.yml

Arquivo ~/home/user/minha_api/docker-compose.yml

Arquivo ~/home/user/docker-compose.yml

Com o arquivo criado, só precisamos criar a rede manualmente pois todos containers esperam que ela já esteja criada. Depois, só precisamos subir tudo.

Mas atenção, pelo falo de termos uma network com as duas aplicações na mesma rede do docker, uma aplicação consegue enxergar a outra, portanto, se uma aplicação possuir alguma falha de segurança, a outra aplicação pode ser comprometida também.

Bônus 2: Adicionando HTTPS

Muito provavelmente você também precisa e/ou quer que seu blog/api seja acessível via HTTPS.

Se não conhece as vantagens de utilizar HTTPS, o Google explica um pouquinho sobre o assunto aqui.

Se você já possui um certificado e uma chave privada para seu domínio, você pode simplesmente criar um volume para inserí-los no nginx-proxy da seguinte forma:

Mas, caso você ainda não possua um certificado, não se preocupe. É possível emitir um certificado de maneira rápida, simples e, o melhor de tudo, de graça, usando o Let’s Encrypt.

E para melhorar mais ainda, existe um repositório que se integra diretamente com o Let’s Encrypt. Ele gera certificados para seus domínios e também os renova de forma automática, isso tudo com zero downtime durante a renovação do certificado.

https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion

Para utilizá-lo, precisamos criar um container novo com a seguinte configuração:

A variável de ambiente NGINX_PROXY_CONTAINER deve conter o nome do container dado ao container do nginx-proxy .

Além disso, precisamos identificar nossas aplicações com qual domínios elas estão utilizando, para que o container saiba para quais domínios os certificados devem ser gerados. Para fazer isso, basta adicionar a variável LETSENCRYPT_HOST em cada container onde você deseja HTTPS.

Se você desejar, ainda é possível adicionar a variável LETSENCRYPT_EMAIL com o seu email para receber lembretes de certificados a serem expirados. É importante caso o próprio container não consiga renovar os certificados automaticamente.

Agora não existe mais desculpa pra não ter o seu serviço servindo em HTTPS. Esse simples passo melhora o SEO da sua página e dá mais segurança para seus clientes, todo mundo sai ganhando.

Assim, nosso arquivo docker-compose.yml “principal” do nginx ficará assim

Referências:

Agradecimento especial ao Ivan Micai da Silva por ter me ensinado a utilizar o nginx-proxy e tudo isso que escrevi aqui na forma de artigo.

--

--