WordPress
postfix
RubyOnRails
docker
letsencrypt

【Docker】マルチサイト構築(WrodPress,Ruby on Rails,Let'sEncrypt,nginx-proxy,postfix,MySQL)

はじめに

Dockerによるマルチサイト構築手順です。
WordPress、Ruby on Railsでマルチサイトを構築です。
投稿者の環境は、CentOS7環境です。

できること

  • WordPress、Ruby on RailsのWebサイトをマルチサイトで公開する。
  • サイト数は、追加、削除が容易に行える。
  • Webサイトは、Let'sEncryptでSSL化して公開する。
  • 1つのMySQLコンテナを共通DBとして利用する。
  • Ruby on Railsの既存プロジェクトをDocker上で動作させる。
  • Ruby on Railsコンテナに対して、dbcreate、migration、seed投入、アセットプリコンパイルする。
  • ホストOSのCronスケジュールで、Ruby on Railsコンテナ上のバッチスクリプトをスケジュール実行する。
  • OS起動時にコンテナは自動起動にする。
  • postfixコンテナでsmtpサーバを建てる。
    WordPress、ruby on railsからsmtp接続設定を行い、メール送信する。

上記が実現できれば、一連のWebサービス公開できると思います。

マルチサイトの完成図

システム概要図.jpg

投稿者の環境は、サーバ2台を利用し、postfixコンテナだけ、さくらVPSで稼働する。

コンテナの構成

コンテナ 使用イメージ 内容
MySQL mysql:5.7 コンテナで使用する共通DB
WordPress
(1番目)
wordpress:latest WordPressのWebサイト
WordPress
(2番目)
wordpress:latest WordPressのWebサイト
Ruby on Rails ruby:2.4.1 Ruby on RailsのWebサイト
nginx-proxy jwilder/nginx-proxy リバースプロキシ、1台のサーバで複数Webサイトをホストする
letsencrypt-nginx-proxy jrcs/letsencrypt-nginx-proxy-companion nginx-proxyと同時使用し、Webサイトの環境変数のVIRTUAL_HOSTを定義することで、WebサイトをSSL化する
postfix catatnight/postfix smtpサーバ

準備ファイル

順を追って説明するが、下記ファイルを作成する。

/home/web
│
├── docker-compose.yml #コンテナの定義ファイル
│
├── mywebservice.service #OS起動時のコンテナ自動起動のサービス定義ファイル
│
├── rails #配下にRuby on Railsのプロジェクトを配置
│   └── rails_web1 #Ruby on Railsサイト1つ目
│       ├── Dockerfile #Ruby on RailsサイトのDockerfile 
│       └── src #Ruby on Railsサイトのソース一式
│
└── sql #Mysqlコンテナ初期起動時に実行するスクリプト
    └── docker-entrypoint.sh #WordPress2つ目以降のDB作成スクリプト

docker-compose up後のフォルダ構成

/home/web
│
├── certs #LetsEncryotの証明書配置
│   └── ・・・
│
├── docker-compose.yml #コンテナ定義
│
├── mysql #MySQLデータ
│   └── ・・・
│
├── mywebservice.service #OS起動時のコンテナ自動起動サービス定義
│
├── rails #Ruby on Railsのプロジェクトルート
│   └── rails_web1 #Ruby on Railsサイト1つ目
│       ├── Dockerfile #Ruby on RailsサイトのDockerfile 
│       └── src #Ruby on Railsサイトのソース一式
│           ├── config
│           │   ├── database.yml
│           │   └── environments
│           │       ├── development.rb
│           │       ├── production.rb
│           │       └── ・・・
│           └── ・・・
│ 
├── sql #MySQLコンテナ初回起動時スクリプト
│   └── docker-entrypoint.sh #WordPress2つ目以降のDB作成スクリプト
│ 
└── wordpress #WordPressのフォルダ
    ├── wp_1 #Wordpressサイト1つ目
    │   └── wp-content
    │       └── ・・・
    │    
    └── wp_2 #Wordpressサイト2つ目
        └── wp-content
            └── ・・・
        

章立て

1.事前準備
2.WordPressサイトを2つ立ち上げる。
3.Let'sEncryptでWordPressサイトをSSL化する。
4.Ruby on Railsサイトを立ち上げる。
5.Ruby on Railsのバッチ処理をCronでスケジュール実行する。
6.postfixのメールサーバを立ち上げる。
7.WebサイトをOS起動時に自動起動にする。

1.事前準備

Docker環境インストール
Docker-Compose環境インストール

Dockerサービス開始、自動起動を設定

#systemctl start docker #Dockerサービス開始
#systemctl enable docker #Docker自動起動

2.WordPressサイトを2つ立ち上げる

(1)docker-compose.yml に導入するコンテナを定義する。

#vi docker-compose.yml
docker-compose.yml
version: '2'
services:
  db:
    container_name: mysql
    image: mysql:5.7
    ports:
      - 3306:3306
    volumes:
      - ./sql:/docker-entrypoint-initdb.d
      - /home/web/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_USER : root
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: wp_1
      MYSQL_USER: wp_1
      MYSQL_PASSWORD: password
    restart: always
 wordpress1:
    container_name: wp_1
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - /home/web/wordpress/wp_1/wp-content:/var/www/html/wp-content
    external_links:
      - db
    expose:
      - 80
    environment:
      VIRTUAL_HOST: XXXXXX.XXX #WordPress1つ目のドメイン名
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wp_1
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: password
    restart: always
 wordpress2:
    container_name: wp_2
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - /home/web/wordpress/wp_2/wp-content:/var/www/html/wp-content
    external_links:
      - db
    expose:
      - 80
    environment:
      VIRTUAL_HOST: XXXXXX.XXX #WordPress2つ目のドメイン名
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wp_2
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: password
    restart: always
nginx-proxy:
    container_name: nginx_proxy
    image: jwilder/nginx-proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - restart: always
networks:
  default:
    external:
      name: net-proxy

nginx-proxyコンテナは、リバースプロキシです。VIRTUAL_HOSTの定義を自動で探して、Webサイトを公開してくれます。

(2)2つ目のDB作成
MySQLコンテナは、初回起動時に初期DBは作成してくれるが、2番目以降のDBは作成しない。
今回、WordPressサイト毎にDBを用意するため、2つDBを用意する。
2つ目以降のDB作成方法として、MySQLコンテナ内のエントリーポイントを利用する。
このエントリーポイントのフォルダにシェルやSQLを配置しておくと、これらを初回起動時に実行してくれる。
この仕組を利用し、WordPressの2番目以降のDBを作成する。

docker-compose.ymlに、エントリーポイントのフォルダ記載を行い、ホスト側のエントリーポイントにシェルを配置する。

services:
  db:
    #---途中省略---
    volumes:
      - ./sql:/docker-entrypoint-initdb.d
    #---途中省略---
#mkdir /home/web/sql -p
#vi /home/web/sql/docker-entrypoint.sh
docker-entrypoint.sh
echo "CREATE DATABASE IF NOT EXISTS \`wp_2\`;" | "${mysql[@]}"
echo "GRANT ALL ON \`wp_2\`.* TO '"$MYSQL_USER"'@'%';" | "${mysql[@]}"
echo 'FLUSH PRIVILEGES;' | "${mysql[@]}"

(3)コンテナ用のネットワーク作成

#docker network create net-proxy

(4)コンテナ起動

#docker-compose up -d

(5)ブラウザで動作確認
ブラウザでアクセスすると、WordPressのサイト1、サイト2が表示される。

3.Let'sEncryptでwordpressサイトをSSL化する。

letsencrypt-nginx-proxy-companionコンテナを導入する。
WordPressコンテナのenvironmentに以下の2つを追加すると、Let'sEncryptでSSL化される。

  • LETSENCRYPT_HOST
  • LETSENCRYPT_EMAIL

(1)letsencrypt-nginx-proxy-companionコンテナを導入する。

#vi docker-compose.yml
docker-compose.yml
      #---途中省略---
 wordpress1:
      #---途中省略---
     environment:
      #---途中省略---
      LETSENCRYPT_HOST: xxxxxx.xxx    #+追加行、WordPress1つ目のドメインのホスト名
      LETSENCRYPT_EMAIL: xx@xxxxxx.xxx    #+追加行、メールアドレス
      #---途中省略---
 wordpress2:
      #---途中省略---
     environment:
      #---途中省略---
      LETSENCRYPT_HOST: xxxxxx.xxx    #+追加行、WordPress2つ目のドメインのホスト名
      LETSENCRYPT_EMAIL: xx@xxxxxx.xxx    #+追加行、メールアドレス
letsencrypt-nginx-proxy-companion: #+追加行
    image: jrcs/letsencrypt-nginx-proxy-companion #+追加行
    volumes: #+追加行
      - /home/web/certs:/etc/nginx/certs:rw #+追加行
      - /var/run/docker.sock:/var/run/docker.sock:ro #+追加行
    volumes_from: #+追加行
      - nginx-proxy #+追加行
    restart: always #+追加行
nginx-proxy:
      #---途中省略---
    volumes:
      - /home/home/web/certs:/etc/nginx/certs:ro #+追加行
      #---途中省略---

(2)コンテナ再起動

#docker-compose restart

(3)ブラウザで動作確認
ブラウザでアクセスすると、WordPressのサイト1、サイト2がSSL化されて表示される。

4.Ruby on Railsサイトを立ち上げる。

Ruby on Railsサイトの既存プロジェクトをDocker環境に移行し、稼働させる。

(1)Ruby on Railsのコンテナを追加する。

#vi docker-compose.yml
docker-compose.yml
  rails_web1: #+追加行
    build: #+追加行
      context: ./rails/rails_web1 #+追加行、rubyコンテナのDockerfileの場所
      dockerfile: Dockerfile #+追加行、rubyコンテナのDockerfile
    container_name: rails_web1 #+追加行
    #command: bundle exec rails s -p 80 -b '0.0.0.0' -e production #+追加行、developmentの場合
    command: bundle exec rails s -p 80 -b '0.0.0.0' -e development #+追加行、productionの場合
    environment: #+追加行
      VIRTUAL_HOST: xxxxxx.xxx    #+追加行、Ruby on Railsサイトのドメイン名
      LETSENCRYPT_HOST: xxxxxx.xxx    #+追加行、Ruby on Railsサイトのドメインのホスト名
      LETSENCRYPT_EMAIL: xx@xxxxxx.xxx    #+追加行、メールアドレス
    volumes: #+追加行
      - ./rails/rails_web1/src:/myapp #+追加行
    expose: #+追加行
      - 80 #+追加行
    depends_on: #+追加行
      - db #+追加行
    restart: always #+追加行

(2)Dockerfileを定義する。

#mkdir -p ./rails/rails_web1/src
#vi ./rails/rails_web1/Dockerfile
Dockerfile.
FROM ruby:2.4.1
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD ./src/Gemfile /myapp/Gemfile
ADD ./src/Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD ./src /myapp

(3)Ruby on Railsの既存ソース一式をホスト側の「src」ディレクトリに配置する。

/home/web
└── rails #配下にRuby on Railsのプロジェクトを配置
    └── rails_web1 #Ruby on Railsサイト1つ目
        ├── Dockerfile #Ruby on RailsサイトのDockerfile 
        └── src #Ruby on Railsサイトのソース一式

(4)Ruby on RailsのDB定義を行う。
docker-compose.ymlに記載したServiceのDB情報をdatabase.ymlに記載する。

vi /home/web/rails/rails_web1/src/config/database.yml
database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: password
  host: db 
  database: db_rails
development:
  <<: *default
production:
  <<: *default

(5)コンテナ再起動

#docker-compose restart

(6)ブラウザで動作確認
ブラウザでアクセスすると、Ruby on RailsサイトがSSL化されて表示される。

(7)db_create、migration、seed投入、アセットプリコンパイル
Ruby on Railsサイトに対して、db_create、migration、seed投入、アセットプリコンパイルを行う。

docker exec rails_web1 bundle exec rake db:create db:migrate db:seed
docker exec rails_web1 bundle exec rake assets:precompile RAILS_ENV=production

5.Ruby on Railsのバッチ処理をCronでスケジュール実行する。

コマンドラインからのバッチ実行で動作するかを確認する。

#docker exec rails_web1 bundle exec rake cron:xxxxx RAILS_ENV=production

動作に問題なければ、ホスト側のcrontabに登録する。

#crontab -e
0 18 * * * docker exec rails_web1 bundle exec rake cron:xxxxx RAILS_ENV=production

6.postfixのメールサーバを立ち上げる。

(1)catatnight/postfixのコンテナを稼働する。

docker run -p 25:25 \
         -e maildomain=xxxxxx.xxx -e smtp_user=user:password \
         --name postfix -d catatnight/postfix

catatnight/postfix

(2)Ruby on Railsのメール送信を設定する。
Ruby on RailsのAction Mail設定を行う。

vi /home/web/rails/rails_web1/src/config/environments/production.rb
production.rb
  #Error キャッチ有効化※メールが送信できない時の調査用
  config.action_mailer.raise_delivery_errors = true

  #メールテスト送信設定
  config.action_mailer.smtp_settings = {
        :address => "xxxxxx.xxx",
        :port => 25,
        :domain => 'xxxxxx.xxx',
        :user_name => "user@xxxxxx.xxx", #アドレス
        :password => "password", #パスワード
        :openssl_verify_mode  => 'none' #SSL無効
  }

設定後、Ruby on Railsサイトからメール配信を行い、正常にメール送信する事を確認する。

(3)WordPressのメール送信を設定する。
WordPressに「WP Mail SMTP」プラグインを導入し、メール送信サーバを設定する。
wp smtp3.png

WordPress側のSMTP設定
wp smtp0.png

wp smtp1.png

WordPress側のSMTP送信テストを行い、正常にメール送信することを確認する。
wp smtp2.png

7.WebサイトをOS起動時に自動起動にする。

(1)サービスファイルを作成する。

#vi /home/web/mywebservice.service
[Unit]
Description=My Service
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/home/web
ExecStartPre=/usr/local/bin/docker-compose stop
ExecStartPre=/usr/local/bin/docker-compose rm
ExecStartPre=/usr/local/bin/docker-compose down
ExecStartPre=rm /home/web/rails_web1/src/tmp/pids/server.pid -f
ExecStart=/usr/local/bin/docker-compose up -d

[Install]
WantedBy=multi-user.target

(2)サービスファイルを有効にする。

#cp /home/web/myservice.service /etc/systemd/system/
#systemctl daemon-reload
#systemctl enable myservice.service
#systemctl start myservice.service