※スマホ対応はしてません。

タグ: Docker Compose

Docker公式イメージでWordPress環境を用意する。

カテゴリー: サーバー

library/wordpress が公式に提供されているのを昨日知りました。WWW+PHP+WordPressなパッケージみたい。DBは library/mysql を使うとして、この二つでさっくり環境が用意できました。

$ docker run --rm -d --name my-mysql -e MYSQL_ROOT_PASSWORD=passwd -v `pwd`/db:/var/lib/mysql mysql
$ docker run --rm -d --name my-wordpress --link my-mysql:mysql -p 80:80 -v `pwd`/wp:/var/www/html wordpress

これで http://localhost を開くと、WordPressの初期設定が始まります。DBの初期処理にちょっと時間がかかるので、エラーが出てもちょっと待ってて開きなおしたりしてください。

終了は

こう。

$ docker stop my-mysql my-wordpress

Windowsは

pwd の代わりに %CD% を使います。

$ docker run --rm -d --name my-mysql -e MYSQL_ROOT_PASSWORD=passwd -v %CD%/db:/var/lib/mysql mysql
$ docker run --rm -d --name my-wordpress --link my-mysql:mysql -p 80:80 -v %CD%/wp:/var/www/html wordpress

後述のDocker Composeを使うと書き分ける必要がなくなります。

変数的なもの

以下の値は適宜変更してください。

  • my-mysql … MySQLコンテナの名前。
  • my-wordpress … WordPressコンテナの名前。
  • passwd … DBのパスワード。開発用となら適当でいいんじゃないの。
  • 80 … ポート番号。 : で分けて左辺は任意。右辺は 80 で固定。
  • pwd/db, pwd/wp … 生成ファイルを配置するディレクトリ。絶対パス(フルパス)にする。

DBやアップロードしたファイルの行方

-v pwd/db:/foo 的な記述のおかげで、コマンド実行時の作業ディレクトリ直下に db, wp の二つのディレクトリが作成されるはずです。これらを保存しておいて、次回も -v で指定します。

新しい環境にする場合はここをさくっと変えればよろしい。

wordpressイメージ

安心安全のDocker公式イメージです。

PHPとApacheが含まれたイメージを元に作成されているみたい。(ものによるけど。) DB以外が揃ってるので簡単に始められる。ありがとう、ありがとう。

WordPressのバージョン

tagsのページを見ると4.8.3, 4.8.2の二つが用意されているっぽい。

でも docker pull wordpress:3 とかで普通に落ちてくるし使えるので、試してないけど一通り用意されてるんじゃないでしょうか。知らんけど。

あるいは、Dockerfileは前述の通り公開されてます。やっぱり試してないんだけど、こいつの WORDPRESS_VERSION の数字をいじるだけで他のバージョンに対応したやつも作れるんじゃないすかね。知らんけど。

バリエーション

例えばこんなタグがあります。

  • 4.8.3-php7.1-fpm-alpine
  • 4.8.2-php5.6-apache
  • cli-1.4.0-php7.1

なんか色々あるみたいなので公式ドキュメントを読んで、良さそうなものを見つけてください。

単純にWordPressのバージョンを指定するだけだと、PHP5.6とApacheとの組み合わせになるみたいです。(古いバージョンについて調べてないです。)

“cli” については次項。

WP-CLI

こちらさまね。

wordpress:cli でCLIも使えます。

$ docker run --rm -ti --volumes-from my-wordpress --link my-mysql:mysql wordpress:cli plugin list
+---------+----------+-----------+---------+
| name    | status   | update    | version |
+---------+----------+-----------+---------+
| akismet | inactive | available | 4.0     |
| hello   | inactive | none      | 1.6     |
+---------+----------+-----------+---------+

あら便利。

話には聞くけど使ったことはないです。ちゃんと動くよね? 大丈夫?

ところでこれって、

ものが全然違うから将来分割されるんじゃないかなあ。 wp-cli みたいなのに。あ、まんまだ。それとも、サーバの方もなんかいろいろあるし、これでいいんだろか。

