Discourseとjwilder / nginx proxy&acme-companionの連携

みなさん、こんにちは。

数時間この問題に詰まっており、解決策が見つからないため、お手伝いをお願いしたく思います。

複数のコンテナで Web サービスをホストしているため、正しいコンテナへトラフィックをプロキシするために独自の Nginx をホストする必要があります。(Discourse を別のサーバーに移行することもできますが、これは最終手段です。)

現在の設定は以下の通りです:

この構成がどのように連携するかを示す良い図は、以下のページにあります:

以下のチュートリアルを利用しましたが、まだ成功していません。

  1. How to Install Multiple Discourse Forums on the Same Server
  2. Use Nginx-Proxy and LetsEncrypt Companion to Host Multiple Websites - Singular Aspect

過去に発見した Discourse のスレッド(2 年以上前)には以下があります:

私の Discourse の app.yml には以下が含まれています(ドメインとメールは伏せ字にしています):

docker_args:
  - "--net nginx-proxy"
  VIRTUAL_HOST: {domain}
  VIRTUAL_PORT: 80
  LETSENCRYPT_HOST: {domain}
  LETSENCRYPT_EMAIL: {email address}

以下の例では、公開ポートの記述をコメントアウトしています。複数のバリエーションを試しましたが、さまざまな投稿を見ました。例えば、この投稿のコメント:Discourse with jwilder/nginx-proxy howtos? や、他の投稿ではコメントアウトされておらず、Docker 変数で VIRTUAL_PORT として指定されているものもあります。この部分について少し混乱しています。

#expose:
#  - "80"

すべてのコンテナは同じネットワーク上にあります。例:
docker network inspect nginx-proxy

