Docker Nginx-Proxyで WordPressを 8080ポートで動かしてみた

Pocket

Docker Nginx-Proxyで WordPressを 8080ポートで動かしてみた
Docker Nginx-ProxyでWordPressを8080ポートで動かしてみた

序文

はい。

最近、DockerにハマってるKaBAです。

今日は、Dockerにて、WordPressコンテナを動かします。

Linuxサーバー上に複数のWordPressを動かすために、Dockerのnginx-proxyコンテナを使っています。

このnginx-proxyは、いわゆるWebサーバーを複数束ねる、フロントにあるプロクシーサーバーです。

このプロクシサーバーがあるおかげで、一つの80ポートを、複数のWebサーバーが共同利用できます。

nginx-proxyは、80ポートを待ち受けているわけですが、他のWebサーバーは、8081や8082ポートなどで待ち受けています。

それで、nginx-proxyがアクセスされたときのドメイン名で判断して、適切なWebサーバーを呼び出し、その結果を代理(プロクシー)でブラウザに返す、という仕組みになっています。

さらに嬉しいことに、今回使用するnginx-proxyは無料のSSL証明書を発行してくれるLet’sEncryptも自動的に使用してくれます。

それでは、Dockerコンテナである、nginx-roxy、Let’sEncrypt、WordPress、MySQLを動かしていきましょう!

nginx-proxyコンテナの設定

それでは、まず、nginx-proxyの設定ファイルを、~/work/docker/nginx-proxy/docker-compose.ymlとして作成します。

下記コマンドを実行し、設定ファイルを保存するフォルダを作成して、docker-compose.ymlファイルを作成してください。

$ mkdir -p ~/work/docker/nginx-proxy
$ cd ~/work/docker/nginx-proxy
$ vi docker-compose.yml

そして、以下のコードをコピー&ペーストして保存してください。

version: "2"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    privileged: true
    ports:
      - 18080:80
      - 8080:443
    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:ro
      - /srv/docker/nginx-proxy-with-encrypt/htpasswd:/etc/nginx/htpasswd
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/docker/nginx-proxy-with-encrypt/log:/var/log/nginx
      - ./docker-compose.d/etc/nginx/vhost.d:/etc/nginx/vhost.d
    environment:
      - HTTPS_METHOD=noredirect
    networks:
      - default
    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
    environment:
      - HTTPS_METHOD=noredirect
    volumes_from:
      - nginx-proxy
    restart: always

image: jwilder/nginx-proxyは、Dockerの公式コンテナとして公開されているnginx-proxyコンテナのイメージを差します。

この指定で、DockerHubというGitHub見たいな公開レジストリ(公開場所みたいなもの)から、コンテナのイメージがダウンロードされます。

といっても、100MBくらいの容量ですので、すぐにダウンロードは完了します。

また、Dockerコンテナを起動する度に、毎回ダウンロードするのではなく、1回ダウンロードした後は、ローカルホストに保存されたイメージが使用されます。

以下の設定は、nginx-proxyの80ポートを外部に対して80ポート(HTTP)として公開し、nginx-proxyの443ポート(SSL)を外部に対して443ポートとして公開する、という設定になります。

    ports:
      - 80:80
      - 443:443

以下の箇所は、Dockerを動かしているサーバーとDockerコンテナの共通して所有するファイルやフォルダを指定しています。
コロン「:」の左側がDokcerを動かしているサーバーのファイルやフォルダ、右側がDockerコンテナのファイルやフォルダです。

    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:ro
      - /srv/docker/nginx-proxy-with-encrypt/htpasswd:/etc/nginx/htpasswd
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/docker/nginx-proxy-with-encrypt/log:/var/log/nginx
      - ./docker-compose.d/etc/nginx/vhost.d:/etc/nginx/vhost.d

上記コードの一部の- ./docker-compose.d/etc/nginx/vhost.d:/etc/nginx/vhost.dは、後で使用します。

ngnxの設定ファイル/etc/nginx/conf.d/default.confをカスタマイズする際に使用しますので、覚えていられて損はないかと思います。

なお、environment:は、コンテナの「環境変数」を指定する命令です。

後から、この環境変数によって、

  • nginx-proxyで認識するドメイン名(URL)
  • nginx-proxyで認識するWordPressの公開ポート番号
  • Let’sEncryptのSSL証明書に書かれるドメイン名(SSLで証明されるドメイン名)
  • Let’sEncryptのSSL証明書作成時に使用される連絡先E-Mailアドレス

