ゼロから始めない Docker + WordPress ハンズオン
Docker概要
コンテナとかハイパーバイザーとか言われてもよくわからない。とりあえず動かしたほうが理解が早まりそうだと考える人のために。
試行錯誤しながらハンズオンで書いてみて手に馴染ませたい! という人へ向けた記事。
VSCode を使ってやっていきます。
動作環境は WSL2 の Ubuntu。以下の記事でセットアップした前提で進んでいきますが、Ubuntu ならだいたい大丈夫なはずです。
WSL2 + Docker + Docker Compose V2 セットアップ
対象読者
- Docker のことがなんとなくわかってる
- Docker の環境がある
- PHP の知識が少しある
mkdir
,ls
,cd
などの基本的な Linux コマンドを理解できる
到達目標
- Docker を使ってWordPress 環境を構築できる
制約
- Docker Image には以下の2つを使い、WordPress 同梱のものは使用しない
- php apache 同梱の PHP イメージ
- mysql 公式イメージ
コンテナの準備
まずは今回のハンズオン用にディレクトリを作成し、その中に入る。
mkdir docker-wordpress
cd docker-wordpress
ハンズオン用のディレクトリで VSCode を起動する。(ほかにあればお好みのエディタで)
code .
PHP の Dockerfile を作成する
docker-wordpress
ディレクトリに docker ディレクトリ、さらにその中に php ディレクトリを作成し、さらにその中に Dockerfile という名前のファイルを作成する。
docker/php/Dockerfile
に以下のような内容を記載する。
FROM php:8.2-apache
COPY ./html/ /var/www/html/
FROM には Docker Image の名前やバージョンを指定したりします。
この場合、簡単にいうと PHP v8.2 がすぐ動くサーバーが同梱された Docker Image が使える。
PHP の動作確認
複数のコンテナをいい感じに管理するための設定ファイルである docker-compose.yml を作成する。
docker-compose は本来複数のコンテナを管理するためのものだが、MySQL コンテナに関しては一旦後回しにして、PHP が動くかどうか確認していく。
docker-compose.yml という名前でファイルを作成し、以下の内容を記載する。
version: "3.9"
services:
web:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./html:/var/www/html
ports:
- 8080:80
適当に PHP ファイルを作る。 html/index.php
ファイルを作成する。
<?php echo "Hello World!" ?>
ディレクトリ構成は以下のようになった。
├── docker
│ └── php
│ └── Dockerfile
├── docker-compose.yml
└── html
└── index.php
ここで試しに以下のコマンドを叩いて、Docker コンテナの PHP が正しく動作しているか確認する。
docker compose up -d
するとコンテナが起動し、http://localhost:8080 をアクセスしたときに index.php の内容が表示されるようになる。
試しに内容を変えてページを更新してみると、もちろん表示内容が変わる。
<?php echo "Hello Docker!" ?>
動作確認が済んだら、以下のコマンドでコンテナを終了しておく。
docker compose down --remove-orphans
--remove-orphans オプションはなくてもいいのですが、とりあえずつけておくとよいです。
DB コンテナを用意する
PHP の動作確認が済んだので、MySQL がインストールされたコンテナを用意する。
docker/mysql/Dockerfile
を作成して以下を記載する。
FROM mysql/mysql-server:8.0
本当はもっと my.cnf を用意してマウントしたり、なんやかんや記述したほうがいいのですが、ここでは最小限にとどめます。
環境変数を管理するために .env
ファイルを作る。
DB_PORT=3306
DB_NAME=wordpress_db
DB_USER=wordpress_user
DB_PASS=wordpress_password
git で管理する場合、.env は .gitignore して git 管理から外すように。
今ディレクトリはこんな感じになった。
├── docker
│ ├── mysql
│ │ └── Dockerfile
│ └── php
│ └── Dockerfile
├── .env
├── docker-compose.yml
└── html
└── index.php
docker-compose.yml を以下のように変更する。
version: "3.9"
services:
web:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./html:/var/www/html
ports:
- 8080:80
db:
build:
context: .
dockerfile: ./docker/mysql/Dockerfile
ports:
- 3306:${DB_PORT}
volumes:
- db-store:/var/lib/mysql
environment:
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASS}
- MYSQL_ROOT_PASSWORD=${DB_PASS}
volumes:
db-store:
.env に記載した内容を ${変数名} のように書くと、コンテナの中の環境変数として持っていくことができる。
この状態でもう一度以下のコマンドを叩くと Docker コンテナがビルドされて再起動する。 ちなみに、Dockerfile や docker-compose.yml のような、Docker に関わるファイルを変更した際には、docker compose build をする必要がある。
docker compose build
その後、もう一度立ち上げてから
docker compose up -d
コンテナを確認してみると、web コンテナと db コンテナの2つが立ち上がっていることが分かる。
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-wordpress-db-1 docker-wordpress-db "/entrypoint.sh mysqld" db 12 seconds ago Up 11 seconds (health: starting) 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060-33061/tcp
docker-wordpress-web-1 docker-wordpress-web "docker-php-entrypoint apache2-foreground" web 12 seconds ago Up 11 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp
MySQL の動作確認
一応 DB コンテナのテストもすることにする。
以下のコマンドで DB コンテナの中に入ると、DB コンテナ内の bash が操作できる。
docker compose exec db bash
コンテナの中の bash で、以下のコマンドを叩く。
mysql -u wordpress_user -p
パスワードが要求されるので、先ほど .env に設定した wordpress_password
と入力する。
するとこんな感じに mysql のコマンドラインに切り替わった。
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.32 MySQL Community Server - GPL
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
試しに以下のコマンドでデータベース一覧を表示すると、事前に環境変数に入れておいた wordpress_db
が作成されていることが分かる。
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| wordpress_db |
+--------------------+
3 rows in set (0.01 sec)
Ctrl + D
で MySQL コマンドラインやコンテナが出ることができる。
Makefile を作る
そろそろコマンドを叩くのがめんどくさくなってきたので、Makefile を作成する。
Makefile
というファイル名のファイルを作成する。
up:
docker compose up -d
down:
docker compose down --remove-orphans
web:
docker compose exec web bash
db:
docker compose exec db bash
すると以下のようにコマンドを省略することができる。
docker compose up -d
↓
make up
make コマンドを使えるようにするには、以下のコマンドを叩けば OK。
sudo apt-get update
sudo apt install build-essential -y
WordPress をインストールする
DB コンテナも用意できたので、WordPress を用意してインストールする
ここでは WordPress 同梱の Docker Image をあえて使っていないので、wget コマンドでインストールすることにする。
が、 この web コンテナは wget コマンドを利用できない。
ということで、docker/php/Dockerfile
に wget をインストールするコマンドを追記した。
FROM php:8.2-apache
# wget インストール
RUN apt update \
&& apt install wget
COPY ./html/ /var/www/html/
そして Docker に関わるファイルを変更したので、一旦ビルドし直す。
docker compose build
ビルドが済んだら、もう一度コンテナを起動する。さっそく先ほど作成した Makefile で自作したコマンドを使ってみる。
make up
起動した web コンテナに入る。
make web
カレントディレクトリが /var/www/html
であることを確認して、先ほどお試しで作った index.php を削除しておく。
rm -f index.php
以下のコマンドを叩いてダウンロード。
wget https://ja.wordpress.org/latest-ja.tar.gz
そして tar コマンドでファイルを展開。
tar -zxvf latest-ja.tar.gz
アーカイブの内容が wordpress ディレクトリという名前で展開されるので、その中身を html 直下に取り出しておきます。
mv ./wordpress/* .
www-data を所有者にしておく。(これはあとで面倒なことになるのでのちほどなかったことにするのですが、こうしておかないと WordPress が動かないので変えておきます)
chown -R www-data:www-data /var/www/html/
最後に、アーカイブと空の wordpress ディレクトリが不要になったので削除する。
rm -rf latest-ja.tar.gz wordpress
この状態で、 http://localhost:8080 にアクセスすると、WordPress の画面が……と言いたいところですが、「mysqli PHP 拡張機能がインストールされ、有効になっていることを確認してください。」というメッセージが表示されています。
なので mysqli PHP 拡張機能というものを有効にします。
docker/php/Dockerfile
を以下のように変更してもう一度ビルド。
FROM php:8.2-apache
# wget インストール
RUN apt update \
&& apt install wget
# mysql 拡張インストール
RUN apt-get update \
&& apt-get install -y libpq-dev \
&& docker-php-ext-install pdo_mysql pdo_pgsql mysqli
COPY ./html/ /var/www/html/
docker compose build
make up
これでもう一度 http://localhost:8080 にアクセスすると、いつものようこそ画面が現れる。
データベース名やらデータベースのユーザ名は、 .env に設定した内容でいいのですが、ホスト名は localhost ではなく、 db と入力します。 docker-compose.yml に記載してある service 名が db であり、ホスト名として使われるからです。
インストールが終わってユーザー登録が完了すると、ダッシュボードへ入ることができた。
パーミッションの修正
実はこの状態だと、VSCode 側からの編集が不可能になっている。
www-data というユーザがファイルの所有権をもっていて、パソコンの利用者である僕たちに書き込み権限がない。
ただこの www-data にも読み書き権限を与えておかないと、WordPress のインストールもできないし、プラグインを入れたりすることもできない。
なので先ほど www-data に chown コマンドで所有権を移した。
これを「WordPress での操作も支障がなくて、エディターからの操作に支障がない」という状態にする。
まず、自分の PC ユーザーの ID を確認する。
Docker コンテナから出た状態で、以下のコマンドを叩く。
id $USER
すると自分のユーザーの uid,gid,groups が確認できる。たいていの場合、uid は 1000 だと思うので、1000という前提で進めていく。
一旦コンテナを終了しておく。
make down
ホストマシン上で、再帰的にファイルの所有者を自分に戻す。
sudo chown -R $USER:$USER html
docker/php/Dockerfile を以下のように編集する
FROM php:8.2-apache
ARG uid
ARG gid
ENV username=coder
# ユーザー作成して、 www-data を coder のグループに追加する
RUN groupadd -g $gid $username \
&& useradd -u $uid -g $username -s /bin/bash $username \
&& gpasswd -a www-data $username
# wget インストール
RUN apt update \
&& apt install wget
# mysql 拡張インストール
RUN apt-get update \
&& apt-get install -y libpq-dev \
&& docker-php-ext-install pdo_mysql pdo_pgsql mysqli
COPY ./html/ /var/www/html/
# ディレクトリおよびファイルの所属グループに読み書きと実行の権限を与え
# 所有者を coder にする
RUN chmod -R 774 /var/www/html/ \
&& chown -R $username:$username /var/www/html/
# コンテナを coder として起動する
USER $username
.env に以下を追記する。
UID=1000
docker-compose.yml を以下のように変更する。
version: "3.9"
services:
web:
build:
context: .
args:
uid: ${UID}
gid: ${UID}
dockerfile: ./docker/php/Dockerfile
volumes:
- ./html:/var/www/html
ports:
- 8080:80
db:
build:
context: .
dockerfile: ./docker/mysql/Dockerfile
ports:
- 3306:${DB_PORT}
volumes:
- db-store:/var/lib/mysql
environment:
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASS}
- MYSQL_ROOT_PASSWORD=${DB_PASS}
volumes:
db-store:
再度ビルドして立ち上げ直す。
docker compose build
make up
これでエディターからも編集することができ、WordPress ダッシュボード上からプラグインを入れたり、メディアをアップロードしたりすることもできるようになる。
試しに以下のコマンドで web コンテナに入り、所有者と所属グループを確認してみると、こんな感じ。
make web
ls -la
これで
- ホストマシンで編集している僕らと coder の UID が同じなのでコンテナ内部でも同じ扱いになる
- www-data はこのグループに所属している
- coder グループに所属している人が実行も読み書きも変更もできる。
という条件が整って、やりたいことが完了した。
ただ、パーミッションの管理がずさんだと、思わぬ攻撃を受ける可能性がある。
今回はあくまで「開発環境」なので、セキュリティリスクはまったく考慮していないということをご承知ください。
広告