↓Pular para o conteúdo principal
  1. blog/
ARTIGO TÉCNICO

Quatro aplicações no mesmo host usando portas distintas, Nginx local e Certbot: organização sem conflito

Como inventariar e organizar várias aplicações Docker no mesmo host com portas distintas, Nginx em 80/443 e certificado cobrindo múltiplos hostnames.

·4 minutos

Um único host pode atender várias aplicações sem conflito, desde que exista uma separação clara entre porta interna/publicada, hostname e camada de entrada.

Em uma coleta real, quatro aplicações Docker estavam publicadas no host em portas diferentes:

1
2
3
4
frontend A        → 3000
frontend B        → 3001
backend           → 5000
landing page      → 4000

No mesmo servidor, Nginx escutava em 80 e 443, e o inventário do Certbot mostrava um certificado cobrindo múltiplos hostnames da aplicação.

O ponto interessante não é a numeração das portas. É a organização que permite descobrir rapidamente quem recebe a conexão e para onde ela precisa seguir.

Comece pelo estado real das portas #

Antes de abrir configuração de Nginx, eu verifico o que realmente está escutando:

1
ss -lntp

Na coleta, isso separava claramente:

1
2
3
4
5
:80/:443  → nginx
:3000     → docker-proxy
:3001     → docker-proxy
:4000     → docker-proxy
:5000     → docker-proxy

Esse mapa já responde metade do troubleshooting.

Se a aplicação funciona em 127.0.0.1:3000, mas o hostname falha em HTTPS, o problema provavelmente está depois da aplicação: Nginx, TLS, DNS ou rota externa.

Depois, confirme containers e portas #

1
2
docker ps --format \
  'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'

O objetivo é montar algo como:

1
hostname público → Nginx → porta local → container

Esse relacionamento deveria ser documentado, não deduzido toda vez que ocorrer incidente.

Nginx precisa ser validado como uma unidade #

Antes de reload:

1
nginx -t

Na coleta analisada, o teste de sintaxe estava OK.

Isso prova que a configuração carregada era sintaticamente válida; não prova que cada server_name ou proxy_pass estava correto.

Para isso, vale inspecionar a configuração efetiva:

1
nginx -T

E procurar:

1
2
3
4
5
server_name
listen
proxy_pass
ssl_certificate
ssl_certificate_key

Um hostname por responsabilidade ajuda muito #

Quando existem frontends, backend e landing page no mesmo host, uma organização comum é:

1
2
3
4
www.example.com       → frontend
operador.example.com  → frontend operador
api.example.com       → backend
example.com           → landing page

O desenho exato depende do produto. O importante é evitar um único vhost cheio de condicionais por path sem necessidade.

Cada server_name pode encaminhar para uma porta local distinta.

Exemplo genérico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    listen 443 ssl;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
        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;
    }
}

Certbot também precisa entrar no inventário #

1
certbot certificates

No ambiente recuperado, um certificado válido cobria vários identificadores/hostnames da mesma aplicação.

Isso ajuda a responder:

1
2
3
4
qual certificado atende cada hostname?
quando expira?
qual caminho do fullchain?
qual chave o Nginx referencia?

Não basta o certificado existir no filesystem. O vhost precisa apontar para ele.

Testar cada camada separadamente #

Aplicação local #

1
2
3
curl -sS -o /dev/null \
  -w '%{http_code}\n' \
  http://127.0.0.1:3000/

Nginx preservando hostname #

1
2
3
curl -skI \
  --resolve www.example.com:443:127.0.0.1 \
  https://www.example.com/

DNS público #

1
dig +short www.example.com

Certificado entregue #

1
2
3
4
5
openssl s_client \
  -connect www.example.com:443 \
  -servername www.example.com \
  </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

Esse método mostra em qual salto o comportamento diverge.

Portas publicadas não precisam ficar abertas para a internet #

A coleta mostrava portas de containers vinculadas em interfaces do host. Isso descreve o estado encontrado, não uma recomendação universal.

Quando somente Nginx precisa acessar a aplicação, é normalmente preferível restringir o bind:

1
2
ports:
  - "127.0.0.1:3000:3000"

ou usar rede Docker interna quando o reverse proxy também está containerizado.

Assim a camada pública continua concentrada em 80/443.

O inventário que eu manteria #

1
2
3
4
5
6
7
8
9
aplicação
container
porta interna
porta publicada
hostname
vhost Nginx
certificado
health endpoint
Compose/projeto

Com isso, adicionar uma quinta aplicação deixa de ser tentativa e erro.

O que a fonte prova #

A coleta real sustenta:

  • quatro aplicações Docker distintas nas portas 3000, 3001, 4000 e 5000;
  • Nginx escutando em 80 e 443;
  • nginx -t válido;
  • Certbot com certificado válido cobrindo múltiplos hostnames;
  • Redis e MongoDB coexistindo no host como componentes adicionais.

O artigo anonimiza domínio, nomes internos, IPs e demais identificadores do ambiente.

Checklist #

1
2
3
4
5
6
7
8
9
[ ] docker ps documentado
[ ] ss -lntp documentado
[ ] relação hostname → porta conhecida
[ ] nginx -t OK
[ ] nginx -T revisado
[ ] certificado correto por hostname
[ ] aplicação local responde
[ ] HTTPS externo responde
[ ] portas internas restritas quando possível

O principal aprendizado #

Várias aplicações no mesmo host não são problema por si só.

O problema começa quando ninguém consegue responder rapidamente:

qual hostname entra em qual vhost, que encaminha para qual porta, que pertence a qual container?

Se essa cadeia está explícita, Nginx, Docker e Certbot conseguem coexistir de forma previsível.

TEM UM CENÁRIO PARECIDO?

Me chama.

Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.

Falar com Castro →
Sem enrolação. Com evidência.