Yuki猫のおうち

気ままに自由に日々を生きるエンジニアのブログ

お名前.comのVPSでCentOS7上にdockerを用いてwordpressとlaravelを稼働させる 〜https対応を添えて〜

前々からdockerはキャッチアップしなきゃなと思いつつ結局触れていなかったのですが、育児休暇を取って少し自宅でPCを触れる時間ができたので勉強してみることにしました。

最近仮想通貨取引を始めて、取引アプリや自動売買bot、収支管理アプリなどいろいろ作ってみたいなと思っていたので、どうせならサーバー上で複数サービスを動かせるようにして、簡単に追加できるようにしてみます。

構成

最終的な構成はこんな感じになります。

f:id:yukineko4you:20200301032353p:plain

docker-compose.ymlは一つにまとめた方が簡単そうではあったのですが、設定ファイルが肥大化してしまうのと、新しいアプリケーションを追加するときに他のサービスを意識しなくて良い、などの理由でアプリケーションごとに分割して作成します。


ディレクトリ構成は以下のようになります。

work_directory/
├── laravel/
│   ├── docker-compose.yml
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       └── Dockerfile
├── shared/
│   └── docker-compose.yml
└── wordpress/
    ├── docker-compose.yml
    ├── nginx/
    │   └── default.conf
    └── php/
        └── Dockerfile

作業手順

docker、docker-composeのインストール

公式ドキュメントの通りに行えばOKです。
docs.docker.com

インストール

まずはインストール作業に必要となるパッケージを導入します。

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2

次にdockerのdocker公式のリポジトリyumに登録します。

$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

最後にdockerをyumでインストールします。

$ sudo yum install -y docker-ce docker-ce-cli containerd.io

これでdockerのインストールは完了です。

続いてdocker-composeもインストールします。

docs.docker.com


以下のコマンドを実行してダウンロードしてきます。

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


実行権限を付与したら完了です。簡単ですね。

$ sudo chmod +x /usr/local/bin/docker-compose
動作確認

公式マニュアルに従って、無事にインストールできているか確認してみます。

まずはdockerを起動します。

$ sudo systemctl start docker

次に、動作確認用のhello-worldコンテナを起動します。

$ sudo docker run hello-world

hello-worldコンテナは初めて起動するので 「Unable to find image 'hello-world:latest' locally」 と表示されますが、イメージをダウンロードして処理が進んでいきます。
いろいろ表示されますが、以下の文章が表示されていれば正常に起動できています。

Hello from Docker!
This message shows that your installation appears to be working correctly.
dockerグループに作業ユーザーを登録

dockerのコマンドは実行にsudo権限が必要なのですが、コマンド実行時に毎回sudoを書くのは面倒なので対応します。

qiita.com

まずは、dockerグループが存在するかを確認します。

$ cat /etc/group | grep docker

私の環境ではdockerグループが既に作成されていたので、作業ユーザーを追加するだけで大丈夫でした。
もしグループがなければ作成します。

$ sudo groupadd docker

あとは、ユーザーをdockerグループに登録して終わりです。

$ sudo usermod -aG docker $USER

ユーザーの所属グループを表示して、リストの中にdockerが存在していれば設定完了です。
確認できたら、設定を反映させるために再ログインします。

$ groups $USER

サブドメインDNS設定

私はお名前.comでドメインを購入しているので、公式マニュアルに従ってサブドメイン登録を行います。
DNS関連機能の設定:DNSレコード設定|お名前.com Navi ガイド|ドメイン取るならお名前.com

今回は、「gitlab」と「trade-log」「wordpress」の3種類のサブドメインを登録しました。

shareネットワークの作成と所属するコンテナの起動

まず、yamlファイル作成する前に、先にshareネットワークを作成しておきます。
ネットワークを事前に作成しておかないとdocker-compose実行時にエラーになってしまいます。

$ docker network create share

次に、share/docker-compose.ymlを以下のように設定します。
shareネットワーク上では「nginx-proxy」「let's-encrypt」「MySQL」のコンテナを立ち上げるための設定を記述します。

version: "3"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy:alpine
    container_name: nginx-proxy
    privileged: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam
      - vhost:/etc/nginx/vhost.d
      - certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt
    privileged: true
    depends_on:
      - "nginx-proxy"
    volumes:
      - certs:/etc/nginx/certs:rw
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always
    environment:
      NGINX_DOCKER_GEN_CONTAINER: "nginx-gen"
      NGINX_PROXY_CONTAINER: "nginx-proxy"

  mysql:
    image: mysql:5.7
    container_name: mysql
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --max-allowed-packet=128M
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_USER: root
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mysql
    volumes:
      - ./mysql:/var/lib/mysql
    restart: always

volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  default:
    external:
      name: shared

yamlファイルを作成したら、以下コマンドでコンテナを起動します。

$ docker-compose up -d

コマンドが正常に終了したら、コンテナがちゃんと立ち上がっているか念のため確認します。
下記コマンドを実行して、全てのコンテナのSTATUSが「UP xx seconds」 になっていれば大丈夫です。

$ docker ps

wordpressの構築

続いて、wordpress用のコンテナを起動していきます。

wordpressという名前のディレクトリを作成し、yamlファイルを以下のように記述します。

