Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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

dockerで起動したメールサーバコンテナのローカルIPアドレスは、以下で取得できます。1台のサーバ内でWebサーバ、メールサーバ等が同居して動かしている場合は、ここで取得するローカルIPがメールサーバのIPアドレスとなります。
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' コンテナID

(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
pyuta
Android、iOS、サーバサイド、フロントエンドの開発を一人でこなせるフルスタックエンジニアが目標です。 Ruby on Rails、React、React Native、Docker、Swift、Kotolinを中心に勉強してます。 よかったら仲良くしてください。
topgate
Google技術を中心に取り扱う技術者集団
https://www.topgate.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away