Nginx Proxy Manager를 사용해 Discourse로 여러 사이트 관리하기

수정: @pfaffman 님이 @tophee 님이 이전에 작성한 내용을 기반으로 이 내용을 독립적인 주제로 다시 작성했습니다. 아직 제가 테스트를 해보지 않았고, Chris의 문구를 여기저기 이동했으므로, 실수가 있다면 대부분 @pfaffman 님의 책임일 가능성이 높습니다.

Run other websites on the same machine as Discourse 에 설명된 대로 수동으로 처리하는 대신 NGINX Proxy Manager를 사용해야 할 이유가 없다면요?

저는 이미 이를 사용하고 있습니다. 개인 서버에 꽤 오랫동안 사용하다가 Discourse 인스턴스를 새로운 클라우드 서버로 이전했을 때, 4년 전 구 서버에서 설정했던 NGINX 리버스 프록시 설정의 대부분을 잊어버렸다는 것을 깨달았습니다. 그래서 "NGINX Proxy Manager로 하면 어떨까?"라고 생각했죠. 놀랍게도 메타 포럼에서 이 도구가 언급되는 경우가 드물다는 것을 알게 되었고, 제가 놓친 단점이 있는지 궁금해지기 시작했습니다.

실제로 이 과정은 시행착오가 좀 필요했지만, 다음과 같이 작동하게 만들었습니다(이것이 최선의 방법이라는 보장은 없습니다. 사실 더 나은 방법이 있을 것이라고 확신합니다. 따라서 수정과 개선 제안은 매우 환영합니다):

우선, Discourse 인스턴스에 접근하는 방법은 두 가지입니다: 1. 포트 노출, 2. 웹소켓을 통한 접근. 이 포럼 어딘가에서 웹소켓이 더 빠르고 효율적이라는 것을 배운 것 같아서 웹소켓을 사용하고 있지만, 포트 노출이 훨씬 쉬울 것입니다. 따라서 웹소켓 작동을 설정할 수 없다면 포트 노출을 시도해 보세요. 혼동을 피하기 위해: 포트를 통해 Discourse에 접근하려면 아래 단계 0, 1, 2, 3, 4, 8을 따르세요. 웹소켓을 사용하려면 단계 0, 1, 5, 6, 7, 8, 9를 따르세요.

0. 시작점

30분 표준 설치를 완료했다고 가정하고, 아직 Discourse가 Let’s Encrypt 인증서를 발급받지 않았다고 가정해 보겠습니다. 리버스 프록시를 사용하는 경우 인증서가 필요 없기 때문입니다. NGINX Proxy Manager가 그 역할을 대신합니다. 이미 인증서가 있어도 상관없습니다. NGINX Proxy Manager가 단순히 새로운 인증서를 발급받게 될 뿐입니다.

1. NGINX Proxy Manager 설치

다음 단계는 NGINX Proxy Manager를 설치하여 두 개의 도커 컨테이너(NGINX Proxy Manager와 그 데이터베이스 컨테이너)가 추가로 실행되도록 하는 것입니다.

다음은 질문하신 부분인 다소 까다로운 부분입니다.

첫 번째 장애물은 Discourse가 기본 도커 bridge 네트워크에서 실행되는 반면, NGINX Proxy Manager는 기본적으로 “사용자 생성 네트워크”(제 경우 npm_default라고 불리는)에서 실행된다는 것입니다. 이는 NGINX Proxy Manager가 Discourse를 볼 수 없음을 의미합니다. :cry:

2. 모든 컨테이너를 기본 bridge 네트워크로 이동

Discourse를 사용자 지정 네트워크로 이동할 수 있는지, 그리고 어떻게 해야 하는지 제가 알지 못하기 때문에, NGINX Proxy Manager를 기본 bridge 네트워크로 이동해야 합니다. 도커 컴파일 파일의 두 NGINX Proxy Manager 컨테이너에 network_mode: bridge를 추가하여 이를 수행할 수 있습니다.

3. 서비스 이름 대신 IP 주소 사용