version: '3'
services:
  nginx:
    image: nginx
    external_links:
      - mysql
    container_name: "wordpress-nginx"
    ports:
      - "80"
      - "443"
    volumes:
      - ./src:/src
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      VIRTUAL_HOST: blog.yukineko.work
      LETSENCRYPT_HOST: blog.yukineko.work
      LETSENCRYPT_EMAIL: yuki@blog.yukineko.work
    restart: always
  php:
    build: ./php
    container_name: "wordpress-php"
    volumes:
      - ./src:/src
      - ./php/php.ini:/usr/local/etc/php/php.ini
    restart: always

networks:
  default:
    external:
      name: shared

注意する点は、ssl対応するためにenvironmentで環境変数を設定しておくことくらいです。
VIRTUAL_HOSTLETSENCRYPT_HOSTの値に割り当てたいドメインを設定しておくことで、nginx-proxyとlet's encryptのコンテナがいい感じにhttpsで接続できるようにしてくれます。

次に、nginxの設定ファイルと、phpコンテナのDockerfileを作成します。

nginx/default.conf

server {
    listen 80;
    server_name localhost;
    root /src/;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass wordpress-php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include       fastcgi_params;
    }
}

php/Dockerfile

FROM php:7-fpm
RUN apt-get update \
        && docker-php-ext-install pdo_mysql mysqli \
        && mkdir -p /src

WORKDIR /src

作成したら、docker-compose.ymlがあるディレクトリに移動してコンテナ群を起動します。

$ docker-compose up -d

無事コンテナが立ち上がったら、コンテナ内に入ってwordpress用の設定を行なっていきます。

まずはmysqlコンテナに入ってデータベースを作成します。

$ docker exec -it mysql bash
(docker内で実行) $ mysql -u root -p
(mysql内で実行) $ create database wordpress;

次に、wordpressディレクトリでwordpressのソースをダウンロードしてきて展開します。

$ wget https://ja.wordpress.org/latest-ja.tar.gz    
$ tar xzfv latest-ja.tar.gz > /dev/null
$ mv -R wordpress/* src/
$ rm -rf wordpress latest-ja.tar.gz

プラグインのインストール時などに権限エラーにならないよう、ディレクトリの権限を変更しておきます。

$ cd src
$ sudo chmod -R 777 wp-content

最後に、 DBやSSLの設定を行います。

$ cp src/wp-config-sample.php src/wp-config.php
$ sudo vi src/wp-config.php

今回はDB_NAMEは事前に作成した「wordpress」を、DB_USERDB_PASSWORDは何も設定していないのでひとまずrootを使用します。
rootユーザーを使い続けるのはセキュリティ的にあんまりよくないので、そのうちDBにユーザーを作って設定を変更するようにしましょう。

また、SSL関連の設定はファイル末尾に記述されている「require_once(ABSPATH . 'wp-settings.php');」より前に書かないとブラウザからアクセスした際にエラーとなってしまうので気をつけてください。

wordpress/src/wp-config.php

~~ 省略 ~~

# DB系のデータベース名やユーザー名を設定

define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
define('DB_HOST', 'mysql');

~~ 省略 ~~

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
  && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
  $_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

~~ 省略 ~~

ここまでできたら、VIRTUAL_HOSTで設定したドメインにブラウザでアクセスしてみます。
無事wordpressが表示されたら設定完了です。

laravel環境の構築

laravelというディレクトリを作成してyamlファイルを記述していきます。

version: '3'

services:
  laravel-nginx:
    image: nginx
    external_links:
      - mysql
    container_name: "laravel-nginx"
    ports:
      - "80"
      - "443"
    volumes:
      - ./src:/src
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      VIRTUAL_HOST: trade-log.yukineko.work
      LETSENCRYPT_HOST: trade-log.yukineko.work
      LETSENCRYPT_EMAIL: mail@trade-log.yukineko.work
    restart: always
  php:
    build: ./php
    container_name: "laravel-php"
    volumes:
      - ./src:/src
    restart: always

networks:
  default:
    external:
      name: shared

wordpressの構築でも対応したように、こちらでもnginxディレクトリを作成して設定ファイルを、phpディレクトリを作成してDockerfileを設置します。

nginx/default.conf

server {
  listen 80;
  server_name localhost;
  index index.php index.html;
  root /src/public/;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    try_files $uri = 404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass laravel-php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
  }
}

laravel/php/Dockerfile

FROM php:7.2-fpm

RUN apt-get update \
  && apt-get install -y zlib1g-dev \
  && docker-php-ext-install zip

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \
  && mv composer.phar /usr/local/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

RUN composer global require "laravel/installer"

RUN apt-get update \
  && apt-get install -y libpq-dev \
  && docker-php-ext-install pdo_mysql

RUN apt-get update \
  && apt-get install -my wget gnupg

RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \
  && apt-get update \
  && apt-get install -y nodejs

WORKDIR /src

ここまでできたら、コンテナ群を起動します。

$ docker-compose up -d

起動できたら「laravel-php」内でlaravelプロジェクトの作成を行います。

$ docker exec -it laravel-php bash
(docker内で実行) $ laravel new
(docker内で実行) $ docker-compose exec php php artisan key:generate

ここまでできたら、VIRTUAL_HOSTで設定したドメインにブラウザでアクセスしてみます。
無事laravelの画面が表示されたら設定完了です。