なども、指定できます。


Let’sEncryptコンテナの設定

  letsencrypt-nginx:
    image: jrcs/letsencrypt-nginx-proxy-companion

は、Let’sEncryptを自動的に実行し、無料のSSL証明書を自動的に取得してくれるDockerコンテナjrcs/letsencrypt-nginx-proxy-companionをDockerHubからダウンロードするようにする設定です。

何度も書きますが、ダウンロードは1回だけで、その後はローカルホストに保存されたイメージが再利用されます。

    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro

これは、Let’sEncryptコンテナとngix-proxyが連携するための、ファイルやフォルダの設定です。

コロン「:」の左側がDokcerを動かしているサーバーのファイルやフォルダ、右側がDockerコンテナのファイルやフォルダです。

Dockerを動かしているサーバー上の/srv/docker/nginx-proxy-with-encrypt/certsフォルダに、Let’sEncryptのSSL証明書が置かれます。

nginx-proxyコンテナとLet’sEncryptコンテナ上では、/etc/nginx/certsに置かれます。Let’sEncryptコンテナでも/etc/nginx/certsですね。

nginx-proxyコンテナとLet’sEncryptコンテナがファイルやフォルダを共有できるのは、以下のLet’sEncryptコンテナの設定のおかげです。

    volumes_from:
      - nginx-proxy

volumes_from:とは、ファイルやフォルダを参照する参照元の設定のことです。ここでは、nginx-proxyとなっていますね。

そのため、nginx-proxyコンテナが公開しているファイルやフォルダをLet’sEncryptコンテナが共有できます。

WordPressコンテナの設定

次に、WordPressコンテナの設定を見ていきます。

WordPressコンテナは指定したURLにアクセスするだけで、WordPressのインストールが始まります。
新たにWordPressサイトを作成するのに便利です。

WordPressコンテナについては、以下のリンク先に詳しく載っています。

Dockerコンテナへのアクセスをドメインごとに変更する「nginx-proxy」レビュー | さくらのナレッジ

WordPressの設定ファイルを作成してみましょう。

$ mkdir -p ~/work/docker/wordpress
$ cd ~/work/docker/wordpress
$ vi docker-compose.yml

~/work/docker/wordpressdocker-compose.xmlの内容は以下のようなものになります。

version: '3.1'
services:
  wordpress:
    image: moongift/wordpress
    hostname: azkeru-now.hasamisan.com
    restart: always
    ports:
      - 8081:80
    depends_on:
      - mysql
    links:
      - mysql
    volumes:
      - /var/docker/azkeru-now.hasamisan.com/www:/var/www/html
    environment:
      VIRTUAL_HOST: azkeru-now.hasamisan.com
      VIRTUAL_PORT: 8081
      LETSENCRYPT_HOST: azkeru-now.hasamisan.com
      LETSENCRYPT_EMAIL: kabahandle@la-bit.sakura.ne.jp
      LETSENCRYPT_TEST: "false"
      WORDPRESS_DB_PASSWORD: password
      HTTPS_METHOD: noredirect
    networks:
      - default
  mysql:
    image: mysql5.7:latest
    restart: always
    ports:
      - 13306:3306
    volumes:
      - /var/docker/azkeru-now.hasamisan.com/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
    networks:
      - default

以下のimage:の設定により、DockerHubから、WordPressコンテナのイメージがダウンロードされてサーバー上にイメージが保存されます。

何度もですが、イメージはローカルホストに保存されるため、次回の実行時以降はローカルホストのイメージが使用されます。

そのため、何度もダウンロードされることはありません。

  wordpress:
    image: moongift/wordpress

下記設定では、ports:命令により、WordPressコンテナの80ポートを、サーバー上では8081でポート待ち受けするよう設定しています。

この8081番は、特に意味はなく、空いているポート、例えば20000番など、指定する番号は自由です。

後で、この8081番を、nginx-proxyコンテナに「この8081番でWordPressを動かしているから、認識してね」と設定できます。

    ports:
      - 8081:80

以下の、volumes:の設定は重要です。コロン「:」の左側のフォルダを/var/docker/azkeru-now.hasamisan.com/wwwと指定しています。

