Usa Nginx Proxy Manager para gestionar múltiples sitios con Discourse

Efectivamente, esto requirió un poco de prueba y error, pero logré que funcionara de la siguiente manera (no hay garantía de que esta sea la mejor manera de hacerlo; de hecho, sé que debe haber una mejor, así que las correcciones y mejoras son muy bienvenidas):

Instrucciones que @pfaffman movió a la primera publicación

Para empezar, hay dos formas de acceder a tu instancia de Discourse: 1. exponiendo un puerto, 2. mediante un websocket. Creo haber leído en algún lugar de este foro que el websocket es más rápido/más eficiente, por lo que es lo que estoy usando, pero exponer un puerto debería ser mucho más fácil; así que, si no logras que el socket funcione, intenta exponer un puerto (más sobre esto más abajo).

Supongamos que has completado la instalación estándar de 30 minutos y que aún no has dejado que Discourse obtenga un certificado de Let’s Encrypt, ya que no lo necesitas cuando usas un proxy inverso. NPM se encargará de eso. Sin embargo, no importa si ya tienes un certificado; NPM simplemente obtendrá uno nuevo.

1. Instalar NPM

El siguiente paso es instalar NPM para que tengas dos contenedores Docker más en ejecución (NPM y su contenedor de base de datos).

A continuación viene la parte complicada sobre la que preguntas.

El primer obstáculo es que Discourse se ejecuta en la red bridge predeterminada de Docker, mientras que NPM, por defecto, se ejecuta en una red “creada por el usuario” predeterminada (en mi caso llamada npm_default), lo que significa que NPM no puede ver Discourse. :cry:

2. Mover todos los contenedores a la red bridge predeterminada

Así que, mientras no sepa si y cómo se puede mover Discourse a una red personalizada, tenemos que mover NPM a la red bridge predeterminada. Podemos hacer esto añadiendo network_mode: bridge a ambos contenedores de NPM en nuestro archivo docker compose.

3. Usar la dirección IP en lugar del nombre del servicio

El siguiente problema es que el archivo docker compose estándar ya no funcionará si simplemente lo mueves a la red bridge. NPM ya no podrá encontrar su contenedor de base de datos. Esto se debe a que la resolución interna de DNS para los nombres de servicio (de la que depende el archivo docker-compose) solo está disponible en redes creadas por el usuario, no en las redes predeterminadas de Docker. Así que tenemos que recurrir a direcciones IP codificadas (lo cual es definitivamente la solución no óptima porque fallará si las direcciones IP de tus contenedores cambian). Por lo tanto, necesitas iniciar el contenedor aunque sepas que no funcionará, anotar la IP del contenedor de base de datos de NPM y reemplazar DB_MYSQL_HOST: "db" en tu archivo docker compose con DB_MYSQL_HOST: "<ip_del_contenedor_db>".

Ahora todos los contenedores deberían estar en la red bridge predeterminada para que NPM pueda ver tanto a Discourse como a su base de datos.

4. Hacer que Discourse sea accesible

Pero “ver” Discourse y poder acceder a él no es lo mismo. Así que debes asegurarte de que Discourse acepte todo el tráfico que NPM le reenvíe. Si no te importa usar el websocket, supongo que puedes simplemente apuntar NPM al puerto 80 (no al 443) de la IP de tu contenedor de Discourse, así:

Aunque no he probado esto. Como mencioné, estoy usando la configuración de websocket, lo que requiere algunos pasos adicionales. Ten en cuenta que el nombre de host/IP y el puerto anteriores se ignorarán cuando uses el websocket.

5. Configurar app.yml para usar websocket

Esto se explica en la primera publicación, así que no entraré en detalles.

6. Montar el websocket en el contenedor NPM

Necesitamos dar acceso a NPM al websocket montándolo como un volumen: - /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock. Este es el último cambio en el archivo docker compose predeterminado de NPM, así que aquí está la versión final que funciona para mí:

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 NPM para usar el websocket

Último paso: decirle a NPM que use el websocket. Por lo que recuerdo, no fue suficiente simplemente activar “Soporte de Websockets”, así que copié la ubicación de NGINX de la primera publicación a la pestaña “Avanzado”, así:

No logré que esto funcionara en la pestaña “Ubicaciones personalizadas”.

8. No olvides activar SSL

No mencioné la configuración SSL en NPM porque parece bastante obvia y no creo que importe en qué punto del proceso la actives. Así que, si aún no lo has hecho, esto es lo que tiene el mío:


9. Descargo de responsabilidad final

Mientras escribía esta publicación, se me ocurrió de repente que NPM y Discourse probablemente ni siquiera necesitan estar en la misma red de Docker cuando usamos el websocket. No tengo tiempo para verificar esto en este momento, pero si esto es cierto, entonces puedes simplemente olvidar los pasos 2, 3 y 4 anteriores y debería funcionar.

Este es el aspecto más fascinante de los foros de soporte: hacer un buen trabajo describiendo tu problema a menudo te lleva a la solución sin siquiera publicar tu pregunta. Y en este caso, estaba respondiendo a la pregunta de otra persona, pero también podría haber encontrado la respuesta a la mía. :smiley:

4 Me gusta