다음 문제는 bridge 네트워크로만 이동하면 표준 도커 컴파일 파일이 더 이상 작동하지 않는다는 것입니다. NGINX Proxy Manager가 더 이상 데이터베이스 컨테이너를 찾을 수 없게 됩니다. 이는 서비스 이름에 대한 내부 DNS 해석(도커 컴파일 파일이 이에 의존)이 사용자 생성 네트워크에서만 사용 가능하고 기본 도커 네트워크에서는 사용 불가능하기 때문입니다. 따라서 하드코딩된 IP 주소를 사용해야 합니다(컨테이너 IP가 변경되면 깨지므로 이것이 확실히 최적의 해결책이 아닌 이유입니다). 따라서 컨테이너가 작동하지 않는다는 것을 알면서도 시작해야 하고, NGINX Proxy Manager 데이터베이스 컨테이너의 IP를 적어 두었다가 도커 컴파일 파일의 DB_MYSQL_HOST: "db"DB_MYSQL_HOST: "<db_container_IP>"로 교체해야 합니다.

이제 모든 컨테이너가 기본 bridge 네트워크에 있으므로 NGINX Proxy Manager가 Discourse와 데이터베이스를 모두 볼 수 있습니다.

4. Discourse 접근 가능하게 만들기

그러나 Discourse를 “보는” 것과 접근할 수 있는 것은 같은 것이 아닙니다. 따라서 NGINX Proxy Manager가 전달하는 모든 트래픽을 Discourse가 수락하도록 확인해야 합니다. 웹소켓 사용을 신경 쓰지 않는다면, NGINX Proxy Manager를 Discourse 컨테이너 IP의 포트 80(443이 아님)으로 지정하면 될 것입니다. 다음과 같이요:

다만, 이것은 테스트해 보지 않았습니다. 언급했듯이 저는 웹소켓 설정을 사용하고 있으며, 이는 몇 가지 추가 단계를 요구합니다. 웹소켓을 사용하는 경우 위 호스트명/IP와 포트는 무시됩니다.

5. app.yml을 웹소켓 사용으로 구성

이것은 OP(원문)에서 설명되어 있으므로 자세히 다루지 않겠습니다.

6. NGINX Proxy Manager 컨테이너에 웹소켓 마운트

볼륨으로 마운트하여 NGINX Proxy Manager가 웹소켓에 액세스할 수 있도록 해야 합니다: - /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock. 이것은 기본 NGINX Proxy Manager 도커 컴파일 파일에 대한 마지막 변경 사항이므로, 제 환경에서 작동하는 최종 버전은 다음과 같습니다:

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. NGINX Proxy Manager를 웹소켓 사용으로 구성

마지막 단계: NGINX Proxy Manager가 웹소켓을 사용하도록 지시합니다. 기억이 정확하지는 않지만, 단순히 "Websockets support"를 켜는 것만으로는 부족했던 것 같아서 OP의 NGINX location을 “Advanced” 탭에 복사했습니다. 다음과 같이요:

“Custom locations” 탭에서는 작동하지 않았습니다.

8. SSL 활성화 잊지 마세요

NGINX Proxy Manager의 SSL 구성에 대해 언급하지 않은 이유는 꽤 자명해 보였고, 프로세스의 어느 시점에 활성화하는지는 중요하지 않다고 생각했기 때문입니다. 따라서 아직 하지 않았다면, 제 설정은 다음과 같습니다:


9. 주의 사항

요약하자면, Discourse 컨테이너를 재시작할 때마다 메인 NGINX Proxy Manager 컨테이너도 재시작해야 합니다(db 재시작은 불필요).
Discourse에 웹소켓을 통해 액세스하고 있다면, Discourse 컨테이너를 재빌드할 때(기본 이미지를 업데이트하기 위해 몇 개월마다 필요함) 이전 웹소켓이 삭제되고 새 웹소켓이 생성된다는 점을 알아야 합니다. 그 결과, NGINX Proxy Manager가 Discourse 인스턴스와 연결을 잃고 502 오류를 발생시킵니다. 향후 NGINX Proxy Manager 업데이트에서 새 웹소켓을 자동으로 찾을 수 있게 될 수도 있지만, 현재(2022년 1월) NGINX Proxy Manager는 NGINX Proxy Manager를 재시작하지 않으면 재빌드된 Discourse 컨테이너를 찾지 못합니다.

설명

위 지침이 왜 웹소켓과 포트를 결합하는지 궁금해하신다면, 단순한 이유는 이 글을 작성하면서 갑자기 NGINX Proxy Manager와 Discourse가 웹소켓을 사용하는 경우 같은 도커 네트워크에 있을 필요가 없을 수도 있다는 생각이 떠올랐기 때문입니다. 그리고 이것이 확인되었을 때, 아무도 지침을 완전히 다시 작성하고 싶어 하지 않았습니다.

