DockerとWord Pressをインストール
くじらの絵が可愛いのでずっと気になっていたDocker。Word PressはDockerでやるのが簡単だと見聞きしたので、DockerもWord Pressも初心者な筆者が、 docker docs:「Docker Engine インストール(Debian 向け)」を参考にしてDebian11(bullseye)環境でDockerとWord Pressをインストールしてみます。
インストールの準備
まず古いバージョンがあったらアンインスト―ルします。かつてはdocker、docker.io、docker-engineという名前で、今はdocker-ceと呼ぶそうです。
一緒に指定しているruncはOCF(Open Container Format)で稼働しているアプリケーションパッケージ用のコマンドラインクライアントです。
Dockerには、aptのリポジトリとは別に、専用のリポジトリがあります。そこへapt経由で参照できるようにします。その際https通信をするので古いバージョンのaptでは、apt-transport-httpsのインストールが必要になるかもしれません。buster以降のバージョンのaptなら多分デフォルトでhttpsサポートがあるので問題ないです。
他、Dockerのリポジトリへ接続するためにインストールが必要なのはca-certificates(SSLベースのアプリケーションが相手先を確認するのに利用されます)、curl(URLを指定してデータを取得する)、GnuPG(暗号化とデジタル署名の作成)、lsb-release(Linux Standard Base バージョン報告ユーティリティ)をインストールします。
curlでGPG鍵を取得します。この時のオプションは、f(サーバーエラー時何も出力しない)、s(ステータスバー非表示)、S(s設定時に失敗でエラーメッセージ表示)、L(ページが移動に従う)となっています。
取得した鍵はGnuGPGの拡張であるASCII armorの公開鍵をほどいて(--dearor)、oオプションで指定した場所に保存します。
ちなみにASCII armorの状態は次のような感じになっています。
-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFit2ioBEADhWpZ8/wvZ6hUTiXOwQHXMAlaFHcPH9hAtr4F1y2+OYdbtMuth lqqwp028AqyY+PRfVMtSYMbjuQuu5byyKR01BbqYhuS3jtqQmljZ/bJvXqnmiVXh 38UuLa+z077PxyxQhu5BbqntTPQMfiyqEiU+BKbq2WmANUKQf+1AmZY/IruOXbnq L4C1+gJ8vfmXQt99npCaxEjaNRVYfOS8QcixNzHUYnb6emjlANyEVlZzeqo7XKl7 UrwV5inawTSzWNvtjEjj4nJL8NsLwscpLPQUhTQ+7BbQXAwAmeHCUTQIvvWXqw0N cmhh4HgeQscQHYgOJjjDVfoY5MucvglbIgCqfzAHW9jxmRL4qbMZj+b1XoePEtht ...
これを--dearmorするとバイナリファイルになりますが、pgpdumpを用いて可視化すると次のようになります。
# pgpdump /usr/share/keyrings/docker-archive-keyring.gpg Old: Public Key Packet(tag 6)(525 bytes) Ver 4 - new Public key creation time - Wed Feb 22 08:36:26 HST 2017 Pub alg - RSA Encrypt or Sign(pub 1) RSA n(4096 bits) - ... RSA e(17 bits) - ... ...
この鍵はDockerレポジトリとの暗号化通信の際に使われます。
似たような言葉が乱立してわかりづらいですが、PGPはもともと有償のパッケージで、それをOpenにしたものがOpenPGPそこから派生したものが、GnuPG、gpgはOpnePGP暗号化・署名パッケージです。
そのあと参考サイトでは次のようにな呪文みたいなコマンドを紹介しています。
これは単にOSのバージョン(コードネーム)等を取得して、/etc/apt/sources.list.d/docker.listに次のような記述をしたいだけです。マニュアル作成しても構いません。ちなみにteeして/dev/nullに捨てている理由は、sudo環境でリダイレクトを管理者権限で処理したいからです。
/etc/apt/sources.list.d/docker.list
deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bullseye stableDockerのインストール
source.listに変更を加えたので、アップデートした後、dockerのパッケージをインスト―ルします。これらは通常のaptのパッケージリストにはありません。
# apt update # apt install docker-ce docker-ce-cli containerd.io
インストールが終えたら、テストしてみます。docker runで指定したコンテナがない場合、自動的にpullされます。
# docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete ....
アンインストールは先のパッケージを削除したのち、/var/lib/dockerと/var/lib/containerdのディレクトリを削除します。このディレクトリにはイメージやコンテナ、設定ファイル等が含まれます。
Docker Compose
今度はDocker Composeのインストールと設定を行います。
Docker Composeは複数のコンテナを定義して実行するDockerアプリケーションの為のツールです。これには名前の固定されたふたつのファイルが使われます。アプリケーション環境はDockerfileに定義し、アプリケーションを構成するサービスをdocker-compose.ymlというYAMLファイルに定義します。
先の参照サイト通りにプロジェクトのディレクトリを作りPythonのコードを書きます。ここで利用されているFlaskはPythonのウェブアプリケーションインターフェース、Redisはインメモリのキーバリューストア型データベースです。
ちなみにPythonのコードを触った事ない人向けの話をすると、Pythonではインデント(字下げ)によって関数の範囲を認識するので注意してください。
app.py
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello! I have seen {} times.\n'.format(count)
if __name__=="__main__":
app.run(host="0.0.0.0", debug=True)
次に、プロジェクト上にrequirements.txtというファイルを作成して次のように記述します。
requirements.txt
flask redis
さらにDockerイメージを構築する、Dockerfileという名前のファイルを作成します。このイメージにはプロジェクトで使うものすべてを含ませます。
Dockerfile
FROM python:3.4-alpine ADD . /code WORKDIR /code RUN pip install -r requirements.txt CMD ["python","app.py"]
このファイルで次のような指示をDockerに伝えています。
- Python 3.4イメージを使って、イメージを構築する
- カレントディレクトリ(.)をイメージ内のパス/codeに加える
- 作業用ディレクトリを/codeに指定する
- 起動後、pipというPython用のパッケージ管理ツールを起動する。
pipに与えたパラメータで、requirements.txtファイル内に記述されたflaskとredisをインストールするという指示になっています。
- コンテナに対するデフォルトのコマンドを、python app.pyにする。
もうひとつのDocker Compose用の設定ファイルであるYAMLファイルを、docker-compose.ymlという名前で作成します。YAMLファイルも書式に癖がありますので注意してください。-は行頭を意味したり、:の後に文字を続けるには空白が欲しかったりします。
docker-compose.yml
version: "3.7"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
ここではwebとredisというふたつのサービスを定義しています。
webサービスはカレントディレクトリにあるDockerfileイメージから構築されます。その際利用されるコンテナの公開用ポート5000番をローカルマシンの5000番にポートフォワードします。これはFlaskWebサーバーのデフォルトポートです。
redisサービスでは、Docker Hubレジストリから取得したRedisイメージを利用する設定になっています。先にpythonのpipでインストールしたredisはpythonからredisを利用するための機能で、redis本体ではありません。本体はこの設定により利用可能になります。
Docker Composeの操作
Dockerfileやdocker-compose.ymlを配置したディレクトリで、docker-compose upコマンドを実行すると、アプリケーションが実行されます。
この時、実行ユーザがdockerのグループに入っていない(実行権限がない)場合や、dockerのサービスの起動が失敗している場合は次のようなエラーになります。
ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running? If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
先に例示したアプリケーションではブラウザを使ってDockerを動かしているサーバーの5000番ポートにアクセスするとサンプルプログラムの稼働状況が確認できると思います。
このアプリケーションでは表示した回数をredisのインメモリデータベースに保存するので、リロードするたびに数値がカウントアップされていきます。
バインドマウント
先のdocker-compose.ymlのwebのエントリーにvolumeのエントリーを加えて次のようにします。
docker-compose.yml
version: "3.7"
services:
web:
build: .
ports:
- "5000:5000"
voluems:
- .:/code
redis:
image: "redis:alpine"
これはカレントディレクトリ(.)を/codeディレクトリにマウントする設定です。こうすることでイメージを再構築することなく、実行中のコードを修正できます。
ほかのコマンド
- docker-compose up -d
docker-compose upにdオプションを付けるとバックグラウンドで実行するようになります。
- docker-compose stop
docker-compose up -dで稼働させたサービスと停止させたい場合はstopを使います。
- docker-compose down
コンテナを完全に削除してすべてを終わらせる場合はdownを使います。この時--volumesを指定すれば、ここではredisコンテナで利用されるデータファイルも削除されます。
- docker-compose ps
現在稼働しているものを確認できます。
ちなみに、イメージの一覧を出力させたい場合は「docker image ls」とします。
- docker-compose run xxx yyy
指定したサービスxxx(ここではweb等)に対して、yyyコマンドを実行します。
- docker-compose --help
ヘルプを表示します。
Word Pressのインストール
Word Pressをインストールするには、プロジェクトディレクトリを作成し、次のdocker-compose.ymlファイルを配置します。
docker-compose.yml
version: "3.7"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
volumes:
- ./wordpress:/var/www/html
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
dbのイメージにmysql:5.7(MySQL 5.7)を使う設定になっています。
MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORDはMySQLの設定ですので環境にあわせて変更します。
wordpressサービス側にあるWORDPRESS_DB_HOSTは、dbと名付けたサービス(MySQL:5.7)で、3306番ポートを使う設定です。このサービスに依存するので、depends_onエントリーで、dbサービスを指定しています。DB_USERとDB_PASSWORDはmysql側で設定したものと同値にします。
さきほどはコンテナ外のディスク領域をマウントする際に使いましたが、volumeはコンテナが終了した後でもデータを残す機能を持っています。
下線を引いたvolumesの部分では、db_dataというvolume領域を定義しています。ここで定義した領域をserviceのdbで指定しています。db_dataにコンテナ内のmysqlの保存領域である/var/lib/mysqlを結びつけています。
こうして定義しておくとコンテナ内で更新された/var/lib/mysqlにあるデータは、--volumesオプションをつけてdocker downを実行しない限り保存されます。
portsの設定では、ホスト側の8000番に、コンテナのWebアプリ(80番)を結びつけています。
Dockerのサイトには載っていたサンプルの設定だと、データベースに保存する以外の編集項目がコンテナの終了とともに消されてしまうので、wordpressサービスのエントリーにvolumesのエントリーを作成し、ローカル環境の./wordpressディレクトリに残すように設定します。
wordpressディレクトリの永続化は、初期イメージから構築する場合は問題ないですが外からデータをコピーしてくる際はちょっとした修正が必要です。ユーザー名やパスワード、データベース名はもちろんそうですが、wp-config.phpの「DB_HOST」の設定をDockerのYAMLファイルで設定する「WORDPRESS_DB_HOST」の値に修正する必要があります。この例ではDB_HOSTの値は「db:3306」とします。またDockerのコンテナ内に存在するオリジナルのwp-configは一度Dockerの環境変数を取得するようにできています。
これらの設定はオブジェクトの広場:「さわって理解する Docker 入門」や、Keruuweb:「Docker: WordPressを永続化する方法」を参考にさせていただきました。
設定は以上です。この状態で「docker-compose up -d」を実行します。
あとは、ブラウザからDockerが動いているマシンの8000番ポートにアクセスします。するとWord Pressがの稼働した状態になっていますので、ウィザードに従ってインストールを完了させます。
参考にさせていただきましたサイトの皆様、ありがとうございました。