自分が作ったテーマを別途追加する

実践編。

たぶん個別にGitで管理したりしてると思うので、そういうのは別々に追加していきましょう。

-v ないし --volume で指定します。 : の左側にテーマのディレクトリ(絶対パス)、右側に配置先、つまり /var/www/html/wp-content/themes/xxx 的なやつを書きます。

$ docker run --rm -d --name my-wordpress --link my-mysql:mysql -p 80:80 \
-v `pwd`/wp:/var/www/html \
-v `pwd`/my-great-theme:/var/www/html/wp-content/themes/my-great-theme \
-v /path/to/my-wonderful-theme:/var/www/html/wp-content/themes/my-wonderful-theme \
wordpress

(さすがに長いので改行しました。)

-v でもっと追加してもいいですよ。

とはいえこんな長えのを毎回ぽちぽちしてらんねえーので、Docker Composeを使います。(シェルスクリプトが好きならそっちでも良いと思う。)

Docker Composeにする

相対パス使えて便利ね。

 # docker-compose.yml
version: "3"

services:

  wp:
    image: wordpress
    ports:
      - "80:80"
    volumes:
      - ./wp:/var/www/html
      - ./my-great-theme:/var/www/html/wp-content/themes/my-great-theme
    depends_on:
      - db

  db:
    image: mysql
    volumes:
      - ./db:/var/lib/mysql
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
      MYSQL_DATABASE: wordpress
      MYSQL_USER: username
      MYSQL_PASSWORD: password

これで起動すれば “Database Host”を “db” にする以外はそのままぽちぽちいけるはずです。

$ docker-compose up

終了は Ctrl+C で。

envが増えてしまうのが謎。いやDocker直でやったらいらない方が謎か。

きっとありがちなエラーとトラブルシュート

名前が被った

docker: Error response from daemon: Conflict. The container name “/my-wordpress” is already in use by container “0c38694fb63ec30c7e5c1a2140489055dec35a3e6b6031af81be4b591e089ec1”. You have to remove (or rename) that container to be able to reuse that name.

その名前( --name で指定したもの)は既に稼働中です。他の名前を付けるか、現在稼働中のものを停止してください。

たぶん停止し忘れ。

ポートが使用中

docker: Error response from daemon: driver failed programming external connectivity on endpoint my-wordpress2 (87a56c6aaaf8adc1a12dcfa26a0f18917bf9fc4809a65726a5eb47d39ad0b3b9): Bind for 0.0.0.0:80 failed: port is already allocated.

そのポート( -p で指定したもの)は既に稼働中です。他の番号を使うか、現在稼働中のものを停止してください。

先の例では80番で起動したけど、例えば8080番で起動する場合はこう。

$ docker run --rm -d --name my-wordpress --link my-mysql:mysql -p 8080:80 -v `pwd`/wp:/var/www/html wordpress

そしてポート番号を指定して http://localhost:8080 みたいにして開いてください。

MySQLを起動していない

docker: Error response from daemon: could not get container for my-mysql: No such container: my-mysql.

先に docker run ... mysql 的なアレを実行して、MySQLのコンテナを用意してください。その後WordPressを起動。

db, wp ディレクトリが作られない

例えば相対パスは使えません。

こちら駄目な例。

$ docker run --rm -d --name my-mysql -e MYSQL_ROOT_PASSWORD=passwd -v ./db:/var/lib/mysql mysql
$ docker run --rm -d --name my-wordpress --link my-mysql:mysql -p 80:80 -v ./wp:/var/www/html wordpress

絶対パスで書くか、冒頭のように pwd や %CD% を利用します。

pwd 周りに使えない記号が含まれている。

docker: Error response from daemon: create `pwd`/wp: “`pwd`/wp” includes invalid characters for a local volume name, only “[a-zA-Z0-9][a-zA-Z0-9_.-]” are allowed. If you intended to pass a host directory, use absolute path.