지원 포럼의 가장 매혹적인 측면은 문제를 잘 설명하는 것이 질문을 게시하기 전에 해결책으로 이어지는 경우가 많다는 것입니다. 그리고 이 경우, 저는 다른 사람의 질문에 답하면서도 제 자신의 질문에 대한 답을 찾았을지도 모릅니다. :smiley:

9개의 좋아요

어떤 리버스 프록시를 사용해야 하는지 논의하는 것은 명확하게 지원 범위를 벗어납니다. :wink: 하지만 NGINX Proxy Manager를 12초 이상 살펴본 결과, 잘 작동할 것 같다고 생각합니다. 이전에 논의된 적이 있는 또 다른 자동화 NGINX 프록시 도구가 있는데, 제 방대한 NGINX Proxy Manager 지식을 바탕으로 볼 때 그 도구가 더 나을 것 같습니다. Traefik에 점점 실망하고 있기 때문에, 그 도구를 살펴볼 수도 있겠네요.

수정: 이제 3분 동안 살펴봤습니다. 저는 자동화를 촉진하는 도구를 선호하므로, Docker 컨테이너에 몇 가지 라벨이나 환경 변수를 추가하기만 하면 웹 인터페이스에서 클릭할 필요가 없는 Traefik과 jwilder/nginx-proxy - Docker Image (이것을 찾았습니다)가 제가 원하는 방식에 더 가깝습니다. 그리고 그 도구를 작동시키려면 웹 인터페이스를 사용하거나, 추가하려는 호스트를 수동으로 데이터베이스에 업데이트하는 우회 방법을 찾아야 하는 것 같습니다. 하지만 웹 인터페이스를 일반인(시스템 관리자 "인간"이 아니라)처럼 이것저것 클릭하는 데 거리낌이 없다면, 그 도구가 바로 당신이 찾고 있는 것이 될 수 있을 것 같습니다.

4개의 좋아요

Nginx Proxy Manager 설치를 시도해 보았지만, 웹으로 접속했을 때 Discourse를 볼 수 있도록 Discourse 컨테이너를 어떻게 “연결”(프록시? 시스템 관리가 처음이라 죄송합니다)해야 하는지 이해하지 못하겠습니다.
어떤 힌트를 주실 수 있을까요? 이 포럼 주제에서 제안하듯, Discourse 컨테이너가 80번과 443번 포트를 노출해야 하는가요, 아니면 하지 말아야 하는가요?

1개의 좋아요

사실 이것을 작동하게 하려면 시행착오가 좀 필요했지만, 다음과 같이 성공했습니다(이것이 최선의 방법이라는 보장은 없습니다. 실제로는 더 나은 방법이 있을 것이라고 생각하므로, 수정과 개선에 대한 조언을 매우 환영합니다):

@pfaffman이 OP로 이동시킨 지침

우선, Discourse 인스턴스에 접근하는 방법은 두 가지가 있습니다: 1. 포트 노출, 2. 웹소켓을 통한 접근. 이 포럼 어딘가에서 웹소켓이 더 빠르고 효율적이라고 들었기 때문에 웹소켓을 사용하지만, 포트 노출이 훨씬 쉬울 수 있으므로 웹소켓이 작동하지 않으면 포트 노출을 시도해 보세요(아래에 자세히 설명되어 있음).

자, 30분 표준 설치를 완료했고, 아직 Discourse가 Let’s Encrypt 인증서를 발급받지 않았다고 가정해 보겠습니다. 리버스 프록시를 사용하는 경우 인증서가 필요 없기 때문입니다. NPM이 그 일을 처리해 줄 것입니다. 이미 인증서가 있어도 상관없습니다. NPM이 단순히 새로운 인증서를 발급받기만 하면 됩니다.

1. NPM 설치

다음 단계는 NPM을 설치하는 것입니다. 이렇게 하면 두 개의 Docker 컨테이너(NPM 및 해당 데이터베이스 컨테이너)가 추가로 실행됩니다.

다음은 질문하신 다소 까다로운 부분입니다.

첫 번째 장벽은 Discourse가 기본 Docker bridge 네트워크에서 실행되는 반면, NPM은 기본적으로 “사용자 생성 네트워크”(제 경우 npm_default라고 불림)에서 실행된다는 것입니다. 즉, NPM은 Discourse를 볼 수 없습니다. :cry:

2. 모든 컨테이너를 기본 bridge 네트워크로 이동

Discourse를 사용자 지정 네트워크로 이동할 수 있는지, 그리고 어떻게 해야 하는지 제가 알지 못하는 한, NPM을 기본 bridge 네트워크로 이동해야 합니다. Docker Compose 파일의 두 NPM 컨테이너 모두에 network_mode: bridge를 추가하여 이를 수행할 수 있습니다.

