長らくVMどまりだったおっさんSEが、今更だがコンテナをやってみる。
というのも、この blog を動かしているプラットフォームがレガシー化して久しく、そろそろ OS ごと入れ直しが必要ということで、折角なのでコンテナ化しようと。
とりあえずは WordPress が動けば良いのだが、今後 *.ookawara.com で色々なサービスを動かして遊びたい、ということでリバースプロキシをたててバックエンドサービスとして WordPress を動かす。考えた構成はこんな感じ。(考えたってほどの構成ではない。誰がやってもこうなる系)
今までは CentOS を使っていたのだが、なんとなく最近の赤帽帝国の不穏な雰囲気を感じているため、新たな OS は Ubuntu 20.04 を採用。
Ubuntu 20.04 および Docker/Docker Compose のインストールは省略。
リバースプロキシ&Let’s Encrypt SSL
まずはリバースプロキシ&Let’s Encrypt SSL証明書自動発行のコンテナ構築から。
構成ディレクトリ&ファイルは以下。
docker-compose.yml
nginx
├certs
├log
└vhost.d
└default
nginx/certs ディレクトリには Let’s Encrypt で発行した証明書関連ファイルができる。
nginx/log はアクセスログ、エラーログを出力するところ。
nginx/vhost.d は Virtual Host単位で nginx の独自設定(例えばBASIC認証とか、リダイレクト系の設定など)を置くところ。
nginx/vhost.d 配下には default というファイルがあるが、これは Virtual Host 単位の独自設定(独自設定ファイル名=FQDN)がない場合に適用される。とりあえず “client_max_body_size 500M;” とか書いて POST できるデータサイズを緩和しておく。
docker-compose.yml はこんな感じ。
version: "3.7"
services:
proxy:
image: jwilder/nginx-proxy
container_name: proxy
environment:
TZ: Asia/Tokyo
DEFAULT_HOST: ${PROXY_DEFAULT_HOST}
DHPARAM_GENERATION: "false"
ports:
- 80:80
- 443:443
networks:
- proxy-link
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/certs:/etc/nginx/certs:ro
- ./nginx/vhost.d:/etc/nginx/vhost.d
- ./nginx/log:/var/log/nginx
- proxy-dhparam:/etc/nginx/dhparam
- proxy-html:/usr/share/nginx/html
restart: always
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt
environment:
TZ: Asia/Tokyo
NGINX_PROXY_CONTAINER: proxy
DEFAULT_EMAIL: ${LETSENCRYPT_EMAIL}
networks:
- proxy-link
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./nginx/certs:/etc/nginx/certs
- ./nginx/vhost.d:/etc/nginx/vhost.d
- proxy-acme:/etc/acme.sh
- proxy-html:/usr/share/nginx/html
depends_on:
- proxy
restart: always
networks:
default:
external:
name: bridge
proxy-link:
name: proxy.internal
volumes:
proxy-dhparam:
proxy-html:
proxy-acme:
docker-compose.yml にて使用している環境変数指定用ファイルを別途作成。このあたりは複数環境でテストしたりしないなら docker-compose.yml に直接書けばいいかもね。
# Proxy
PROXY_DEFAULT_HOST=proxy.domain.example
# Let's Encrypt
LETSENCRYPT_EMAIL=foo@domain.example
注意すべきところは以下2点。
間違えやすいとか、ネット上に新しい情報があんまりなさそうなところだね。
- ボリューム “docker.sock” のところ。nginx-proxy 側は”/tmp/docker.sock” 、letsencrypt 側は “/var/run/docker.sock” とパスが微妙に異なる。うっかりコピペ放置注意。
- 環境変数 NGINX_PROXY_CONTAINER にプロキシーコンテナ名称を指定する。
本家ドキュメントも結構突き放し系。
https://hub.docker.com/r/jwilder/nginx-proxy
https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion/
WordPress
次に、WordPress。
1コンテナで完結する All in one もあるようだが、自分は無駄にこだわる 3コンテナ構成。
docker-compose.yml
nginx
├nginx.conf
└conf.d
└default.conf
wordpress
├Dockerfile
├msmtprc
└uploads.ini
nginx.conf はこんな感じ。正直どっかからのコピペで、あまり煮詰めてはいない。
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
}
default.conf も同じく動けばいいんだよ系。
server {
listen 80 default_server;
server_name _;
server_tokens off;
root /var/www/html;
index index.php index.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(.+)$;
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
client_max_body_size 500M;
}
WordPress コンテナにメール送信できるソフトウェアが入っていないため、msmtp を別途インストールするためビルドする。Dockerfile はこんな感じ。
FROM wordpress:php8.0-fpm
RUN apt-get update \
&& apt-get install -y msmtp msmtp-mta \
&& apt-get clean
COPY ./msmtprc /etc/msmtprc
RUN chown www-data.www-data /etc/msmtprc
RUN chmod 600 /etc/msmtprc
COPY ./uploads.ini /usr/local/etc/php/conf.d
RUN chown www-data.www-data /usr/local/etc/php/conf.d/uploads.ini
RUN echo 'sendmail_path = "/usr/sbin/sendmail -t"' > /usr/local/etc/php/conf.d/mail.ini
msmtprc … msmtp でメール送信する際の設定ファイル。イマドキは必ず送信認証があるだろうからアカウント設定が必要。
# Set default values for all following accounts.
defaults
auth on
tls on
tls_starttls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
aliases /etc/aliases
logfile -
# Gmail
account yok
host mail.domain.example
port 587
from noreply@domain.example
user noreply
password hogehoge
# set a default account
account default : yok
uploads.ini … PHP の追加設定ファイル。でかいファイル Upload したい人向けの変更など。
memory_limit = 512M
upload_max_filesize = 500M
post_max_size = 500M
max_execution_time = 600
上記各ファイルを前提とした、docker-compose.yml はこちら。
version: "3.7"
services:
wordpress-db:
image: mariadb
container_name: wordpress-db
environment:
TZ: Asia/Tokyo
MYSQL_ROOT_PASSWORD: ${WORDPRESS_MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${WORDPRESS_MYSQL_DATABASE}
MYSQL_USER: ${WORDPRESS_MYSQL_USER}
MYSQL_PASSWORD: ${WORDPRESS_MYSQL_PASSWORD}
networks:
- wordpress-link
volumes:
- wordpress-db-data:/var/lib/mysql
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
wordpress:
build: ./wordpress
container_name: wordpress
environment:
TZ: Asia/Tokyo
WORDPRESS_DB_HOST: wordpress-db
WORDPRESS_DB_NAME: ${WORDPRESS_MYSQL_DATABASE}
WORDPRESS_DB_USER: ${WORDPRESS_MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${WORDPRESS_MYSQL_PASSWORD}
networks:
- wordpress-link
volumes:
- wordpress-www-data:/var/www/html
depends_on:
- wordpress-db
restart: always
wordpress-web:
image: nginx
container_name: wordpress-web
environment:
TZ: Asia/Tokyo
VIRTUAL_HOST: ${WORDPRESS_VIRTUAL_HOST}
VIRTUAL_PORT: ${WORDPRESS_VIRTUAL_PORT}
LETSENCRYPT_HOST: ${WORDPRESS_VIRTUAL_HOST}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
LETSENCRYPT_TEST: ${WORDPRESS_LETSENCRYPT_TEST}
CERT_NAME: ${WORDPRESS_CERT_NAME}
networks:
- proxy-link
- wordpress-link
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
- wordpress-www-data:/var/www/html
depends_on:
- wordpress
restart: always
networks:
default:
external:
name: bridge
proxy-link:
external:
name: proxy.internal
wordpress-link:
name: wordpress.internal
volumes:
wordpress-www-data:
wordpress-db-data:
環境設定。
# WordPress MariaDB
WORDPRESS_MYSQL_ROOT_PASSWORD=hogehoge
WORDPRESS_MYSQL_USER=root
WORDPRESS_MYSQL_PASSWORD=hogehoge
WORDPRESS_MYSQL_DATABASE=wordpress
# WordPress nginx
WORDPRESS_VIRTUAL_HOST=www.domain.example
WORDPRESS_VIRTUAL_PORT=80
WORDPRESS_LETSENCRYPT_TEST=false
WORDPRESS_CERT_NAME=www.domain.example
ここで、WORDPRESS_LETSENCRYPT_TEST を true にして WORDPRESS_CERT_NAME を default としておくとテスト証明書発行になる。本物の発行は何回か失敗すると暫く発行できなくなったりするので、最初はテスト証明書で確認したほうが無難。
nginx-proxy および letsencrypt が wordpress コンテナ起動を検知して、VIRTUAL_HOST VIRTUAL_PORT LETSENCRYPT_HOST LETSENCRYPT_EMAIL LETSENCRYPT_TEST CERT_NAME 各変数の値をもとにリバースプロキシの設定や証明書自動発行(更新チェック)などを行ってくれる。便利。素晴らしい。神。
本格的に運用するとなると、各コンテナの各種ログを集約管理するとか、各ボリュームの定期バックアップとか、いろいろあるが、とりあえず別の記事としていずれ。