Use Nginx Proxy Manager para gerenciar múltiplos sites com Discourse

De fato, isso exigiu um pouco de tentativa e erro, mas consegui fazer funcionar da seguinte maneira (sem garantia de que esta seja a melhor forma de fazê-lo — na verdade, sei que deve haver uma maneira melhor — então correções e melhorias são muito bem-vindas):

Instruções que @pfaffman moveu para a OP

Para começar, existem duas maneiras de acessar sua instância do Discourse: 1. expondo uma porta, 2. via websocket. Acredito ter aprendido em algum lugar neste fórum que o websocket é mais rápido/mais eficiente, então é isso que estou usando, mas expor uma porta deve ser muito mais fácil. Então, se você não conseguir fazer o socket funcionar, tente expor uma porta (mais sobre isso abaixo).

Vamos supor que você tenha concluído a instalação padrão de 30 minutos e que você ainda não deixou o Discourse obter um certificado do Let’s Encrypt — porque não é necessário quando se usa um proxy reverso. O NPM cuidará disso. Não importa, no entanto, se você já tiver um certificado. O NPM simplesmente obterá um novo.

1. Instalar o NPM

O próximo passo é instalar o NPM para que você tenha mais dois containers Docker em execução (o NPM e seu container de banco de dados).

Agora vem a parte complicada sobre a qual você está perguntando.

O primeiro obstáculo é que o Discourse roda na rede bridge padrão do Docker, enquanto o NPM, por padrão, roda em uma “rede criada pelo usuário” (chamada npm_default no meu caso), o que significa que o NPM não consegue ver o Discourse. :cry:

2. Trazer todos os containers para a rede bridge padrão

Então, enquanto não sei se e como o Discourse pode ser movido para uma rede personalizada, temos que mover o NPM para a rede bridge padrão. Podemos fazer isso adicionando network_mode: bridge a ambos os containers do NPM no nosso arquivo docker compose.

3. Usar endereço IP em vez de nome de serviço

O próximo problema é que o arquivo docker compose padrão não funcionará mais se você apenas movê-lo para a rede bridge. O NPM não conseguirá mais encontrar seu container de banco de dados. Isso ocorre porque a resolução interna de DNS para nomes de serviço (da qual o arquivo docker-compose depende) está disponível apenas em redes criadas pelo usuário, não nas redes padrão do Docker. Então, temos que recorrer a endereços IP codificados manualmente (o que é definitivamente não a solução ideal, pois quebrará se os IPs dos seus containers mudarem). Portanto, você precisa iniciar o container mesmo sabendo que não funcionará, anote o IP do container de banco de dados do NPM e substitua DB_MYSQL_HOST: "db" no seu arquivo docker compose por DB_MYSQL_HOST: "<ip_do_container_db>".

Agora, todos os containers devem estar na rede bridge padrão para que o NPM possa ver tanto o Discourse quanto seu banco de dados.

4. Tornar o Discourse acessível

Mas “ver” o Discourse e conseguir acessá-lo não é a mesma coisa. Então, você precisa garantir que o Discourse aceite qualquer tráfego que o NPM encaminhe para ele. Se você não se importa em usar o websocket, imagino que possa apenas apontar o NPM para a porta 80 (não 443) do IP do seu container do Discourse, assim:

Não testei isso, no entanto. Como mencionei, estou usando a configuração do websocket, que requer alguns passos adicionais. Note que o nome de host/IP e a porta acima serão ignorados quando você usar o websocket.

5. Configurar app.yml para usar websocket

Isso está explicado na OP, então não vou entrar nisso.

6. Montar o websocket no container do NPM

Precisamos dar ao NPM acesso ao websocket montando-o como um volume: - /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock. Esta é a última alteração no arquivo docker compose padrão do NPM, então aqui está a versão final que funciona para mim:

version: '3'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    network_mode: bridge
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    environment:
      DB_MYSQL_HOST: "172.17.0.6"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "my-super-safe-pwd"
      DB_MYSQL_NAME: "npm"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
      - /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock
  db:
    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    network_mode: bridge
    environment:
      MYSQL_ROOT_PASSWORD: 'my-super-safe-pwd'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'my-super-safe-pwd'
    volumes:
      - ./data/mysql:/var/lib/mysql

7. Configurar o NPM para usar o websocket

Último passo: dizer ao NPM para usar o websocket. Até onde me lembro, não foi suficiente apenas ativar o “Suporte a Websockets”, então copiei a localização do NGINX da OP para a aba “Avançado”, assim:

Não consegui fazer isso funcionar na aba “Locais personalizados”.

8. Não se esqueça de ativar o SSL

Não mencionei a configuração SSL no NPM porque parece bastante óbvia e não acho que importa em que ponto do processo você a ativa. Então, se você ainda não fez isso, é assim que a minha se parece:


9. Aviso final

Enquanto escrevia este post, de repente me ocorreu que o NPM e o Discourse provavelmente nem precisam estar na mesma rede Docker quando usamos o websocket. Não tenho tempo para verificar isso no momento, mas se isso for verdade, então você pode simplesmente esquecer os passos 2, 3 e 4 acima e deve funcionar.

Este é o aspecto mais fascinante dos fóruns de suporte: fazer um bom trabalho descrevendo seu problema frequentemente leva você à solução sem nem mesmo postar sua pergunta. E, neste caso, eu estava respondendo à pergunta de outra pessoa, mas também pode ter encontrado a resposta para a minha própria. :smiley:

4 curtidas