3. 서비스 이름 대신 IP 주소 사용

다음 문제는 bridge 네트워크로만 이동하면 표준 Docker Compose 파일이 더 이상 작동하지 않는다는 것입니다. NPM이 더 이상 데이터베이스 컨테이너를 찾을 수 없게 됩니다. 이는 서비스 이름에 대한 내부 DNS 해석(Docker Compose 파일이 의존하는 것)이 사용자 생성 네트워크에서만 사용 가능하고 기본 Docker 네트워크에서는 사용 불가능하기 때문입니다. 따라서 하드코딩된 IP 주소를 사용해야 합니다(컨테이너 IP가 변경되면 깨지므로 이것이 확실히 최적의 해결책이 아닌 이유입니다). 따라서 작동하지 않는다는 것을 알면서도 컨테이너를 시작하고, NPM 데이터베이스 컨테이너의 IP를 적어 두어야 하며, Docker Compose 파일의 DB_MYSQL_HOST: "db"DB_MYSQL_HOST: "<db_container_IP>"로 대체해야 합니다.

이제 모든 컨테이너가 기본 bridge 네트워크에 있으므로 NPM이 Discourse와 데이터베이스를 모두 볼 수 있게 됩니다.

4. Discourse 접근 가능하게 만들기

그러나 Discourse를 “보는” 것과 접근할 수 있는 것은 다른 문제입니다. 따라서 NPM이 전달하는 트래픽을 Discourse가 수용하도록 해야 합니다. 웹소켓 사용을 신경 쓰지 않는다면, NPM을 Discourse 컨테이너 IP의 포트 80(443이 아님)으로 가리키면 됩니다. 방법은 다음과 같습니다:

다만, 이것은 테스트해 보지 않았습니다. 언급했듯이 저는 웹소켓 설정을 사용하며, 이를 위해 몇 가지 추가 단계가 필요합니다. 웹소켓을 사용할 경우 위의 호스트명/IP와 포트는 무시됩니다.

5. 웹소켓 사용을 위한 app.yml 구성

이것은 OP에서 설명되어 있습니다, 따라서 여기서 자세히 다루지 않겠습니다.

6. NPM 컨테이너에 웹소켓 마운트

볼륨으로 마운트하여 NPM이 웹소켓에 접근할 수 있도록 해야 합니다: - /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock. 이것이 기본 NPM Docker Compose 파일에 대한 마지막 변경 사항이므로, 제 환경에서 작동하는 최종 버전은 다음과 같습니다:

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. NPM을 웹소켓 사용하도록 구성

마지막 단계: NPM이 웹소켓을 사용하도록 지시합니다. 기억하기로는 "Websockets support"를 단순히 켜는 것만으로는 부족했던 것 같아서, OP의 NGINX location을 “Advanced” 탭에 복사했습니다. 방법은 다음과 같습니다:

“Custom locations” 탭에서는 작동하지 않았습니다.

8. SSL 활성화 잊지 마세요

NPM의 SSL 구성은 매우 자명해 보이고, 프로세스의 어느 시점에 활성화하는지는 중요하지 않다고 생각하기 때문에 언급하지 않았습니다. 따라서 아직 하지 않았다면, 제 설정은 다음과 같습니다:


9. 최종 면책 조항

이 글을 쓰던 중, 웹소켓을 사용하는 경우 NPM과 Discourse가 같은 Docker 네트워크에 있을 필요가 없을 수도 있다는 생각이 갑자기 들었습니다. 현재 이를 확인할 시간이 없지만, 이것이 사실이라면 위의 2, 3, 4번 단계를 무시해도 작동할 것입니다.

지원 포럼의 가장 매혹적인 측면은 다음과 같습니다: 문제를 잘 설명하는 것이 질문을 게시하지 않고도 해결책으로 이어지는 경우가 많습니다. 그리고 이 경우, 저는 다른 사람의 질문에 답변하고 있었지만 제 자신의 질문에 대한 답도 찾았을 수 있습니다. :smiley:

4개의 좋아요

정말 훌륭하고 세심한 답변을 주셔서 감사합니다! 조언을 최대한 빨리 시도해 보겠습니다.顺便, NPM에 입력할 IP는 서버의 IP(즉, 서버에 접근하기 위한 외부 IP)인가요, 아니면 Docker 내부 IP인가요? (컨테이너에 172…를 사용한다는 것을 확인했습니다.)
질문이 사소하게 느껴질 수 있어 죄송합니다. 네트워크 관련 사항을 잘 모르기 때문입니다.