Windowsだと pwd が使えないです。本記事冒頭参照。

localhostに繋がらない

初回ならたぶんMySQL待ちです。

念のためdockerの状況見ときましょうか。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
730219bd4919        wordpress           "/entrypoint.sh ap..."   6 seconds ago       Up 29 seconds       0.0.0.0:80->80/tcp   my-wordpress
29d4002b011b        mysql               "docker-entrypoint..."   15 seconds ago      Up 38 seconds       3306/tcp             my-mysql

一覧右端 “NAMES” に my-wordpress が出てくれば大丈夫。のはず。

DBエラー

Error establishing a database connection

たぶん前項と同じ。

あるいはイメージのバージョンを変えちゃったとか。それならバージョンを戻すか作り直し。

イメージを変えたのにWordPressのバージョンが変わらない

ちゃんと db, wp のディレクトリを新しいのにしました?

書いてる人について

WordPressは仕事で使ったことないですのでそこらへんの温度感についてはお察しください。

Docker入門みたいなやつやってみたよ。(下書き供養 Advent Calendar 2018 – 05日目)

カテゴリー: サーバー

この記事は下書き供養 Advent Calendar 2018の05日目の記事です。

というわけで公開は2018年12月05日ですが、書いたのは2017年06月です。記事の日付は後者の方を設定しました。ちなみに開催はもうちょっと前で2017年04月でした。あらやだ怠惰。

当日利用したリソース群はこちらにまとまってます。

ちなみにWordPressやるならその名の通り library/wordpress というDocker公式イメージが公開されてるので、そっち使う方が楽だと思います。

(以下、下書きの状態であったもの。書きあがってるっぽいのでそのまま。)


当方初心者なんだけど、まわりにやってる人が少なくて、利用者が増えたらいいなーそんでもって誰か詳しくなっておれに教えてくれたらいいなーくらいの感じでやりました。

本当は詳しい人にも来てもらって駄目出しされつつ進行したかったんだけど、日程が合いませんでした。先にそっち合わせとけっていう。

というわけで、やった内容を書いておきます。「利点について」→「単語と知識」→「手を動かす」という流れです。

Dockerとは何か

端的に言うと、

  • 仮想マシンです。
  • 仮想マシンじゃないです。

「使う」側からすると自分のマシン(物理)の中に別のマシンが仮想的に用意されて、その中で色々走ったりするよーっていう感じ。実際は「仮想マシン」と呼ばれる技術とは別物で、仮想ハードウェアをすっ飛ばして直接物理リソースを使うとかなんかそういう?違い?があるらしい。

あとコンテナを小分けにしてっていうのもVM方面にだけ慣れてるとすぐには出てこない発想かなーと思う。

何が嬉しいのか

VMでも何でもいいんだけど、基本的にはホストマシンと分けて環境を作れる嬉しさというものがあると思ってます。ほら汚染とかバージョン管理とかさ。

開発者向けには

  • 開発環境を簡単に用意できる
  • 実際こんな手順
    1. git clone
    2. docker-compose up
    3. やったね
  • いらない
    • Node.js, Ruby, Python, etcのインストール
    • Sass, Babel, Rails, image magic, etcのインストール
    • ウェブサーバの設定
    • ネットワークの設定(たぶん)

誰かがDocker環境を用意してくれていて、それを使うという状況です。

データベースの用意とか、 gem install sass とか、そもそも言語環境の用意とかそういうのをすっ飛ばして、一発でwatchとかローカルサーバとかを起動できます。

Docker自体もWin/MacともにGUIでインストールできるので、準備の難易度は低いかと思ってます。(でもWindowsだとHyper-Vが必須だったりするのかな? 自分は元々使ってたし、周りが皆Macなんで調べてない。)

上位開発者には

今度はDocker環境を用意する側のひと。Makefileとかnpm scriptを用意するあたりの人達。

  • 環境の詳細が文書化される
  • 環境を他の人と共有できる
  • 過去に作った環境を再利用したり拡張したりできる