これは、WordPressコンテナが、ドメイン名ごとにWprdPressコンテナの/var/www/html(コロン「:」の右側)を、サーバー上の/var/docker/<ドメイン名>/www(コロン「:」の左側)に置くことを指定しています。

    volumes:
      - /var/docker/azkeru-now.hasamisan.com/www:/var/www/html

上記指定により、WordPressコンテナ内の/var/www/htmlがサーバー上でも確認可能となります。

なお、サーバー上では、/var/www/htmlはrootが所有者ですが、WordPressコンテナ上では/var/www/htmlwww-dataユーザーが所有しています。
サーバー上で、rootで/var/www/htmlをいじると、WordPressコンテナが正常に動作しないため、注意してください。

次に、WordPressコンテナの「環境変数」の設定である、environment:を見ていきましょう。

    environment:
      VIRTUAL_HOST: azkeru-now.hasamisan.com
      VIRTUAL_PORT: 8081
      LETSENCRYPT_HOST: azkeru-now.hasamisan.com
      LETSENCRYPT_EMAIL: kabahandle@la-bit.sakura.ne.jp
      LETSENCRYPT_TEST: "false"
      WORDPRESS_DB_PASSWORD: password
      HTTPS_METHOD: noredirect

ここでは、下記のような環境変数設定を行っています。

  • VIRTUAL_HOST:WordPressのドメイン名
  • VIRTUAL_PORT:先ほど設定したWordPressのサーバー上で公開されているポート番号(8081でしたね)。
  • LETSENCRYPT_HOST:Let’sEncryptがSSL証明書を発行する際に必要な証明するドメイン名。
  • LETSENCRYPT_EMAIL:Let’sEncryptのSSL証明書有効期限が近くなるとお知らせが来るメールアドレス。
  • LETSENCRYPT_TEST:WordPress起動時すぐにSSL証明書ができていることを確認するかどうか。"false"で確認しない。"true"で確認する。
  • WORDPRESS_DB_PASSWORD:MySQLにあるDBのパスワードの設定。
  • HTTPS_METHOD:nginx-proxyの80ポートにアクセスがあった場合、443ポートに自動的に転送するかどうか。noredirectだと転送しない。redirectだと転送する。

「環境変数」とは、例えば、WordPressコンテナで設定した環境変数を、ngnx-proxyに伝達する、という役割があります。

上記例でも、VIRTUAL_HOSTをngnx-proxyコンテナに、LETSENCRYPT_HOSTをletsencrypt-nginxコンテナに伝達しています。

先ほどWordPressコンテナに指定した8081番のポート番号もVIRTUAL_PORTにより、nginx-proxyに伝達されます。

そしてnginx-prxyが8081番ポートにアクセスして、WordPressのWebページを代理で80番ポートや443ポートからブラウザにダウンロードさせる、という仕組みになっています。

このように、設定ファイルに変数を作り、コンテナの挙動を変更したり、コンテナ間で設定情報を共有したりすることに「環境変数」が使用されます。

MySQLの方は、image: mysql5.7:latestにてDockerHubからMySQLをダウンロードしています。

  mysql:
    image: mysql5.7:latest
    restart: always
    ports:
      - 13306:3306
    volumes:
      - /var/docker/azkeru-now.hasamisan.com/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

ポートは、サーバー上では13306となっていますが、特に意味はありません。
WordPressコンテナとMySQLは同一の設定ファイル内にあり、内部ネットワークの設定networks: - defaultがあるため、内部ネットワークで、WordPressとMySQLが通信可能です。

    ports:
      - 13306:3306

また、volumes:の指定により、MySQLのDBファイルも、サーバーとMySQLコンテナとで共有されます。

    volumes:
      - /var/docker/azkeru-now.hasamisan.com/mysql:/var/lib/mysql

MySQLのrootのパスワードは、下記environment:の設定により、「password」になります。

このパスワードを変更する場合は、WordPress側のMYSQL_ROOT_PASSWORDの値も変更することをお忘れなく。

    environment:
      MYSQL_ROOT_PASSWORD: password

なお、wp-config.phpの設定は、

  • DB名:wordpress
  • ユーザー名:root
  • パスワード:passwod
  • MySQLホスト名:mysql

となっています。

nginx-proxyコンテナとWordPressコンテナの起動

nginx-proxyコンテナを起動するには、以下のコマンドを実行します。

$ cd ~/work/docker/nginx-proxy
$ docker-compse up -d

nginx-proxyコンテナを停止には、以下のコマンドを実行します。

$ cd ~/work/docker/nginx-proxy
$ docker-compse down