1개의 좋아요

웹소켓(websocket) 사용을 권장합니다. 이렇게 하면 IP가 사용되지 않으므로 아무 값을 입력해도 됩니다. 그렇지 않은 경우, 호스트의 공개 IP가 아니라 컨테이너의 내부 IP를 사용해야 합니다.

참고: 이메일을 통한 답변이 올바르게 렌더링되지 않은 것 같습니다. 위의 게시물을 수정(단축)해 보시는 건 어떨까요?

2개의 좋아요

네, 확인했습니다. 이메일의 "답장"을 사용했는데, 원래 메시지가 전부 포함되려고 하더군요. 그런데 수정하는 방법을 찾을 수 없는데, 가능한가요? 저는 사용자로도 Discourse가 처음이라서… :pensive:

1개의 좋아요

메시지 하단의 연필 아이콘을 사용하여 게시물을 편집할 수 있습니다. 다만… 신뢰 수준(Trust Level) 1 이하인 사용자는 기본적으로 24시간 동안만, 신뢰 수준 2 이상인 사용자는 기본적으로 30일 동안 편집할 수 있습니다.

현재 신뢰 수준 1(Basic)인 것으로 보이지만, '레벨 업’을 위해 무엇을 해야 하는지에 대한 자세한 내용은 신뢰 수준에서 확인하실 수 있습니다. :+1:

2개의 좋아요

지난 질문 이후 꽤 시간이 흘렀네요. 제안해 주신 방법을 시도하는 데 많은 시간을 보냈지만, 전혀 성공하지 못했습니다. app.yml을 수정하고 제안하신 변경 사항으로 앱을 다시 빌드했을 때, 로그에 "config/unicorn_launcher: line 71: kill: (898) - No such process"라는 메시지가 표시되기 시작했습니다. 어떤 시도를 해도 이 동작을 멈출 수가 없었습니다. 포트가 노출된 상태이고 websocket이 없는 원래 상태로 앱을 다시 빌드해 보기도 했고, npm을 정지해 보기도 했지만, "unicorn"이 실행되지 않아서 전혀 해결되지 않았습니다.

이 문제에 대해 구글에서 찾을 수 있는 모든 방법도 시도해 보았지만(보편적인 문제인 것 같습니다), 제대로 작동하는 discourse 컨테이너를 다시 빌드하는 방법을 찾을 수가 없었습니다. 현재 문제(그중에서도 가장 큰 문제 중 하나이며, discourse를 포기할 지경에 다다랐습니다)는 알 수 없는 이유로 내부 postgres가 항상 “restarting” 상태라는 것입니다.

왜 이런 일이 일어나는지는 모르겠습니다. 단순히 제안하신 변경 사항을 적용하고 앱을 다시 빌드했을 뿐인데, 그때부터 "unicorn"은 죽어 버렸습니다. :roll_eyes:

이 postgres 문제를 수정할 방법이 있을까요? 왜 이런 일이 발생한 것일까요? discourse가 정상적으로 작동했을 때 했던 모든 변경 사항을 잃지 않을 가능성이 있을까요? (전혀 없을 것 같지만요!)

그리고 참고로, 사소한 변경이나 문제를 해결하려는 시도가 항상 다른 부분의 작동 중단으로 이어지는 것이 정상인가요? :rage:

화난 것이 아니라 discourse 자체에 대한 이야기입니다. 이 “겉으로 보기에는” 괜찮은 포럼을 작동하게 하려고 많은 시간을 들였는데, 매번 다른 문제가 발생해서 discourse가 매우 신뢰할 수 없는 시스템이라는 제 느낌은 점점 더 강해지고 있습니다.

1개의 좋아요

정상적으로 작동하던 표준 설치 환경이 있었다면, 모든 것을 이전 상태로 되돌려 두면 계속 정상적으로 작동할 수 있을 것입니다.

Postgres 문제는 PostgreSQL 13 업데이트와 관련이 있을 수 있습니다?

작업을 시작하기 전에 백업을 만들었다면, 새 서버에 설치하고 해당 백업을 복원할 수 있습니다. 이것이 최악의 시나리오가 될 것입니다.

2개의 좋아요

