8
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Dockerでリバースプロキシ(nginx)構築+SSL対応

Last updated at Posted at 2021-03-31

はじめに

この記事は前回の記事の続きです。

前回の記事↓
自宅鯖のDocker内でWordPressを構築する - Qiita

記事一覧

対象とする読者

  • 今までの記事を見た方
  • リバースプロキシの知識が既にある方

前提

  • SSL証明書を取得しておいてください
    • LetsEncryptを使用しています。
    • /etc/letsencryptに証明書があることを前提に進めます。
/etc/letsencrypt
         ├── archive
         └── live # ←ここに最新の証明書が入ってます。

環境

  • 自宅サーバー
    • OS: Ubuntu 20.04.2 LTS
  • Docker
    • verison: 20.10.5, build 55c4c88
  • Docker Compose
    • version: 1.28.5, build c4eb3a1
    • ファイルフォーマット: 3.9

本題

今回はnginxを使ってリバースプロキシを構築します。
作業自体は簡単です。

事前準備

リバースプロキシでフォワーディングする先の各種サーバーを構築し、Dockerの仮想ネットワークを作成しておいてください。
今回はmy_networkの仮想ネットワークに接続させました。

ネットワーク図

ディレクトリ構造

WordPress側とリバースプロキシ側でdocker-compose.ymlを分けます。
※この構成を推奨してるわけではありません。ご自身の環境にあった構成にしてください。
** Composeファイルをひとつにしても全く問題ありません。**
** むしろ分けないほうが良いかもしれません。**

概念図_nginx-Directory.png

docker-compose.yml

docker-compose.yml
version: "3.9"

services:

  proxy:
    image: nginx:latest                             # 2020-03-25 latest=1.19.8
    volumes:
      - ./templates:/etc/nginx/templates            # nginxのconfファイルのテンプレート
      - ./conf/certpath.txt:/etc/nginx/certpath.txt # nginxでincludeさせるSSL関係の設定
      - /etc/letsencrypt:/etc/nginx/letsencrypt     # Lets Encryptの署名+秘密鍵
    restart: always
    ports:
      - "80:80"
      - "443:443"
    env_file:
      - ./conf/conf.env
    networks:
      - my_network

networks:
  my_network:
   name: my_network

各種オプションの説明はこちらに書いてますので参考にしてください。

templatesについて説明します。

templatesについて

Docker Hub | nginx
nginxの公式イメージ(ver.1.19.8)はテンプレートという便利機能がついてます。

訳:

nginxコンフィグでの環境変数の使用 (1.19からの新機能)

素のnginxだとコンフィグ内の環境変数をサポートしていませんが、このイメージにはnginxが起動する前に環境変数を抽出する関数があります。
例のdocker-compose.ymlを示します。

web:
 image: nginx
 volumes:
  - ./templates:/etc/nginx/templates
 ports:
  - "8080:80"
 environment:
  - NGINX_HOST=foobar.com
  - NGINX_PORT=80

