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

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

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

関連記事

Mackerelでサーバ内ホスト・Dockerコンテナを監視する

サーバ監視ソフトを入れたいなと考えていたところ、ひょんなことからMackerelというサーバ監視サービスを発見したため、導入してみました。 環境は以下です。 OS:Ubuntu16.04 目次1 要件 …

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

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

systemdでのCPU制限方法~serviceファイルでの設定編

systemd に悩まされる皆様、進捗どうですか(? 標題の件、仕事で必要に迫られたため、備忘録として。 目次1 まえがき2 動作環境3 確認内容3.1 systemdから起動するserviceのデフ …

ltraceを用いてstd::vector::push_backの動作を見える化する

仕事で使用したltraceの使い方を、メモがてら残しておきます。 目次1 概要1.1 環境2 設計・実装3 ltraceを用いたdynamic libraryのトレース4 終わりに5 メモ5.0.1 …

systemdからdockerコンテナを起動+timerで定期実行

今回はdockerコンテナをsystemdから起動し、かつtimerを使用して定期実行する方法を紹介します。 目次1 背景2 要求と仕様3 systemdについて4 設計・実装4.1 テストアプリとs …