포스트그레SQL 문제가 13 버전 업데이트와 관련이 있는지 어떻게 알 수 있을까요? 저는 업데이트를 선택하지 않았고, 단순히 "./launcher rebuild app"을 실행했을 뿐인데 모든 일이 벌어졌습니다.
네, 버전은 13입니다. 인터넷에서 같은 문제를 겪는 다른 사용자들의 글을 몇 시간 동안 읽은 끝에 이것이 문제일 수 있다는 것을 발견했지만, discourse를 다시 실행하는 방법을 찾지 못했습니다.

1개의 좋아요

그렇다면 그 문제가 아니군요. 죄송합니다.

1개의 좋아요

이런 문제가 발생했다는 소식에 안타깝습니다. 무언가를 고치려고 몇 시간을 보낸 그 답답한 기분을 잘 알고 있어요. 하지만 매번 무언가를 배우게 되죠. 해답으로 가는 길이 직선인 경우는 드물지만요…

죄송하지만, 이 문제에 대해 도움을 드릴 적절한 사람이 아닙니다. postgres나 유니콘에 대한 경험이 전혀 없거든요. 저는 이런 “아무것도 안 되는” 상황을 다음과 같은 세 가지 방법으로 극복합니다: 1. 원래 상태로 되돌아갈 수 있도록 백업을 해두는 것. 2. 한 번에 한 가지씩만 변경하고, 먼저 프로덕션이 아닌 머신(또는 중요도가 낮은 포럼)에서 테스트하는 것. 3. 문제를 파악하기 위해 더 많은 시간을 투자하는 것.

참고로: 상세한 문제 설명이나 지원 티켓을 여러 번 작성해 본 경험이 문제를 해결하는 데 도움이 되었습니다. 티켓을 제출할 필요조차 없었어요. 작성하는 과정에서 해결책이 보였거든요.

따라서 당신의 경우, 제가 이해하려고 할 부분은 다음과 같습니다: app.yml을 변경했다가 원래 상태로 되돌렸을 때, 원래 결과와 다른 결과가 나올 수 있는 상황은 무엇인지요. 이 부분을 조사하다 보면, 실제로 정확한 원래 상태로 복원하지 않았다는 사실을 깨닫거나, 정상 작동하려면 “리셋”해야 할 다른 것이 무엇인지 이해하게 될 것입니다.

5개의 좋아요

정말 죄송하지만 이해가 되지 않습니다. 처음에 포스트그레SQL 문제가 Postgresql 13 업데이트와 관련이 있을 수 있느냐고 물으셨고, 저는 "네, 13버전입니다"라고 답했는데요(솔직히 이전에는 어떤 버전이었는지 몰랐습니다. 앱 재구축을 자주 하지 않아서 그랬습니다), 그러자 그쪽에서는 그게 문제가 아니라고 하시더군요… 그러면 왜 포스트그레SQL은 계속 “시작 중” 상태이고 디스커스가 진행되지 않는 건가요?

1개의 좋아요

안녕하세요 @Wander 님. 어떤 문제인지 정확히 알 수 없어서 postgres 업그레이드를 무작정 제안한 것입니다. 현재 postgres 13을 실행 중이라면, 10이나 12에서 업그레이드하는 데 막혀 있다는 것이 문제가 아닐 가능성이 높습니다. 따라서 postgres 자체에 문제가 있을 수는 있지만, postgres 13 업그레이드와 직접적인 관련은 없을 것으로 보입니다.

이 분야에 전문가가 아닌 분들에게 드리는 제 최선의 조언은 깨끗한 설치(Clean installation)를 진행한 후 가장 최근의 백업을 복원하는 것입니다.

더 구체적인 도움을 원하시고 예산이 있으시다면, 저에게 연락하시거나 Marketplace 채널에 게시물을 올리시면 됩니다.

Nginx Proxy Manager 사용 지침을 개선하는 데 주력할 계획입니다. 하지만 제 추측으로는, 이 복잡한 설정으로 전환을 시도하면서 문제가 드러나긴 했지만, 지침 자체의 오류 때문은 아닐 가능성이 높습니다. (정확히는 모르지만, 제 최선의 추측입니다.)

2개의 좋아요

제 버전은 다음과 같습니다. 거의 포기할 뻔했지만, @tophee 님이 제가 (!?) 작성한 포스트에 링크를 걸어주셨고, 그 덕분에 필요한 마법을 풀 수 있었습니다. 이제 Nginx Proxy Manager를 Discourse에 설정하는 것이 매우 간단해졌습니다. 이는 Run other websites on the same machine as Discourse - #396 와 유사하다고 생각합니다.