自分のマシンにぽちぽちインストールして環境作って、いざそれを他の開発者にも使ってもらおうとすると、割と面倒くさかったりするじゃないすか。試行錯誤してると文書化するの億劫だし。

そういうのが全部 Dockerfile と docker-compose.yml に残るので、「えーとあれこれってどうやって入れたんだっけ?」「そもそも入れたっけ?」みたいなのがなくなります。文書に残っているので、環境の共有はそのファイルを共有するだけで事足ります。(パスワードとかの秘匿情報については別途にしても良さそう。)

あとは後から変更したり拡張したりも、残ってるのでいけるはず。

アドミンには

サーバの管理者さんとか。

  • 開発環境を簡単に用意できる
  • 本番環境を簡単に用意できる
  • 環境を簡単に複製できる

ここら辺は完全に想像です。

既存プロジェクト

をDocker化することもできるのでは。

  • 依存パッケージのインストールが不要に
    • grunt, gulp, rails, etc
  • プロジェクトのディレクトリの外からあれこれできる

プロジェクトが /home/ginpei/myproject にあったとして、 /home/ginpei/myproject-docker みたいなのを用意してそっちにDocker系ファイルを置いたりとかして、既存のものは既存のままにしておけば、簡単にできるのではないか?と思いました。

でも実際やってみたら別の問題があって、ちゃんとできるのかわかりません……、という話をしました。なんかwatchがうまく動かなかったんだけど、まあこの話はいずれ。

使ってみよう

ワークショップ前に知識の整理をしました。

使う場合

Docker本体のインストールは別にして、

  1. ファイル群をダウンロード
    • git clone
  2. コンテナ作成
    • docker-compose up

でおわり。

※ただし理想的な環境に限る

作る場合

  1. Dockerfile でコンテナを用意
  2. docker-compose.yml でコンテナ群を連携
  3. docker-compose up で起動

これだけ言ってもわからんと思うけど、こういう流れです。

単語

  • コンテナ … 仮想マシン実体的な。実際に動くもの。作って捨てる
  • イメージ … ISOイメージ的な。コンテナの素。ダウンロードしてくる。作れる
  • docker … イメージからコンテナを作成するコマンド
  • docker-compose … 複数のdockerコマンドをまとめてやってくれるコマンド
  • ボリューム … 記憶領域。コンテナを作りなおしても消えない

コンテナ vs イメージは、OOPのクラス vs インスタンスに近いかなと思ってます。

ファイル

  • Dockerfile
    • マシンひとつ分(イメージ)の設定
    • Linuxのディストリビューションとか
    • インストールするパッケージとか
  • docker-compose.yml
    • マシン間の繋がりの指定とか
      • データ専用マシンとか
    • 簡単なマシンの設定とか
    • 実マシンへの露出の設定とか
  • その他
    • Nginxの設定ファイルとか

ワークショップ

ここ↓に当日使用したやつが残ってます。

用意した環境はこんなの:

  • all/ … ダウンロードする用に色々書いただけ
  • php/ … PHP + Nginx + MySQL
  • rails/ … Ruby on Rails
  • web-front/ … gulp + sass + browser-sync
  • wordpress/ … 当日皆で一緒に作ったやつ

最初に all/ で docker-compose up してもらうと、一通りのイメージが降ってきます。皆で一斉にやるとネットワークがつらそうなので、各自自宅でやってきてもらいました。

php, rails, web-front はこちらが用意した環境を使ってみようというやつです。だいたい何もしなくても、すぐに何かが起動します……というわけにはいかなくて、 rake db:migrate とか npm install とかが必要です。今回はそれはそういうもんだということにしてやってもらいました。

最後、 wordpress は自分で docker-compose.yml をはじめ各種設定を書いて「環境を作る」を体験するやつです。構成はだいたい php と一緒。

その他話したこと

コンテナを小分けにする