wordpressコンテナを起動するには、以下のコマンドを実行します。

$ cd ~/work/docker/wordpress
$ docker-compse up -d

wordpressコンテナを停止するには、以下のコマンドを実行します。

$ cd ~/work/docker/wordpress
$ docker-compse down

 

nginx-proxy の公開ポートを8080に設定する

ここからは余談になります。

KaBAのサーバーの都合上、既に、80番と443番(SSL)のポートはDocker以外のWebサーバーで埋まっていましたので、Dockerのnginx-proxyのSSLの公開ポートを8080にする必要が出てきました。

そこで、~/work/docker/nginx-proxy/docker-compose.ymlにて、nginx-proxyの設定を変えることにしました。

以下の設定は、nginx-proxyの80ポートを外部に対して80ポートとして公開し、nginx-proxyの443ポート(SSL)を外部に対して443ポートとして公開する、という設定になります。

これは通常のnginx-popxyの設定です。

    ports:
      - 80:80
      - 443:443

以下の設定は、nginx-proxyの80ポートを外部に対して18080ポートとして公開し、nginx-proxyの443ポート(SSL)を外部に対して8080ポートとして公開する、という設定です。

KaBAの環境の都合上、SSLのポート番号を8080にしています。

    ports:
      - 18080:80
      - 8080:443

ただ、この指定だけでは、うまく行きません。

nginx-proxyは80番と443番で待ち受けていて、ブラウザで8080番にアクセスすると強制的に443番のURLに置き換えてしまいます。

そこで、~/work/docker/nginx_proxy2/docker-compose.d/etc/nginx/vhost.dというフォルダを作成し、~/work/docker/nginx-proxy/docker-compose.ymlファイルに下記設定を行いました。

$ mkdir -p ~/work/docker/nginx_proxy2/docker-compose.d/etc/nginx/vhost.d

以下、~/work/docker/nginx-proxy/docker-compose.ymlの設定です。

    volumes:
      - /srv/docker/nginx-proxy-with-encrypt/certs:/etc/nginx/certs:ro
      - /srv/docker/nginx-proxy-with-encrypt/htpasswd:/etc/nginx/htpasswd
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/docker/nginx-proxy-with-encrypt/log:/var/log/nginx
      - ./docker-compose.d/etc/nginx/vhost.d:/etc/nginx/vhost.d

最後の、- ./docker-compose.d/etc/nginx/vhost.d:/etc/nginx/vhost.dが重要です。

このvhost.d配下に<ドメイン名>というファイルを作成した場合、nginx-proxyの設定ファイル/etc/nginx/conf.d/default.confの<ドメイン名>用設定部分に組み込まれます。(incudeされます)

ここでは、~/work/docker/nginx-proxy/docker-compose.d/etc/nginx/vhost.d/azkeru-now.hasamisan.comとドメイン名をazkeru-now.hasamisan.comとしたファイルを作成します。

$ vi ~/work/docker/nginx-proxy/docker-compose.d/etc/nginx/vhost.d/azkeru-now.hasamisan.com

~/work/docker/nginx-proxy/docker-compose.d/etc/nginx/vhost.d/azkeru-now.hasamisan.comの中身は以下のように記述します。
azkeru-now.hasamisan.comは、皆さんのドメイン名にしてください。

listen 8080;

この設定で、nginx-proxyコンテナがazkeru-now.hasamisan.comの場合のみポート8080番で待ち受ける

ということになります。

詳しくは、nginx-proxyの公式サイトをご確認ください。

次に、azkeru-now.hasamisan.comの80番ポートと443番ポートにアクセスがあった際に、8080番ポートへ「恒久リダイレクト(301リダイレクト)」させるように設定します。

恒久リダイレクトとは、「Webサイトが移転し、URLが変わりました。これからは新しいURLへアクセスしてください。」とユーザーさんやGoogleなどのボットに伝える機能です。

実際に80ポートや443ポートを8080ポートに恒久リダイレクトすると、ブラウザも自動的に8080番のURLを表示してくれます。

また、Googleなどのボットも、8080番が正式なURLになったと認識して、これからはインデックス追加を8080ポートから取得するようにしてくれます。

それでは、恒久リダイレクトを行ってみましょう。

なお、KaBAの環境では、80番と443番で待ち受けているWebサーバーはapacheですので、apacheの設定を行うことになります。