해당 지침에 따라 Nginx Proxy Manager 설치

SSL 및 Let’s Encrypt 템플릿 제거:

yml 파일에서 다음 줄들이 주석 처리되어 있거나 삭제되었는지 확인하세요:

## Lets Encrypt(https)를 추가하려면 다음 두 줄의 주석을 해제하세요
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"

Discourse가 npm-default 네트워크를 사용하도록 설정

Nginx Proxy Manager 설치 지침을 그대로 따를 경우, npm_default라는 이름의 Docker 네트워크가 생성됩니다.

이 스탠스를 yml 파일에 추가하세요. web_onlydata 컨테이너가 분리되어 있다면 각각에 이 내용을 추가해야 합니다. (mail-receiver 컨테이너는 테스트하지 않았습니다.) docker_args는 들여쓰지 않습니다.

docker_args: |
  --network npm_default

포트 노출 불필요

yml 파일에서 다음 줄들을 주석 처리하거나 제거하세요:

# expose:
#  - "80:80"   # http
#  - "443:443" # https

이제 컨테이너를 다시 빌드하고 Nginx Proxy Manager를 다음과 같이 설정할 수 있습니다:

image

두 번째 Discourse 사이트를 시작하는 간단하지만(반드시 권장되지는 않는) 방법은 다음과 같습니다:

cd /var/discourse/containers
cp app.yml othersite.yml
# somehow edit, at a minimum, the hostname in othersite.yml
./launcher rebuild othersite

그런 다음 위와 같이 NPM에 추가하되, app 대신 othersite를 사용하세요.

app.yml과 두 개의 web_only 스타일 컨테이너, 그리고 단일 data 컨테이너, 그리고 data 컨테이너의 복사본으로 redis 템플릿만 포함하는 별도의 othersite-redis 컨테이너로 이 방법을 테스트했습니다. (하지만 더 쉬운 해결책은 추가적인 redis를 web_only 컨테이너에 넣는 것입니다.)

2개의 좋아요

결국 고군분투 끝에 모든 것을 정상 작동하게 만들었습니다.

먼저 전제를 하나 말씀드리면, 저는 ‘구세대’ 개발자(1980년 첫 개발)이지만, 개발이나 관리를 위한 최선의 새로운 방식을 항상 찾아왔습니다. 그래서 2021년 현재, 예전 CP/M-DOS처럼 암호화된 옵션이 가득한 이상한 명령어를 작성하는 것은 정말 싫어합니다. 제 삶을 더 쉽고 명확하게 만들어 주는 인터페이스를 항상 찾아다니죠.

예를 들어, 저는 Portainer를 사용하여 컨테이너를 관리합니다. 이 도구를 사용하면 파일 시스템 여기저기를 뒤져서 백만 중 하나인 파일을 찾아 헤매지 않고도 모든 컨테이너를 즉시 시작/중지/편집/복제할 수 있습니다. 예를 들어 컨테이너 네트워크를 변경하려면 목록에서 하나를 선택하고 클릭하기만 하면 되고, 매개변수를 추가하거나 @tophee 님이 예시로 든 볼륨을 추가하는 것도 마찬가지입니다. 이 이유 때문에 저는 NPM을 시도해 보았습니다. Nginx 프록시를 '컨테이너화’하는 것을 선호하기 때문이기도 하고, 분명 몇 번의 클릭만으로 새로운 이상한 명령어와 옵션 세트를 기억하지 않으면서도, 내가 무엇을 하는지 명확히 이해하며 설정할 수 있을 것 같았기 때문입니다.