Vagrantだと全部入りのマシンを用意して普通に(実マシンと同様に)あれこれする感じなんだけど、Dockerないしコンテナ云々の技術大系ではばらばらに用意してからネットワークで繋げていく、みたいな感じらしい。疎結合って言えるのかな。

全部入りにしない利点はよくわかってないです。一番大事なところなんだろうけど。たぶん、イメージ再構築のコストを減らすとかそういうところなのかなって想像してます。そのうち調べる。公式ドキュメントに書いてあったのは覚えてる。

バージョンを固定する

ビルドするたびに「同じ」環境になってほしいよね、なのでイメージのバージョン指定に latest はやめましょう、と。

イメージとコンテナ、そしてボリューム

イメージはダウンロードしてきて長いことファイルに保存されます。コンテナは使うたびに新規作成して、使い終わったら削除されます。

OOPでいうところのクラスとインスタンスみたいな関係。

削除されるということはコンテナ内でファイル編集しても元に戻っちゃうので、編集するファイルはボリュームとして残します。ボリュームにも二種類あって、ホストマシンのファイルをマウント?して使う場合と、Docker内で「これとっといてねー」みたいに指定するのとがある。

イメージとレイヤー

イメージはダウンロードしてくるだけじゃなくて、自分で Dockerfile を書いて作成できる。

イメージはでかい塊だけど、実は玉ねぎみたいに複数の層から成っている。(だから、実は docker image ls で出てくるサイズはディスクに保存されるファイルサイズと直結しない。)

基本的にひとつのレイヤーは Dockerfile の指示一行ごとに作成される。なので、一時ファイルを作成するような指示は一行の中でその削除までするのが好ましい。(下記の例。) さもなくば一時ファイルがある状態の上に削除した状態のレイヤーがかぶさるだけなので、レイヤーのファイルサイズがでかくなる。

RUN apt-get update && apt-get install -y \
    ruby1.9.1 \
 && rm -rf /var/lib/apt/lists/*

あと、レイヤーもイメージ。名前が付いてるかどうかが違う、と言いきっちゃって良い?

Dockerそんなによくないよね

って話もいくつか共有しました。

話さなかったこと

初手の選択肢は少ない方が良い、という方基本針です。あと知らないものは知らないので。

コンテナ化技術

知らなくても使えるので第一歩で触れる必要なさそう。おれ自身詳しくないし。

docker vs docker-compose

composeの説明でちょっと触れたくらい。

compose以外のオーケストレーションツール

Kubernetes てのが熱いらしいぞ! でもおれ使ったことないぞ!

Docker Hub

イメージのダウンロードに絡めてちょっとだけ。

Moby

忘れてた。まあいいか。

パッケージのバージョン管理

イメージのバージョンを固定した方が良いぞという話はしたんだけど、パッケージ類のバージョンについては触れてなかったはず。

で、そのパッケージ類も固定化した方が環境が安定しそう。

Dockerfile で単純に apt-get とかすると「そのとき」のパッケージをダウンロードしてくるので、一年ぶりにビルドしたらツールのバージョンが変わってた……とかになっちゃうかもしれない。もしくは古すぎて消えてるとか。

そもそも Dockerfile を共有すること自体が既に悪手で、誰かがイメージまで用意してからそれを docker-compose.yml で指定する、の方が良いのではないでしょうか。

どうなんすか、先生。

イメージの配布

前項と絡めて話せるかなと思うけど、しなかった。Docker Hub以外の場所を使うやり方も知らないしなー。

docker-compose run xxx ç³»

「このコマンドを入力してください」という形でさんざん使ってはもらったんだけど、説明はあんまりしなかった。「もうbashでいいじゃん!」みたいになってもアレだなーと思って。

とはいえ、コマンド実行する必要がある場合はどうするのが良いのかなあ。ほら、初期設定は別にしてもRoRで rake db:migrate とかばんばんするでしょ。別途シェルスクリプト的なものを用意しておくの?

やってみた感想

いろいろたいへんだったけど、たのしかったです。