Docker Linux Ubuntu

Docker上でnginx-proxy他を使ってSSL対応マルチドメインサーバ環境の構築

投稿日:2017年10月7日 更新日:

今回は、nginx-proxyを使用し、SSLに対応したマルチドメイン環境を構築します。

追記(2017/10/08):作成したdocker-compose.ymlをGithubに公開しました。目次の「Github」からダウンロードできます。

背景

VPSをレンタルしてLinuxサーバを立てました。私がサーバで実現したい要件は以下です。

  • ブログ用のWebサーバの構築
  • タスク管理用のチケット管理システムの構築
  • 上記の2つのサービスへのアクセスを、1つのIPアドレスで待ち受ける
  • 上記の要件をSSLを用いて暗号化する

そこで、今回はDockerとDockerイメージを用いて、上記の要件を実現しようと思います。

  • Webサーバ→Wordpress公式Dockerイメージ(Wordpress+mysql)
  • チケット管理システム→Redmine公式Dockerイメージ(Redmine+mysql)
  • 1つのIPアドレス(メイン+サブドメイン)で上記サービスへのリクエストを待ち受ける→nginx-proxyを用いたマルチドメイン環境
  • 上記のSSLでの暗号化→nginx-proxydocker-letsencrypt-nginx-proxy-companionの連携

このうち、下記2つについて、本ページで取り上げます。
(上記2つについては別ページを作成して取り上げます)

nginx-proxyとは

nginx-proxyは、リバースプロキシとして動作するDockerイメージです。
リバースプロキシとは、特定のドメイン・パスに対して受けたHTTP等のリクエストに対し、それぞれ対応したポートにリクエストを振り分ける機能です。
nginx-proxyは、Webサーバとしてnginxを使用し、上記のリバースプロキシを実現しています。Dockerイメージですので、コンテナとして起動すれば、ソフト等のインストールも不要でそのまま使用することができます。

docker-letsencrypt-nginx-proxy-companion とは

docker-letsencrypt-nginx-proxy-companionは、SSL通信に必要なサーバ証明書を、Let’s encryptを使用し自動で取得・更新する機能を持つDockerイメージです。
Let’s encryptは、サーバ証明書を無料で取得できるサービスです。サーバ証明書を取得するためには、Let’s encryptが作成したスクリプトをインストールし、各種設定をする必要があります。
しかし、docker-letsencrypt-nginx-proxy-companion を使用することによって、コンテナとして起動した際に自動でサーバ証明書の取得を行います。また、サーバ証明書を取得した後、定期的に証明書の有効期限を確認し、必要ならば自動で更新します。

docker-composeによる両サービスの起動

今回は、nginx-proxとdocker-letsencrypt-nginx-proxy-companion を、docker-composeによって連携させた状態で起動・動作させます。
作成したdocker-compose.ymlは以下になります。

version: "2"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    privileged: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:ro
      - /srv/docker/nginx-proxy-with-encrypt/htpasswd:/etc/nginx/htpasswd
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/docker/nginx-proxy-with-encrypt/log:/var/log/nginx
    networks:
      - default
      - ssl_proxy
    restart: always

letsencrypt-nginx:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt-nginx
    privileged: true
    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy
    restart: always
networks:
  ssl_proxy:
    external: true
~

3行目~20行目までがnginx-proxy、22行目~31行目までがdocker-letsencrypt-nginx-proxy-companionの設定です。

nginx側では、以下が特徴的な設定になります。

  • 8、9行目では、portsオプションにより80番、443番ポート(HTTPS用)にきたパケットを自身にポートフォワードするように設定します。
    ports:
      - 80:80
      - 443:443
  • 11行目では、証明書の確認および永続化のため、nginx-proxy側の/etc/nginx/certs、すなわち証明書が入るディレクトリは、ホスト側にvolumesとしてマウントしておきます。
    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:ro
  • 19行目でnetworksオプションによりネットワークブリッジを指定します(ssl_proxy)。
    networks:
      - default
      - ssl_proxy

    これは、プロキシをさせたいdockerサービスがこのネットワークブリッジに所属することで、該当のdockerサービスの起動・終了をnginx-proxyが検知してくれるようになります。

docker-letsencrypt-nginx-proxy-companion側では、以下が特徴的な設定になります。

  • 29行目にvolumes_fromオプションを入れることで、nginx-proxyそのものをマウントします。
    volumes_from:
      - nginx-proxy

    これにより、docker-letsencrypt-nginx-proxy-companionが行う一連の証明書取得処理がnginx-proxy側で反映されるようになります。

最後に、32行目のnetworksの項目に、nginx-proxyで指定したネットワークブリッジをexternal:trueしておくことを忘れないでください

networks:
  ssl_proxy:
    external: true

これは、他のdockerコンテナが該当のネットワークブリッジを参照するために必要なコードです。

実際に使用する場合は、docker-composeする前に、該当のネットワークブリッジを作成しておく必要があります。以下のコマンドでは、先程ymlファイルに記述したssl-proxyブリッジを作成してから、各コンテナをバックグラウンドで起動しています。

admin@hostname:~# docker create --driver bridge ssl-proxy
admin@hostname:~# docker-compose up -d

動作確認

動作確認は、nginx-proxyにプロキシさせたいサービスを起動した際に行います。
nginx-proxyにプロキシさせたいサービスの起動方法は別ページ(WordPressとRedmine環境の構築用ページ)に記載します。

終わりに

SSLに対応したマルチドメイン環境が、ほとんど設定なし、かつホスト環境に手を入れずに、簡単に実現できました。dockerさまさまですね。

今後は、各サービスとproxyが連携して協調動作を行う部分を構築していきます。

Github

今回使用したdocker-compose.ymlをGithubに公開しました。下記リンクからgit cloneすることで、docker-compose.ymlが取得できます。

-Docker, Linux, Ubuntu
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

関連記事

pthread_cancelすると何が行われるのか

仕事でのメモ。 目次1 pthread_cancel2 pthread_cancelで何が行われるのか2.1 シグナル送出2.2 注意2.3 ソースコードを読む2.4 pthread_cancel時の …

Linux+RustでOS自作〜環境構築編〜

目次1 概要2 環境構築2.1 ツール一覧2.2 ツールのインストール3 終わりに4 参考サイト様4.0.1 関連 概要 先日、「30日でできる! OS自作入門」を購入しました。 30日でできる! O …

C++のマルチスレッド環境における問題とvalgrindを用いた検出方法

私は仕事でC++を使用してソフトウェアを実装しています。 今回は、C++マルチスレッドプログラミングで発生する問題点とその検出方法を(自分のメモも兼ねて)記述します。 環境は以下になっております。 O …

cmake, googletestを利用したC++開発環境の構築テスト

自学用メモ。 業務で使用しているcmakeの勉強がてら、業務に近いソースツリーを作成した。 googletestを用いた単体テストも合わせて書けるような構成になっている。 テンプレートとして、今後のC …

Linuxサーバの初期設定(Ubuntu 16.04 LTS)

先日、VPS(Scaleway VCS1プラン)をレンタルし、Linuxサーバを立ち上げました。その際の初期設定について記述していきます。 目次1 環境2 作業内容2.1 ユーザ設定2.2 SSH設定 …