제 Discourse 컨테이너로 돌아와서, 다시 'discourse-setup’을 실행해야 했습니다. 모든 것이 순조롭게 진행되었고, ‘악당’ Postgres는 13버전이 설치되었으며, '취한 유니콘’은 없었습니다(죄송하지만 제 서버에서 '유니콘’이 달리는 상상을 하면 웃음이 나네요! :laughing:). 요약하자면 모든 것이 올바른 방향으로 진행되었습니다. 그 후 웹소켓으로 Discourse가 실행되도록 수정을 진행했는데, 이번에도 모든 것이 잘 작동했습니다. 다행히 이전 Discourse 설정 시 자동 백업이 이루어져 있었기 때문에 몇 번의 클릭만으로 모든 것을 복원할 수 있었습니다(Discourse를 더 많이 사용할수록 더 좋아집니다!).

NPM 설정은 여러 번 시도해야 했습니다. 처음에는 인증서 관련 문제가 있었但最终 결국 그것도 잘 작동하게 되었습니다.

저는 제 Wordpress 컨테이너를 가리키는 두 번째 프록시도 추가했습니다(네, 저는 모든 것을 '컨테이너화’합니다. 주요 패키지들이 관리 가능한 곳에 포함되어 있는 더 깔끔한 서버라는 아이디어를 좋아합니다). 이것도 잘 작동했습니다.

결국 제 서버(VPS)에는 이메일 서버(이것도 '컨테이너화’해 보았지만, 몇 주간의 힘든 싸움 끝에 포기했습니다), 그 이메일 서버를 가리키는 Discourse, 다른 컨테이너에서 실행되는 Wordpress, 그리고 이 둘을 관리하는 NPM이 있습니다. 모두 제 서버 위에 있으며, 배포나 이메일 등을 위해 다른(그리고 훨씬, 훨씬 더 비싼) 서비스에 의존하지 않습니다.

다음 단계는 '오래된 좋은 Phpbb’에서 수십만 개의 게시물을 가져오는 것입니다: 저의 다른 게시물들을 기대해 주세요! :grinning_face_with_smiling_eyes:

도와주신 @tophee 님과 @pfaffman 님께 큰 감사를 드립니다. 저처럼 비표준적인 방식으로 작업하는 사람들을 돕는 것이 얼마나 어려운 일인지 이해할 수 있습니다.

3개의 좋아요

웹소켓으로 작동하게 해서 다행입니다. 웹소켓 때문에 고생하고 계신 다른 분들을 위해, 위에서 @pfaffman 님이 제시한 웹소켓 없이 설정하는 방법을 참고하시기 바랍니다.

어떤 원인으로 문제가 발생했는지는 알 수 없지만, 디스코urs 관리에 상대적으로 익숙하지 않은 분들을 위해 명확히 할 필요가 있는 부분이 있다고 생각합니다. 기본적으로 외부 프록시 없이 설치된 경우 Let’s Encrypt 인증서가 어떻게 작동하는지, 그리고 NPM(nginx-proxy-manager)과 함께 사용할 때 어떻게 작동하는지를 이해해야 합니다. (왜 이를 외부 프록시라고 부르는지 궁금하시다면, 그 이유도 알아내셔야 합니다.)

저는 처음부터 외부 프록시를 수동으로 설정했고 Let’s Encrypt도 수동으로 설정했기 때문에, HTTPS가 자동으로 작동하도록 디스코urs와 NPM이 여러분을 위해 수행하는 모든 마법을 이해하고 있었습니다. 덕분에 디스코urs가 관리하던 인증서에서 NPM이 관리하는 인증서로 전환할 때 여러 함정을 피할 수 있었습니다.

메일 서버를 NPM 뒤에 두려는 이유가 잘 이해가 가지 않습니다…

1개의 좋아요

크리스토프, NPM 뒤에 두는 게 아니라 그냥 컨테이너에 올리는 겁니다. Zimbra를 시도해 봤는데 완전 엉망이었어요. 그래서 간단한 '컨테이너화’된 Postfix를 시도해 봤지만 이 역시 성공하지 못했습니다. 저는 당시 리눅스 사용 초기 단계였거든요(여전히 초보이지만, 적어도 몇 가지 관리 개념에 대해서는 점점 자신감이 붙어 가고 있습니다). 그래서 포기하고 서버에 직접 설치해 봤더니 큰 문제 없이 시작되더군요. 그래서 그 방향으로 진행했습니다. 제 메일 서버를 사용하도록 Discourse를 설정하는 것은 꽤 어려웠지만요. 하지만 지금은 모든 것이 정상적으로 작동하는 것 같습니다.

2개의 좋아요

설치 단계까지는 괜찮아 보였는데, npm이 discourse 호스트와 통신하는 부분에서 막혔습니다. npm의 compose 파일에서 mySQL 호스트로 데이터 컨테이너의 IP를 설정하라고 하셨는데,

 environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"

이 부분을 데이터 컨테이너로 변경하면 연결 거부(connection refused) 오류가 발생합니다.

connect ECONNREFUSED 172.17.0.2:3306 <-- npm이 discourse 네트워크(network_mode: bridge)에 있을 때 발생하는 오류.
getaddrinfo ENOTFOUND db <-- mySQL이 npm compose 파일에서 "db"로 정의되어 있을 때 발생하는 오류.

3단계가 정상적으로 작동하도록 도와줄 수 있는 조언이 있을까요?

1개의 좋아요