【 前提 】
docker-compose を使用したウェブサイトを作成しています。
SSL 対応をしようとしていますが、https での接続ができず困っています。
諸事情でコンテナを使用して構成する必要があります。
ホストOS側で確認したところ、どうやら443 番ポートは listen 状態にはなっているようです。
以下のような構成で、 SSL 化を行う方法をご存じの方がいらっしゃいましたら
ご教示頂けますと幸いです。
Let's Encrypt の証明書はホスト側の OS で cron 等を用いて定期的に更新し、NGINX を再起動することで対応しようと考え、現在以下の構成となっています。
< ディレクトリ構成 >
├── django
│ ├── Dockerfile
│ └── requirements.txt
├── docker-compose.yml
├── mysql
│ └── .env
├── nginx
│ ├── certs
│ │ └──
│ ├── nginx.conf
│ └── uwsgi_params
├── sql
│ └── init.sql
├── src
│ └── django のプロジェクトディレクトリ
└── static(静的ファイルを集めています)
./nginx/certs ディレクトリに certbot で取得した証明書をコピーしています。
< サーバーの構成 >
- 物理サーバ: Amazon lightsail
- WEBサーバ: NGINX ( docker イメージ nginx:latest) → 2022 年 5 月 6 日時点で 1.21.6 を使用しています。
- アプリケーション・サーバ: uWSGI ( docker イメージ python:3.9 からインストールしたもの)
- フレームワーク: Django ( docker イメージ python:3.9 からインストールしたもの)
- データベース: MySQL ( docker イメージ mysql:8.0)
実現したいこと
サーバ証明書に Let's Encrypt を使用して SSL 対応を行いたい。
発生している問題(ホスト OS 側のシェルにて確認)
以下 6 点のコマンド入力を行い、確認作業を行いました。
全てホスト OS 側のシェルで実行しています。
bash
# input 1 curl -i http://ドメイン名前 # output 1 HTTP/1.1 200 OK Server: nginx Date: Fri, 06 May 2022 11:35:16 GMT Content-Type: text/html; charset=utf-8 Content-Length: 3744 Connection: keep-alive X-Frame-Options: DENY Vary: Cookie X-Content-Type-Options: nosniff Referrer-Policy: same-origin Cross-Origin-Opener-Policy: same-origin
↑ html の内容もきちんと返って来ます。
bash
# input 2 curl -i https://ドメイン名 # output 2 curl: (28) Failed to connect to ドメイン名 port 443: Connection timed out
↑ タイムアウトになってしまいます。
bash
# input 3 sudo lsof -i -P # output 3 (dockerの出力部分以外、長いのでカットしています。) ~~~~~~ docker-pr 74639 root 4u IPv4 538863 0t0 TCP *:3306 (LISTEN) docker-pr 74644 root 4u IPv6 538872 0t0 TCP *:3306 (LISTEN) docker-pr 74858 root 4u IPv4 539960 0t0 TCP *:443 (LISTEN) docker-pr 74862 root 4u IPv6 539967 0t0 TCP *:443 (LISTEN) docker-pr 74875 root 4u IPv4 540029 0t0 TCP *:80 (LISTEN) docker-pr 74880 root 4u IPv6 540036 0t0 TCP *:80 (LISTEN) ~~~~~~
↑ 443 ポートは listen になっています。
bash
# input 4 sudo docker logs NGINXのコンテナ名 # output 4 /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up curl を送ったIPアドレス - - [06/May/2022:11:35:16 +0000] "GET / HTTP/1.1" 200 3744 "-" "curl/7.68.0" "-"
なお、この時点で http://ドメイン名 宛に GET リクエストを送信したものはログとして出力されますが、
https://ドメイン名 宛にリクエストを送ったものについてはログの出力がありません。
bash
# 実行時の日付は日本時間で 2022 年 05 月 06 日です。 # input 5 sudo openssl x509 -in /etc/letsencrypt/live/ドメイン名/fullchain.pem -noout -dates # output 5 notBefore=May 6 04:57:17 2022 GMT notAfter=Aug 4 04:57:16 2022 GMT
有効期限は残っています。
コピー後のディレクトリの中身、およびコンテナ内のマウントしたディレクトリも確認しました。
しかし、権限、所有者の情報が変わった様子もありません。
bash
# docker-compose.yml で django コンテナの /tmp/mylog.log にログ出力するようにしています。 # input 6 sudo docker-compose exec django cat /tmp/mylog.log # output 6 *** Starting uWSGI 2.0.20 (64bit) on [Fri May 6 11:34:57 2022] *** compiled with version: 10.2.1 20210110 on 06 May 2022 08:42:41 os: Linux-5.4.0-1018-aws #18-Ubuntu SMP Wed Jun 24 01:15:00 UTC 2020 nodename: adbb29352c07 machine: x86_64 clock source: unix pcre jit disabled detected number of CPU cores: 1 current working directory: /code detected binary path: /usr/local/bin/uwsgi uWSGI running as root, you can use --uid/--gid/--chroot options ~~~途中略~~~ *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 1) spawned uWSGI worker 1 (pid: 7, cores: 1) Python auto-reloader enabled [pid: 7|app: 0|req: 1/1] IPアドレス () {32 vars in 349 bytes} [Fri May 6 20:35:16 2022] GET / => generated 3744 bytes in 360 msecs (HTTP/1.1 200) 7 headers in 222 bytes (1 switches on core 0) ~~~
httpのログ出力は見つかりました。
該当のソースコード
以下3点を記載します。
①./docker-compose.yml
②./nginx/nginx.conf
③./nginx/uwsgi_params
①./docker-compose.yml
docker
# ./docker-compose.yml version: '3' services: nginx: image: nginx:latest ports: - '80:80' - '443:443' volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params - ./static:/static # ---------------------------------------------------------------- # 事前にホスト OS の /etc/letsencrypt/live/ドメイン名 のディレクトリを # docker-compose を行うディレクトリ(./enginx/certs)にコピーしています。 # # そして、ホスト OS の nginx/certs ディレクトリを nginx コンテナの # /etc/nginx/certs にマウントしています。 # ---------------------------------------------------------------- - ./nginx/certs:/etc/nginx/certs depends_on: - django mysql: image: mysql:8.0 command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb-buffer-pool-size=16M ports: - "3306:3306" env_file: - ./mysql/.env volumes: - ./mysql:/var/lib/mysql - ./sql:/docker-entrypoint-initdb.d django: build: ./django command: uwsgi --socket :8001 --module mysite.wsgi --py-autoreload 1 --logto /tmp/mylog.log volumes: - ./src:/code - ./static:/static expose: - "8001" env_file: - ./django/.env depends_on: - mysql
②./nginx/nginx.conf
nginx.conf
# ./nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; upstream django_8001 { ip_hash; server django:8001; } server { listen 80; listen 443 ssl; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; server_name ドメイン名; charset utf-8; location /static/ { autoindex on; alias /static/; } location / { uwsgi_pass django_8001; include /etc/nginx/uwsgi_params; } } server_tokens off; }
③./nginx/uwsgi_params
uwsgi_params
# ./nginx/uwsgi_params uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name;
補足情報(FW/ツールのバージョンなど)
- 物理サーバ: Amazon Lightsail (Ubuntu 20.04)
- WEBサーバ: NGINX ( docker イメージ nginx:latest) → 2022 年 5 月 6 日時点で 1.21.6 を使用しています。
- アプリケーション・サーバ: uWSGI ( docker イメージ python:3.9 からインストールしたもの)
- フレームワーク: Django ( docker イメージ python:3.9 からインストールしたもの)
- データベース: MySQL ( docker イメージ mysql:8.0)
さいごに
拙い質問文となってしまい恐縮ですが、どなたか知恵をお貸し頂けますと幸甚です。
構成自体を変えた方がいい、このコンテナ使った方がいい or やめた方がいい 等
どんな意見でもご教示頂けると、とても嬉しいです。
どうぞ宜しくお願い致します。
まだ回答がついていません
会員登録して回答してみよう