[
    {
        "Name": "nginx-proxy",
        "Id": "d2715f513771f002711521838340b879bb9106ef50118fb29be6b0cf2d5f25e7",
        "Created": "2022-02-01T20:32:10.021632263Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0b6296ccf7e31b67caf0d31ccc5485e30bd6f1746ceee7e6ce29617b892178cd": {
                "Name": "app",
                "EndpointID": "1cea3782ef9dea3cf0066add142121f569682c74ff8faa6b19813035eff8998c",
                "MacAddress": "02:72:f8:ee:03:32",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "975ea34d56a65b722aa5e83b99f71039fd687b1aee4e8d4df3cb192b1d35c043": {
                "Name": "nginx-proxy",
                "EndpointID": "bc7a0b4602614be516ee0ceb1c4edf923b91bf7a6528c013157180a98d435807",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "e299a734584a765dbc10102a5bc9b0d0c98ac6096b6ae75dd1169105893e40af": {
                "Name": "letsencrypt-proxy",
                "EndpointID": "6b3588359ac4eec02618d3a7438d2750cb6e1c3d1cb6e1a8ce6378c568358a50",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

証明書は正常に生成されています(以下参照)が、現在 502 エラーが発生しています。

Discourse コンテナの Nginx ログを確認してデバッグを試みましたが、ログファイルは生成されるものの、内容は空のままです:

root@ubuntu-vm-dev-app:/var/log/nginx# ls -lt
total 692
-rw-r--r-- 1 www-data www-data      0 Feb  4 07:23 access.letsencrypt.log
-rw-r--r-- 1 www-data www-data      0 Feb  4 07:23 error.letsencrypt.log
-rw-r--r-- 1 www-data www-data      0 Feb  4 07:23 error.log
-rw-r--r-- 1 www-data www-data      0 Feb  1 23:04 access.log
-rw-r--r-- 1 www-data www-data 700917 Jan 31 23:48 error.log.1
-rw-r--r-- 1 www-data www-data      0 Jan 31 22:55 access.letsencrypt.log.1
-rw-r--r-- 1 www-data www-data      0 Jan 31 22:55 error.letsencrypt.log.1

Docker ログには、現時点で最も有用と思われる情報が表示されています(パブリック IP とドメイン名は伏せ字にしています):

nginx-proxy          | nginx.1     | 2022/02/04 08:35:04 [error] 206#206: *93 connect() failed (111: Connection refused) while connecting to upstream, client: {REDACTED_PUBLIC_IP}, server: {MY_FORUM_DOMAIN}.com, request: "GET / HTTP/2.0", upstream: "http://172.18.0.4:80/", host: "{MY_FORUM_DOMAIN}.com"
nginx-proxy          | nginx.1     | {MY_FORUM_DOMAIN}.com {REDACTED_PUBLIC_IP} - - [04/Feb/2022:08:35:04 +0000] "GET / HTTP/2.0" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" "172.18.0.4:80"
nginx-proxy          | nginx.1     | 2022/02/04 08:35:06 [error] 206#206: *93 connect() failed (111: Connection refused) while connecting to upstream, client:{REDACTED_PUBLIC_IP}, server: {MY_FORUM_DOMAIN}.com, request: "GET /service-worker.js HTTP/2.0", upstream: "http://172.18.0.4:80/service-worker.js", host: "{MY_FORUM_DOMAIN}.com", referrer: "https://{MY_FORUM_DOMAIN}.com/service-worker.js"
nginx-proxy          | nginx.1     | {MY_FORUM_DOMAIN}.com {REDACTED_PUBLIC_IP} - - [04/Feb/2022:08:35:06 +0000] "GET /service-worker.js HTTP/2.0" 502 559 "https://{MY_FORUM_DOMAIN}.com/service-worker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" "172.18.0.4:80"
nginx-proxy          | nginx.1     | 2022/02/04 08:35:19 [error] 206#206: *93 connect() failed (111: Connection refused) while connecting to upstream, client:{REDACTED_PUBLIC_IP}, server: {MY_FORUM_DOMAIN}.com, request: "GET /service-worker.js HTTP/2.0", upstream: "http://172.18.0.4:80/service-worker.js", host: "{MY_FORUM_DOMAIN}.com", referrer: "https://{MY_FORUM_DOMAIN}.com/service-worker.js"
nginx-proxy          | nginx.1     | {MY_FORUM_DOMAIN}.com{REDACTED_PUBLIC_IP} - - [04/Feb/2022:08:35:19 +0000] "GET /service-worker.js HTTP/2.0" 502 559 "https://{MY_FORUM_DOMAIN}.com/service-worker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" "172.18.0.4:80"

コンテナ/app.yml ファイルで指定したポートを介して Discourse コンテナへの通信は問題ないことを確認しました。例えば、ブラウザからリクエストを行う前に、Discourse コンテナにログインしてポート 80 で netcat を実行しました。

root@ubuntu-vm-dev-app:/var/log/nginx# netcat -lnvp 80
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::80
Ncat: Listening on 0.0.0.0:80
Ncat: Connection from 172.18.0.2.
Ncat: Connection from 172.18.0.2:48776.
GET / HTTP/1.1
Host: {REDACTED_HOST}.com
Connection: close
X-Real-IP: {REDACTED_PUBLIC-IP}
X-Forwarded-For: {REDACTED_PUBLIC-IP}
X-Forwarded-Proto: https
X-Forwarded-Ssl: on
X-Forwarded-Port: 443
cache-control: max-age=0
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site: none
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cookie: _t=azl2WkpyN1hgbENOd3pyZ1d6V3ZXUT....

root@ubuntu-vm-dev-app:/var/log/nginx# 

nginx-proxy コンテナから生成された Nginx 設定のサンプルは以下の通りです:

root@975ea34d56a6:/etc/nginx/conf.d# cat default.conf 
# nginx-proxy version : 0.10.0-11-g42c8b0c
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
  default $http_x_forwarded_port;
  ''      $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
  default upgrade;
  '' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
# Set appropriate X-Forwarded-Ssl header based on $proxy_x_forwarded_proto
map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
  default off;
  https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent" '
                 '"$upstream_addr"';
access_log off;
		ssl_protocols TLSv1.2 TLSv1.3;
		ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
		ssl_prefer_server_ciphers off;
resolver 127.0.0.11;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
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 $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
	server_name _; # This is just an invalid value which will never trigger on a real hostname.
	server_tokens off;
	listen 80;
	access_log /var/log/nginx/access.log vhost;
	return 503;
}
server {
	server_name _; # This is just an invalid value which will never trigger on a real hostname.
	server_tokens off;
	listen 443 ssl http2;
	access_log /var/log/nginx/access.log vhost;
	return 503;
	ssl_session_cache shared:SSL:50m;
	ssl_session_tickets off;
	ssl_certificate /etc/nginx/certs/default.crt;
	ssl_certificate_key /etc/nginx/certs/default.key;
}
# {REDACTED_DOMAIN}.com
upstream {REDACTED_DOMAIN}.com {
	## Can be connected with "nginx-proxy" network
	# app
	server 172.18.0.4:80;
}
server {
	server_name {REDACTED_DOMAIN}.com;
	listen 80 ;
	access_log /var/log/nginx/access.log vhost;
	# Do not HTTPS redirect Let'sEncrypt ACME challenge
	location ^~ /.well-known/acme-challenge/ {
		auth_basic off;
		auth_request off;
		allow all;
		root /usr/share/nginx/html;
		try_files $uri =404;
		break;
	}
	location / {
		return 301 https://$host$request_uri;
	}
}
server {
	server_name {REDACTED_DOMAIN}.com;
	listen 443 ssl http2 ;
	access_log /var/log/nginx/access.log vhost;
	ssl_session_timeout 5m;
	ssl_session_cache shared:SSL:50m;
	ssl_session_tickets off;
	ssl_certificate /etc/nginx/certs/{REDACTED_DOMAIN}.com.crt;
	ssl_certificate_key /etc/nginx/certs/{REDACTED_DOMAIN}.com.key;
	ssl_dhparam /etc/nginx/certs/{REDACTED_DOMAIN}.com.dhparam.pem;
	ssl_stapling on;
	ssl_stapling_verify on;
	ssl_trusted_certificate /etc/nginx/certs/{REDACTED_DOMAIN}.com.chain.pem;
	add_header Strict-Transport-Security "max-age=31536000" always;
	include /etc/nginx/vhost.d/default;
	location / {
		proxy_pass http://{REDACTED_DOMAIN}.com;
	}
}

この設定が動作したことがある方はいますか?あるいは、私が受け取っている 502 エラーをデバッグする方法についてご存知ですか?このエラーは複数の要因が考えられますが、Discourse や私と似た設定で同様の問題に直面した方がいれば、その解決策が役立つかもしれません。

よろしくお願いいたします。

複数のプロキシサーバーが関与する Discourse のインストールをデバッグする方法を確認してください。
サブフォルダーの Discourse インストールをデバッグする方法

プロキシ構成は機能しているようですが、Discourse が機能していません。データベースにアクセスできないのではないでしょうか?

次のような場所を確認できます。

/var/discourse/shared/standalone/logs/rails/production.log

"GET /server-worker.js HTTP/2.0" **502** […]
これは静的ファイルを取得する際の502エラーのように見えます。プロキシが機能していないようです。

ああ。それはあなたのプロキシnginxからであり、Discourseのnginxからではありません。すみません。

あなたが説明したことの中に明らかに間違っているところは見当たりませんが、たくさんの細かい部分があります。Discourseが間違ったDockerネットワーク上にあるのかもしれません(しかし、あなたはそれを解決しようとしたように見えました)。

過去数ヶ月間、あなたが言っていることをまさにやろうと思っていましたが、人々は他のことをするように私にお金を払い続けています。おそらく来週か再来週にはできるかもしれませんが、それは数ヶ月前から言っています。

[…] "https://… […]

外部プロキシを設定して、ディスコースNginxのhttp-urlに接続するようにしてください。httpsではなく。

@rrit @pfaffman さん、回答とご提案をありがとうございます。

今日ももう一度取り組んでみました。時間はかかりましたが、ついに動作するようになりました。他の皆様の参考になればと思い、私の設定とデバッグ方法をいくつか共有します。

: nginx、acme-companion、discourse の各コンテナがどのように連携して、証明書の自動化とリバースプロキシを実現しているかについては、最初の投稿をご覧ください。

デバッグ方法に興味がなければ、最後の方にある私の解決策(docker-compose ファイルと app.yml ファイル)までお進みください

私の設定から特定した主なエラー

私が直面していたエラーの一つは、複数のチュートリアルを盲目的に追随した結果、設定がごちゃごちゃになっていたことに起因する私のミスでした。最初の投稿をご覧いただければわかる通り、私は「netcat -lnvp 80」コマンドを使って discourse アプリコンテナのポート 80 でリッスンできていました。しかし、リバースプロキシが discourse コンテナのリスニングポートにトラフィックを送信したい場合、そのポートは netcat でリッスンできる状態であってはなりません。それは**「使用中」**であるべきです。

問題の原因は、以下のテンプレートを使用していたことにありました:web.socketed.template.yml
これにより、discourse コンテナ内の nginx はTCP/IP ポートではなくUnix ソケットを利用していました。テンプレートの例と、それによって nginx に適用される設定は以下の通りです。

ubuntu@ubuntu-vm-dev:/var/discourse/templates$ cat web.socketed.template.yml 
run:
  - file:
     path: /etc/runit/1.d/remove-old-socket
     chmod: "+x"
     contents: |
        #!/bin/bash
        rm -f /shared/nginx.http*.sock
  - file:
     path: /etc/runit/3.d/remove-old-socket
     chmod: "+x"
     contents: |
        #!/bin/bash
        rm -rf /shared/nginx.http*.sock
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 80;/
     to: |
       listen unix:/shared/nginx.http.sock;
       set_real_ip_from unix:;
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 443 ssl http2;/
     to: |
       listen unix:/shared/nginx.https.sock ssl http2;
       set_real_ip_from unix:;

問題は、nginx-proxy コンテナ内のnginxdiscourse コンテナへトラフィックを正常に転送していたものの、共有 Unix ソケットではなくポート 80へ転送していたことにありました。

nginx-proxy のドキュメントをご覧いただければわかりますが、バーチャルポートが指定されていない限り、デフォルトのポートはポート 80となります。
画像添付元:GitHub - nginx-proxy/nginx-proxy: Automated Nginx Reverse Proxy for Docker · GitHub

nginx-proxy コンテナの設定をあれこれ弄る代わりに、私はweb.socketed.template.ymlを削除しました。その後、discourse コンテナが公開していたポートも不要になったため削除しました。discourse コンテナが正しい Docker ネットワーク(nginx-proxy および acme-companion と同じネットワーク)にあれば、問題なく動作するはずです。

デバッグのヒント

1. ネットワークのデバッグ

1.1 Docker ネットワーク
ネットワークが正常に機能しているかを確認する例を以下に示します(Docker アプリと nginx/acme コンテナを起動した後)。

ubuntu@ubuntu-vm-dev:/var/discourse$ docker network inspect nginx-proxy
 {
        "Name": "nginx-proxy",
        "Id": "d2715f513771f002711521838340b879bb9106ef50118fb29be6b0cf2d5f25e7",
        "Created": "2022-02-01T20:32:10.021632263Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "205772214b77a6bf49a76d082eef216aa5fc4ca15a39ae2c8fefc0b3eeb61e00": {
                "Name": "nginx-test_webserver2_1",
                "EndpointID": "ee3096663b1a90443906652ff3a192243fa1f60081e5bbee190a23f1d23393f7",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "3050831bf600ae02c18e5045549267b583ec732d6f1550f869ab651dfc7d8dca": {
                "Name": "nginx-test_nginx_1",
                "EndpointID": "a7f95f2a7589ca3823da01b9d28244bbd81815d6f5cc1f2f89804a488ef2148d",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "696ce8d129a62ce37ae8373ed4f603fd5d731f5f29166bd6fa889631ef0ae606": {
                "Name": "nginx-proxy",
                "EndpointID": "99d90539668b97652ffca7e3301aa83c40fe7b31ca8eea2a8a4d9bf7afe19ac0",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "d3faf6489ca6617dceda4f2907ee6c055a1d81e3590c3eab2768601dfc0b60d7": {
                "Name": "app",
                "EndpointID": "aed6bfcc61e439e2206615a1569355c529a63a21c356e54da378f630d44fd3bc",
                "MacAddress": "02:72:f8:ee:03:32",
                "IPv4Address": "172.18.0.6/16",
                "IPv6Address": ""
            },
            "e04f2125001d5f346255312f10cdd0ab176388cddb0819b0022c5988a23303eb": {
                "Name": "letsencrypt-proxy",
                "EndpointID": "0088bcd942aed41c9351b935ed7b115e49046cc3a8308ca5a8d3828a194ecfee",
                "MacAddress": "02:42:ac:12:00:05",
                "IPv4Address": "172.18.0.5/16",
                "IPv6Address": ""
            }
        },

: ネットワーク名をお使いのものに変更してください(「nginx-proxy」を使用している場合を除く)。

これにより、nginx-proxy コンテナの設定内で Docker ネットワークからこれらの IP アドレスが表示されるはずです。これは以下のようにしてアクセスし、確認できます。

ubuntu@ubuntu-vm-dev:/var/discourse$ docker exec -it nginx-proxy /bin/bash
root@696ce8d129a6:/app# cd /etc/nginx/conf.d/
root@696ce8d129a6:/etc/nginx/conf.d# cat default.conf
... NGINX 設定がここに表示されます ... 

ネットワーク通信が正常かどうかをテストするには、アップストリームロケーションのいずれかに指定された IP アドレスと対話します。例えば、nginx-proxy コンテナから、割り当てられた Docker ネットワークの IP アドレスを介して discourse コンテナと対話してみてください。

例:私の設定ファイルには以下が含まれています。

upstream my_forum_domain.com {
	## Can be connected with "nginx-proxy" network
	# app
	server 172.18.0.6:80;
}

私の discourse コンテナのアップストリーム IP が172.18.0.6であるため、discourse コンテナに対して curl を実行すると成功した出力が表示されるはずです。

root@696ce8d129a6:/etc/nginx/conf.d# curl 172.18.0.6
... Curl リクエストの出力 ... 

1.2. ネットワークトラブルシューティングツール(Netstat, lsof, netcat)
以下のツール「netstat」、「lsof」、「netcat」はトラブルシューティングに役立ちます。discourse コンテナにはこれらのツールが最初からインストールされていないため、以下のようにしてインストールしてください。

root@ubuntu-vm-dev-app:/# apt-get install lsof
root@ubuntu-vm-dev-app:/# apt-get install net-tools
root@ubuntu-vm-dev-app:/# apt-get install netcat

lsof
lsof を使用すると、nginx プロセスがポート 80 でリッスンしていることが確認できるはずです。

root@ubuntu-vm-dev-app:/# lsof -i :80
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx    55 root    6u  IPv4 254317      0t0  TCP *:http (LISTEN)
root@ubuntu-vm-dev-app:/# 

netstat
以下の netstat コマンドも、正しいプロセスやポートが使用されているかを確認するのに役立ちます。例えば、HTTP(80)、redis(6379)、PostgreSQL(5432)、Unicorn(3000)などのポートを確認できます。

root@ubuntu-vm-dev-app:/# netstat -peanut
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      0          254317     55/nginx: master pr 
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      1000       255560     -                   
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      105        255137     -                   
tcp        0      0 127.0.0.11:46697        0.0.0.0:*               LISTEN      0          254194     -                   
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      106        255126     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37600         ESTABLISHED 106        255583     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37608         ESTABLISHED 106        255610     -                   
tcp        0      0 127.0.0.1:37632         127.0.0.1:6379          ESTABLISHED 1000       254766     -                   
tcp        0      0 127.0.0.1:37626         127.0.0.1:6379          ESTABLISHED 1000       254745     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37634         ESTABLISHED 106        254773     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37650         ESTABLISHED 106        255950     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37668         ESTABLISHED 106        255965     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37612         ESTABLISHED 106        255618     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37602         ESTABLISHED 106        255585     -                   
tcp        0      0 127.0.0.1:37624         127.0.0.1:6379          ESTABLISHED 1000       254739     -                   
tcp        0      0 127.0.0.1:37594         127.0.0.1:6379          ESTABLISHED 1000       255578     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37594         ESTABLISHED 106        254527     -                   
tcp        0      0 127.0.0.1:37618         127.0.0.1:6379          ESTABLISHED 1000       255635     -                   
tcp        0      0 127.0.0.1:37586         127.0.0.1:6379          ESTABLISHED 1000       255168     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37622         ESTABLISHED 106        255645     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37624         ESTABLISHED 106        254740     -                   
tcp        0      0 127.0.0.1:37600         127.0.0.1:6379          ESTABLISHED 1000       254537     -                   
tcp        0      0 127.0.0.1:37610         127.0.0.1:6379          ESTABLISHED 1000       254563     -                   
tcp        0      0 127.0.0.1:3000          127.0.0.1:36678         TIME_WAIT   0          0          -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37620         ESTABLISHED 106        255642     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37636         ESTABLISHED 106        254779     -                   
tcp        0      0 127.0.0.1:37628         127.0.0.1:6379          ESTABLISHED 1000       254751     -                   
tcp        0      0 127.0.0.1:37590         127.0.0.1:6379          ESTABLISHED 1000       254361     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37626         ESTABLISHED 106        254746     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37586         ESTABLISHED 106        255169     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37590         ESTABLISHED 106        255173     -                   
tcp        0      0 127.0.0.1:37668         127.0.0.1:6379          ESTABLISHED 1000       254849     -                   
tcp        0      0 127.0.0.1:37622         127.0.0.1:6379          ESTABLISHED 1000       254582     -                   
tcp        0      0 127.0.0.1:37634         127.0.0.1:6379          ESTABLISHED 1000       254772     -                   
tcp        0      0 127.0.0.1:37602         127.0.0.1:6379          ESTABLISHED 1000       254541     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37630         ESTABLISHED 106        254760     -                   
tcp        0      0 127.0.0.1:37612         127.0.0.1:6379          ESTABLISHED 1000       255617     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37628         ESTABLISHED 106        254752     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37610         ESTABLISHED 106        255612     -                   
tcp        0      0 127.0.0.1:3000          127.0.0.1:36682         TIME_WAIT   0          0          -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37632         ESTABLISHED 106        254767     -                   
tcp        0      0 127.0.0.1:37650         127.0.0.1:6379          ESTABLISHED 1000       254826     -                   
tcp        0      0 127.0.0.1:37608         127.0.0.1:6379          ESTABLISHED 1000       254559     -                   
tcp        0      0 127.0.0.1:37620         127.0.0.1:6379          ESTABLISHED 1000       255641     -                   
tcp        0      0 127.0.0.1:37636         127.0.0.1:6379          ESTABLISHED 1000       254778     -                   
tcp        0      0 127.0.0.1:37630         127.0.0.1:6379          ESTABLISHED 1000       254759     -                   
tcp        0      0 127.0.0.1:6379          127.0.0.1:37618         ESTABLISHED 106        255636     -                   
tcp6       0      0 :::5432                 :::*                    LISTEN      105        255138     -                   
tcp6       0      0 :::6379                 :::*                    LISTEN      106        255127     -                   
udp        0      0 127.0.0.1:54569         127.0.0.1:54569         ESTABLISHED 105        255145     -                   
udp        0      0 127.0.0.11:44019        0.0.0.0:*                           0          254193     -                   
root@ubuntu-vm-dev-app:/# 

nc
nc を使用して、リスニングポートが正しく設定/リッスンされているかを確認します(これは netstat でも表示されるはずです)。

root@ubuntu-vm-dev-app:/# nc -zv localhost 1-10000 2>&1 | grep -i  succeeded 
Connection to localhost (127.0.0.1) 80 port [tcp/http] succeeded!
Connection to localhost (127.0.0.1) 3000 port [tcp/*] succeeded!
Connection to localhost (127.0.0.1) 5432 port [tcp/postgresql] succeeded!
Connection to localhost (127.0.0.1) 6379 port [tcp/redis] succeeded!

1.3 プロセス
もう一つ便利なコマンド:ps aux

root@ubuntu-vm-dev-app:/# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0   6772  3252 pts/0    Ss+  15:20   0:00 /bin/bash /sbin/boot
root          41  0.0  0.0   2340   636 pts/0    S+   15:20   0:00 /usr/bin/runsvdir -P /etc/service
root          42  0.0  0.0   2188   696 ?        Ss   15:20   0:00 runsv cron
root          43  0.0  0.0   2188   636 ?        Ss   15:20   0:00 runsv rsyslog
root          44  0.0  0.0   2188   632 ?        Ss   15:20   0:00 runsv nginx
root          45  0.0  0.0   2188   636 ?        Ss   15:20   0:00 runsv postgres
root          46  0.0  0.0   2188   636 ?        Ss   15:20   0:00 runsv redis
root          47  0.0  0.0   2188   636 ?        Ss   15:20   0:00 runsv unicorn
root          48  0.0  0.0 151068  3868 ?        Sl   15:20   0:00 rsyslogd -n
root          49  0.0  0.0   2336   700 ?        S    15:20   0:00 svlogd /var/log/redis
root          50  0.0  0.0   6620  2768 ?        S    15:20   0:00 cron -f
redis         51  0.1  0.0  54180  5828 ?        Sl   15:20   0:02 /usr/bin/redis-server *:6379
root          52  0.0  0.0   2336   636 ?        S    15:20   0:00 svlogd /var/log/postgres
postgres      53  0.0  0.3 213196 28676 ?        S    15:20   0:00 /usr/lib/postgresql/13/bin/postmaster -D /etc/postgresql/13/main
discour+      54  0.0  0.0  15256  3924 ?        S    15:20   0:00 /bin/bash config/unicorn_launcher -E production -c config/unicorn.conf.rb
root          55  0.0  0.0  21280  7128 ?        S    15:20   0:00 nginx: master process /usr/sbin/nginx
www-data      69  0.0  0.0  22156  5004 ?        S    15:20   0:00 nginx: worker process
www-data      70  0.0  0.0  22124  4524 ?        S    15:20   0:00 nginx: worker process
www-data      71  0.0  0.0  21656  3768 ?        S    15:20   0:00 nginx: cache manager process
postgres      75  0.0  0.0 213296  6344 ?        Ss   15:20   0:00 postgres: 13/main: checkpointer 
postgres      76  0.0  0.0 213196  5896 ?        Ss   15:20   0:00 postgres: 13/main: background writer 
postgres      77  0.0  0.1 213196 10028 ?        Ss   15:20   0:00 postgres: 13/main: walwriter 
postgres      78  0.0  0.1 213736  8492 ?        Ss   15:20   0:00 postgres: 13/main: autovacuum launcher 
postgres      79  0.0  0.0  67960  5548 ?        Ss   15:20   0:00 postgres: 13/main: stats collector 
postgres      80  0.0  0.0 213752  6868 ?        Ss   15:20   0:00 postgres: 13/main: logical replication launcher 
discour+      81  0.4  3.1 436276 253572 ?       Sl   15:20   0:08 unicorn master -E production -c config/unicorn.conf.rb
postgres      99  0.0  0.3 220252 30612 ?        Ss   15:20   0:00 postgres: 13/main: discourse discourse [local] idle
discour+     116  0.6  3.7 831804 306708 ?       SNl  15:20   0:12 sidekiq 6.4.1 discourse [0 of 5 busy]
discour+     125  0.4  3.6 750356 297108 ?       Sl   15:20   0:07 unicorn worker[0] -E production -c config/unicorn.conf.rb
discour+     133  0.3  3.5 737812 289896 ?       Sl   15:20   0:07 unicorn worker[1] -E production -c config/unicorn.conf.rb
postgres     147  0.0  0.3 219372 27792 ?        Ss   15:20   0:00 postgres: 13/main: discourse discourse [local] idle
root        1858  0.0  0.0   7036  3828 pts/1    Ss   15:46   0:00 /bin/bash
postgres    1982  0.0  0.2 217012 24008 ?        Ss   15:47   0:00 postgres: 13/main: discourse discourse [local] idle
discour+    2236  0.0  0.0  13760  2216 ?        S    15:51   0:00 sleep 1
root        2237  0.0  0.0   9636  3292 pts/1    R+   15:51   0:00 ps aux
root@ubuntu-vm-dev-app:/# 

: 上記の出力を提供した理由は、あなたのデプロイメントと私のデプロイメントとの間の異常や違いを特定するのを助けるためです。これらではなく、リバースプロキシなしで動作するデプロイメントを自分で立ち上げ、以下のような項目を比較することもできます。

  • ネットワーク
  • プロセス
  • ファイルの作成/変更
  • ログ出力

私の動作する設定ファイル

1. ./launcher rebuild app 実行時のログ出力の例

+ /usr/bin/docker run --shm-size=512m -d --restart=always -e LANG=en_US.UTF-8 -e RAILS_ENV=production -e UNICORN_WORKERS=2 -e UNICORN_SIDEKIQS=1 -e RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 -e RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 -e RUBY_GC_HEAP_INIT_SLOTS=400000 -e RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 -e DISCOURSE_DB_SOCKET=/var/run/postgresql -e DISCOURSE_DB_HOST= -e DISCOURSE_DB_PORT= -e VIRTUAL_HOST={your_domain}.com -e LETSENCRYPT_HOST={your_domain}.com -e LETSENCRYPT_EMAIL=steve@{your_email_domain}.com -e LC_ALL=en_US.UTF-8 -e LANGUAGE=en_US.UTF-8 -e EMBER_CLI_PROD_ASSETS=1 -e DISCOURSE_HOSTNAME={your_domain}.com -e DISCOURSE_DEVELOPER_EMAILS=steve@{your_email_domain}.com -e DISCOURSE_SMTP_ADDRESS=smtp.mailgun.org -e DISCOURSE_SMTP_PORT=587 -e DISCOURSE_SMTP_USER_NAME=noreply@mail.{your_domain}.com -e DISCOURSE_SMTP_PASSWORD={your_password} -e DISCOURSE_SMTP_DOMAIN=mail.{your_domain}.com -e DISCOURSE_NOTIFICATION_EMAIL=noreply@mail.{your_domain}.com -h ubuntu-vm-dev-app -e DOCKER_HOST_IP=172.17.0.1 --name app -t -v /var/discourse/shared/standalone:/shared -v /var/discourse/shared/standalone/log/var-log:/var/log --mac-address 02:72:f8:ee:03:32 --network nginx-proxy local_discourse/app /sbin/boot
d3faf6489ca6617dceda4f2907ee6c055a1d81e3590c3eab2768601dfc0b60d7
ubuntu@ubuntu-vm-dev:/var/discourse$ 

2. 私の docker-compose ファイル

ubuntu@ubuntu-vm-dev:~/nginx-test$ cat docker-compose.yml 
version: '3'
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - letsencrypt-certs:/etc/nginx/certs
      - letsencrypt-vhost-d:/etc/nginx/vhost.d
      - letsencrypt-html:/usr/share/nginx/html
  letsencrypt-proxy:
      image: jrcs/letsencrypt-nginx-proxy-companion
      container_name: letsencrypt-proxy
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - letsencrypt-certs:/etc/nginx/certs
        - letsencrypt-vhost-d:/etc/nginx/vhost.d
        - letsencrypt-html:/usr/share/nginx/html
      environment:
        - DEFAULT_EMAIL=steve@{your_email_domain}.com
        - NGINX_PROXY_CONTAINER=nginx-proxy

networks:
  default:
    external:
      name: nginx-proxy
 
volumes:
  letsencrypt-certs:
  letsencrypt-vhost-d:
  letsencrypt-html:

3. 私の discourse app.yml ファイル

ubuntu@ubuntu-vm-dev:/var/discourse$ cat containers/app.yml 
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"

docker_args:
  - "--network nginx-proxy"

params:
  db_default_text_search_config: "pg_catalog.english"

  db_shared_buffers: "128MB"

env:
  VIRTUAL_HOST: {your_domain}.com
  LETSENCRYPT_HOST: example.com
  LETSENCRYPT_EMAIL: steve@{your_email_domain}.com
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8
  EMBER_CLI_PROD_ASSETS: 1
  # DISCOURSE_DEFAULT_LOCALE: en

  UNICORN_WORKERS: 2
  
  DISCOURSE_HOSTNAME: example.com
  
  DISCOURSE_DEVELOPER_EMAILS: 'steve@{email_domain}.com'

  DISCOURSE_SMTP_ADDRESS: smtp.mailgun.org
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: noreply@mail.{domain.com}.com
  DISCOURSE_SMTP_PASSWORD: "{password}"
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)
  DISCOURSE_SMTP_DOMAIN: mail.{domain}.com
  DISCOURSE_NOTIFICATION_EMAIL: noreply@mail.{domain}.com

volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-spoiler-alert.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-cakeday.git

run:
  - exec: echo "Beginning of custom commands"
  - exec: echo "End of custom commands"

上記が、同じようにこの問題で立ち往生している方のお役に立てば幸いです。