まずは、80番の設定ファイルを作成します。/etc/httpd/conf.d/httpd-vhost.azkeru-now.hasamisan.com.confを開きます。

$ vi /etc/httpd/conf.d/httpd-vhost.azkeru-now.hasamisan.com.conf

設定内容は以下の通りです。

<VirtualHost *:80>
  ServerName azkeru-now.hasamisan.com
#  ServerAlias main.com
  DocumentRoot /var/www/html/azkeru-now
  <Directory "/var/www/html/azkeru-now">
    AllowOverride All
    Options FollowSymLinks
    Require all granted
  </Directory>
RewriteEngine on
RewriteCond %{SERVER_NAME} =azkeru-now.hasamisan.com
RewriteRule ^ https://%{SERVER_NAME}:8080%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

SERVER_NAMEがazkeru-now.hasamisan.comの時に、RewriteRule ^ https://%{SERVER_NAME}:8080%{REQUEST_URI} [END,NE,R=permanent]で80番から8080番ポートへ恒久リダイレクトしています。

次は、443番の設定ファイルを作成します。/etc/httpd/conf.d/httpd-vhost.azkeru-now.hasamisan.com-ssl.confを開きます。

$ vi /etc/httpd/conf.d/httpd-vhost.azkeru-now.hasamisan.com-ssl.conf

設定内容は以下の通りです。

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName azkeru-now.hasamisan.com
#  ServerAlias main.com
  DocumentRoot /var/www/html/azkeru-now
  <Directory "/var/www/html/azkeru-now">
    AllowOverride All
    Options FollowSymLinks
    Require all granted
  </Directory>
RewriteEngine on
RewriteCond %{SERVER_NAME} =azkeru-now.hasamisan.com
RewriteRule ^ https://%{SERVER_NAME}:8080%{REQUEST_URI} [END,NE,R=permanent]

SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES:!RC4:!DH

SSLCertificateFile /srv/docker/nginx-proxy-with-encrypt/certs/azkeru-now.hasamisan.com.crt
SSLCertificateKeyFile /srv/docker/nginx-proxy-with-encrypt/certs/azkeru-now.hasamisan.com.key
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /srv/docker/nginx-proxy-with-encrypt/certs/azkeru-now.hasamisan.com.chain.pem
</VirtualHost>
</IfModule>

Dockerのnginx-proxyコンテナのSSL証明書は、サーバー上では/srv/docker/nginx-proxy-with-encrypt/certs配下に配置されます。

  • <ドメイン名>.crtが証明書
  • <ドメイン名>.keyが秘密キー
  • <ドメイン名>.chain.pemが中間証明書

です。

SERVER_NAMEがazkeru-now.hasamisan.comの時に、RewriteRule ^ https://%{SERVER_NAME}:8080%{REQUEST_URI} [END,NE,R=permanent]で443番から8080番ポートへ恒久リダイレクトしてるのは、80番の設定と同じですね。

以上で設定完了です。

まとめ

皆様、大変お疲れ様でした。

長文失礼致しました。

今日の学びをここにまとめます。

  • Dockerのコンテナであるnginx-proxyは、一つのサイトに複数のWebサイトを同居でき便利。
    コンテナ単位でサイトを管理できるため、扱いが楽。
  • Let’sEncryptコンテナを使うと、Webサイトのコンテナを追加しただけで自動的にSSL証明書を発行してくれるので便利。
  • 通常nginx-proxyコンテナは80番と443番のポートを使用するが、8080ポートなども指定できる。
    apacheとの併用であれば、80番、443番から8080番に恒久リダイレクトを行うこともできる。

なにかと話題の多いDockerとnginx-proxyコンテナ、それとLet’sEncryptコンテナは、使って見るとやっぱり便利です。

コンテナをたくさん積むと、それなりにメモリも使います。

KaBAの場合は、AWHというVPSを使っています。

  • CentOS7
  • メモリ8GB
  • SSD50GB

のプランで使っていますが、費用は999円/月です。

他にもKAGOYAさんなど、最近は価格がこなれたVPSやレンタルサーバーも出てきています。

皆さんも、色々と検討されると良いかもしれませんね。

なお、下図のAWHさんは、クーポンコード「aff0905」にて、全使用期間5%割引になります。宜しかったらどうぞ。(画像をクリックするとAWHさんのサイトにジャンプします)

AWH VPS メモリ8GBで999円プランあり
AWH VPS メモリ8GBで999円プランあり