デフォルトでは、この関数は/etc/nginx/templates/*.templateのテンプレートファイルを読み込み、envsubstの実行結果を/etc/nginx/conf.dに出力します。

templates/default.conf.templateに環境変数を参照したファイルを置くと次のようになります。

listen       ${NGINX_PORT};

出力結果/etc/nginx/conf.d/default.confの中身↓

listen       80;

要するに*.template拡張子で保存してあげれば環境変数読み取っていい感じにconf.dファイルに変換してくれます。

今回は./conf/conf.envファイルに環境変数を書き込んでそれを読ませてあげます。

docker-compose.yml(抜粋)
    env_file:
      - ./conf/conf.env
./conf/conf.env
NGINX_HOST=example.com
NGINX_PORT=443 ssl
NGINX_WP_HOST=blog.example.com
NGINX_WP_PORT=443 ssl

テンプレートファイルは次のとおりです。最小構成です。

./templates/default.conf.template
# HTTPをHTTPに飛ばす設定
server {
    listen 80;
    server_name ${NGINX_HOST};
    rewrite ^(.*)$ https://$host$1 permanent;
}


############## リバースプロキシ本体 ###################
server {
    listen       ${NGINX_PORT};
    server_name  ${NGINX_HOST};

    # アクセスログ 全部取る
    access_log  /var/log/nginx/host.access.log  main;

    # SSL設定
    include /etc/nginx/certpath.txt;

    # ロケーション設定
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }


}
./templates/wordpress.conf.template
server {
    listen       ${NGINX_WP_PORT};
    server_name  ${NGINX_WP_HOST};

    access_log  /var/log/nginx/host.access.log  main;

    location / {
        proxy_pass http://wordpress;  # コンテナ名を指定
        proxy_redirect   off;
        proxy_set_header Host               $host;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host   $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-Proto  https;
    }
}

wordpress.conf.template

        proxy_redirect   off;
        proxy_set_header Host               $host;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host   $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Real-IP          $remote_addr;

の記述は、これがないとWordPressのCSSが崩れるので必要です。
申し訳ないです…設定の意味は理解できていません…。
気が向いたら調べて追記します。

SSLについて

  • ./conf/certpath.txtにSSLの設定を書いてます。
    いずれ変わることもあるかなと思って別ファイルに書きました。

  • 2021年3月時点ですとTLS1,TLS1.1をサポートしてるとよろしくないようなので無効にしてます。
    TLS1.2の接続のみだけ許可しています。
    この設定であればSSLのテストをしてくれるサイト↓で「A」は取れると思います。(TLS1.2のみだとBになる)
    https://www.ssllabs.com/ssltest/

  • 証明書をコンテナ内に配置する方法ですが、「コンテナ内で取得」か「ホストで取得してコンテナにマウント」で迷いました。Lets EncryptのイメージもDocker Hubにあるのでそれを使おうかとも思いました。
    結局「ホストで取得してコンテナにマウント」で対応しています。こっちのほうが簡単そうなので。あと、コンテナ技術的にたぶん証明書はコンテナ外管理のほうがいいですよね。
    ただ、Lets Encryptの最新証明書が入ってるliveフォルダって中身がarchiveフォルダへのシンボリックリンクなんですよね。liveフォルダだけをマウントさせるのは無理っぽいので/etc/letsencryptごとマウントさせてます。
    証明書以外の余計なものまでマウントさせてますがまあしょうがないです…。

./conf/certpath.txt
# SSL証明書の場所 (実際にある場所を入れてください。)
ssl_certificate     /etc/nginx/letsencrypt/live/<domain_name>/fullchain.pem;
ssl_certificate_key /etc/nginx/letsencrypt/live/<domain_name>/privkey.pem;


# ssl_prefer_server_ciphersをonに指定すると、利用する暗号を選ぶ際に、
# SSLv3やTLSではサーバが示した暗号スイートが優先されます。
# offにするとクライアントのものが優先されます。デフォルトはoffです。
# これはnginxの機能というよりはOpenSSLの機能で、
# SSL_CTX_set_options()にSSL_OP_CIPHER_SERVER_PREFERENCEを設定します。
# https://heartbeats.jp/hbblog/2012/06/nginx06.html
ssl_prefer_server_ciphers on;


# サーバー側で有効にするプロトコル
ssl_protocols TLSv1.2;


# サーバー側で有効にする暗号
# 参考:https://rms.ne.jp/sslserver/basis/forward_secrecy_apache_ngix/
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

実行

あとはdocker-compose up -dすればOKです。
example.comでnginxのデフォルトページ、blog.example.comでWordPressのページにつながるはずです。

トラブルシューティング

nginxが起動できない

コンフィグファイルの構文ミスである場合が多いです。設定を見直してみてください。

もしくは、nginxは起動時にコンフィグファイルを評価し、名前解決を行います。
先にWordPressサーバーを起動しておかないと名前解決できません。先にWordPressを起動させてください。

この問題についての具体的な解決方法は出せていません…。
そもそもリバースプロキシと他のWEBサイトをCopmoseで分けるという発想が良くないのかもしれないです。
運営してみて構成を試行錯誤してみます。

意図しないページに飛ばされる

proxy_pass https://wordpress:443という記述にしていないですか?
私はこの記述の仕方でうまくいきませんでした。ポート番号外したら繋がるようになりました。

最後に

なんとかDockerでサイト構築することが出来ました。
今後もコンテナでサービス増やしていけたらいいなと思います。
フォルダ構成やComposeについては色々試行する余地がありそうです…。

Twitterもよかったらフォローしてください😊
https://twitter.com/daemokra

以上です。

参考にさせてもらったサイト

8
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?