Docker Compose で WordPress
web+dbなど, 複数のコンテナやサービスで構成されるアプリを構築する際の手段の一つにDocker Composeがある.
構成パラメータをymlに書き出すので, ymlを読むと何をしているのかが何となくわかるのがいい感じ.
今回はお試しWordPress環境の構築を例に, Docker Composeを使ってみる.
(DockerHubに書いてあることをほぼそのままやる. )
https://hub.docker.com/_/wordpress
環境
- Docker host on Oracle VirtualBox VM (Ubuntu 18.04) on macOS Mojave
- Docker 18.09.0
$ docker -v Docker version 18.09.0, build 4d60db4
- docker-composeのインストール
Linux環境でDockerをインストールしていても, Docker Composeはインストールされない.
以下を参考にホストマシンにdocker-composeをインストールする.
docs.docker.com
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 617 0 617 0 0 864 0 --:--:-- --:--:-- --:--:-- 862 100 11.1M 100 11.1M 0 0 783k 0 0:00:14 0:00:14 --:--:-- 1098k $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version docker-compose version 1.23.1, build b02f1306 $
- Docker Composeをインストールしたら, 適当なディレクトリで以下のstack.ymlファイルを作成
version: '3.1' services: wordpress: image: wordpress restart: always ports: - 8080:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: exampleuser WORDPRESS_DB_PASSWORD: examplepass WORDPRESS_DB_NAME: exampledb db: image: mysql:5.7 restart: always environment: MYSQL_DATABASE: exampledb MYSQL_USER: exampleuser MYSQL_PASSWORD: examplepass MYSQL_RANDOM_ROOT_PASSWORD: '1'
最新のWordPressとMySQL 5.7のイメージを指定している.
WORDPRESS_DB_ で接続先のデータベースの情報を指定する.
- stack.ymlのディレクトリで以下のコマンドを実行
$ docker-compose -f stack.yml up (略)
-fオプションはupの前にしないとエラーが出るかも.
このコマンドにより, ymlで指定したイメージの取得, WordPressコンテナとMySQLコンテナの起動, db接続などが行われる.
dbの互換性などでうまく起動しない場合もあるので, その場合はdbのバージョンを変更して試してみる.
Docker内でのネットワークもデフォルト設定で作成してくれる.
作成されたネットワークの情報はdocker network inspectで確認できる
$ docker network ls NETWORK ID NAME DRIVER SCOPE df9f685f5ba9 bridge bridge local 6dc567989d6f host host local dd596238709d none null local 0e8b407e4748 wordpress_default bridge local $ docker network inspect wordpress_default [ { "Name": "wordpress_default", "Id": "0e8b407e474893dccf87901d5430d012e0d6e9900ea624cdb08a76bed14a2688", "Created": "2019-01-01T13:14:04.278596181+09:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.19.0.0/16", "Gateway": "172.19.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "9b60a44e3db6693a605a9a8328e4ec78bfff8031b4f85c22e95f1e825c12c10d": { "Name": "wordpress_wordpress_1_c757a4d508cd", "EndpointID": "a1c750990e9f00868321ea9ad38d007ede2924f10719ae0b93d4f19362cd14fe", "MacAddress": "02:42:ac:13:00:02", "IPv4Address": "172.19.0.2/16", "IPv6Address": "" }, "ea3572652f4ab07568d530e3cb11b816a5cae7144d232888e293bd0cca6fd932": { "Name": "wordpress_db_1_3c36a9263ab8", "EndpointID": "47154ceb96f3695878d364e4f2075e146f272919264855d7631b9854894c311d", "MacAddress": "02:42:ac:13:00:03", "IPv4Address": "172.19.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": { "com.docker.compose.network": "default", "com.docker.compose.project": "wordpress", "com.docker.compose.version": "1.23.1" } } ]
- こんな感じの仮想ネットワークが作成されている.
- 各コンテナのステータスやポートはdocker-compose psで確認できる.
$ docker-compose -f stack.yml ps Name Command State Ports -------------------------------------------------------------------------------------------------- wordpress_db_1_3c36a9263ab8 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp wordpress_wordpress_1_c757a4d508cd docker-entrypoint.sh apach ... Up 0.0.0.0:8080->80/tcp
- docker-composeがうまくいったら, ブラウザを開いてhttp://localhost:8080 にアクセスすると初期設定画面が開く
設定を順次行い, ブログ作成などをやってみる.
おわり.
- 終わったら, docker-composeで作成したコンポーネントをまとめて削除する.
$ docker-compose -f stack.yml down --rmi all
--rmiオプションでallを指定すると, docker-composeで作成したコンテナ・イメージ・ネットワークなどが一括削除される.
以上
Docker Tomcatにsample.warをデプロイする Dockerfile編
前回の記事ではTomcatコンテナに入ってサンプルアプリをデプロイしてみた.
koimedenshi.hatenablog.com
今回は同じことをDockerfileでやってみる.
環境
- Docker host on Oracle VirtualBox VM (Ubuntu 18.04) on macOS Mojave
- Docker 18.09.0
$ docker -v Docker version 18.09.0, build 4d60db4
前回同様サンプルアプリ(sample.war)をCATALINA_BASEにデプロイするが, コンテナに入り込むのではなく, アプリがデプロイされたイメージからコンテナを起動する.
まず以下の内容でDockerfileを作成する.
FROM tomcat:8.5.37 ENV CATALINA_HOME /usr/local/tomcat ENV PATH $CATALINA_HOME/bin:$PATH WORKDIR $CATALINA_HOME RUN set -ex; \ cd webapps && \ wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war
わりとシンプルだと思うが, ざっくり言うと「tomcat:8.5.37のイメージを用意して, CATALINA_HOME/webappsにsample.warをダウンロードしてね」という指示を書いている.
詳しいことはググってください(ひどい)
tomcat:8.5.37は現時点でのlatestを選択した.
このファイルを保存したディレクトリでdocker buildする.
$ docker build . -t sample:0.1 Sending build context to Docker daemon 2.048kB Step 1/5 : FROM tomcat:8.5.37 ---> ef802ca71927 Step 2/5 : ENV CATALINA_HOME /usr/local/tomcat ---> Running in 96bc5a455775 Removing intermediate container 96bc5a455775 ---> 21a687433aee Step 3/5 : ENV PATH $CATALINA_HOME/bin:$PATH ---> Running in 1d2b1a0510fa Removing intermediate container 1d2b1a0510fa ---> 09499132613c Step 4/5 : WORKDIR $CATALINA_HOME ---> Running in e187f9a604f5 Removing intermediate container e187f9a604f5 ---> 27b0a898e31c Step 5/5 : RUN set -ex; cd webapps && wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war ---> Running in 24ec52d55e3c + cd webapps + wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war (略) Successfully tagged sample:0.1 $
イメージ作成に成功したら, 作成したイメージを用いてコンテナを起動する.
$ docker container run --name sample-container -p 80:8080 sample:0.1 (略)
コンテナが起動したら, ブラウザからhttp://localhost/sampleにアクセスしてJSP Pageやservletが正常に開けることを確認.
おわり.
不要なコンテナやイメージは削除.
$ docker container stop sample-container sample-container $ docker container rm sample-container sample-container $ docker image rm sample:0.1 (略)
公式のDockerfileを引用したので, たぶん余計なコマンドが入っていてすみません.
warファイル取得方法はADDを使うとか, これ以外にもいろいろな方法があると思う.
Docker Tomcatにsample.warをデプロイする
これまでの記事で, DockerでApache Tomcatコンテナを構築する方法を2通りやってみた.
DockerでTomcatその1 - いろいろ書いていくつもり
DockerでTomcatその2 ( docker build ) - いろいろ書いていくつもり
といってもコンテナを起動しただけで味気ないので, 今回はサンプルアプリをデプロイしてみる.
環境
- Docker host on Oracle VirtualBox VM (Ubuntu 18.04) on macOS Mojave
- Docker 18.09.0
$ docker -v Docker version 18.09.0, build 4d60db4
アプリのデプロイ手順
Tomcat公式で公開されているサンプルアプリ(sample.war)を, TomcatコンテナのCATALINA_BASE/webappsに保存するだけ.
http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/
warファイルを保存すると, 自動的にアプリがデプロイされる.
CATALINA_BASEは環境によって異なるが, Docker公式イメージではCATALINA_BASE=/usr/local/tomcat/ となる(Docker Hubに書いてある).
https://hub.docker.com/_/tomcat/
warファイルの保存方法はいろいろ考えられるが, 今回はコンテナに入り込んで手動で行う.
ほかの方法は次以降の記事で書く, かも.
手順
1. tomcat container起動
以下のコマンドによりTomcatコンテナを起動.
$ docker container run --name tomcat-example -p 80:8080 tomcat:8.5.35 (略) XX-Dec-2018 XX:XX:XX.XXX INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1639 ms
イメージがローカルに保存されていない場合, イメージのダウンロードも同時に行われる.
2. コンテナ内でbashプロセスを起動し, ダウンロード
ターミナルをもうひとつ開いて, docker execコマンドでコンテナ内でbashを起動
$ docker exec -it tomcat-example /bin/bash root@d37eaefd6537:/usr/local/tomcat#
3. /usr/local/tomcat/webappsに移動し, warファイルをダウンロードする
root@d37eaefd6537:/usr/local/tomcat# cd webapps root@d37eaefd6537:/usr/local/tomcat/webapps# wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war Saving to: ‘sample.war’ sample.war 100%[===================>] 4.50K --.-KB/s in 0s 2018-12-XX (380 MB/s) - ‘sample.war’ saved [4606/4606]
4. ブラウザで動作確認
ブラウザでhttp://localhost/sampleにアクセス.
JSP pageやServletへのリンクをクリックして, 正常に動作することを確認.
5. おわり
不要なコンテナやイメージは削除.
$ docker container stop tomcat-example tomcat-example $ docker container rm tomcat-example tomcat-example $ docker image rm tomcat:8.5.35 Untagged: tomcat:8.5.35 (略)
DockerでTomcatその2 ( docker build )
前回の記事で,docker image pullで公式イメージを取ってくる手順を書いた
DockerでTomcatその1 - いろいろ書いていくつもり
今回はdocker buildを使ってみる.
公式のコードそのままではうまくいかないことがあったので,その辺りも書く.
環境
- Docker host on Oracle VirtualBox VM (Ubuntu 18.04) on macOS Mojave
コンテナで立てるアプリはApache Tomcat.
Apache Tomcat - Wikipedia
公式イメージの使用可能なバージョン等はDocker Hubで確認できる
https://hub.docker.com/_/tomcat/
今回は執筆時点におけるlatestバージョンである8.5.35を用いる.
手順
- Docker HubのDockerfileリンクを辿って,8.5.35のDockerfileをダウンロードする
https://hub.docker.com/_/tomcat/
↓
github.com
- ファイル名は"Dockerfile"のままにする.(変更してもよいが,その場合は後のbuildコマンドで-fオプションで指定する)
- Dockerfileのあるディレクトリでターミナルを開く
- ここでdocker buildすればイメージ完成..のはずなのだが,このままだとうまくいかなかった.
$ docker build -t tomcat:8.5.35 . (sniped) ...returned a non-zero code: 2
- -tオプションによりTAG名"tomcat:8.5.35"でイメージ作成しているが,リストにも中間生成物的なものしか見当たらない
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> b334452e1e39 About a minute ago 447MB openjdk 8-jre dd20fb277e3c 3 weeks ago 443MB
- 実行時のエラーを追ってみると,gpg鍵の検索に失敗した後終了しているっぽい
(sniped) + mktemp -d + export GNUPGHOME=/tmp/tmp.QmRGq0ytuG + gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys XXXXXXXX gpg: keybox '/tmp/tmp.QmRGq0ytuG/pubring.kbx' created gpg: keyserver receive failed: Cannot assign requested address (sniped)
最後のエラー文で検索すると,同じような現象が多数報告されている
Key server down for get.docker.com · Issue #13555 · moby/moby · GitHub
keyserverをpgp.mit.edu や keyserver.ubuntu.comにしてみろとのこと
- Dockerfileのkeyserverの値を上記のいずれかに変更して保存
gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
↓↓↓
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
- 再度buildする前に,中間生成物的なものを削除する(しなくてもよいが,あとでゴミが残るので・・・詳しくは後ほど)
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> b334452e1e39 36 minutes ago 447MB
- IMAGE ID指定で削除しようとすると,停止中のコンテナで使っていると怒られる
$ docker image rm b334452e1e39 Error response from daemon: conflict: unable to delete b334452e1e39 (must be forced) - image is being used by stopped container 2642a25811d8
- 中間生成物として作られた不要なコンテナなので,削除する
$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2642a25811d8 b334452e1e39 "/bin/sh -c 'set -eu…" 36 minutes ago Exited (2) 36 minutes ago objective_engelbart $ docker container rm 2642a25811d8 2642a25811d8 $ docker image rm b334452e1e39 Deleted: sha256:b334452 ... (sniped) $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE
- 綺麗にしたところで,もう一度buildコマンドを実行
$ docker build -t tomcat:8.5.35 . (sniped) Successfully built 5734bc644c71 Successfully tagged tomcat:8.5.35
- 成功すると指定したタグのイメージが一覧に追加される.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat 8.5.35 5734bc644c71 About a minute ago 475MB openjdk 8-jre dd20fb277e3c 4 weeks ago 443MB
- 同じエラーが出た場合は,他のkey serverを試してみるか,コメントアウトするしかない・・・
- 前回同様,追加されたイメージを用いてコンテナを起動する
$ docker container run -p 80:8080 --name my-tomcat-2 tomcat:8.5.35 (snip) XX-Dec-2018 XX:XX:XX.XXX INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2327 ms
- コンテナ一覧でも見えるはず
$ docker container ls
- 最後にブラウザでhttp://localhost/にアクセスし, Tomcat/8.3.35のトップページが表示されることを確認
http://localhost/examples/にあるJavaアプリも動くはず
- 終わり.
- コンテナとイメージを(目的は果たしたので)削除
# コンテナ停止 $ docker container stop my-tomcat-2 # コンテナ削除 $ docker container rm my-tomcat-2 $ docker container ls # イメージ削除 $ docker image rm tomcat:8.5.35 $ docker image ls
- 他の公式Dockerfileでも上記のkey serverをつかっているのが見受けられたので,同じような現象が起きるかも.
余談
- docker buildコマンドはDockerfileのRUNなどの処理を1行ずつ実行し,その度に中間イメージおよびコンテナを生成している
- そのため,上記手順の中で中間生成物を削除しないで継続すると,エラーで落ちたところから再開してくれるので少し速くなる.
- 楽でいいかなと思ったが,後でイメージを削除する際に中間生成物が残っており,ちょっと微妙だったので先に削除した.
DockerでTomcatその1
Docker imageを準備するにはいくつかの方法がある.
- docker image pull
- docker build
- docker import
などなど
今回はdocker image pullで公式イメージを落として,コンテナを起動するところまでをやってみる.
環境
- Host: macOS (Mojave)
- Guest: Ubuntu 18.04 (Oracle VirtualBox)
コンテナで立てるアプリはApache Tomcat.
Apache Tomcat - Wikipedia
公式イメージの使用可能なバージョン等はDocker Hubで確認できる
https://hub.docker.com/_/tomcat/
今回は執筆時点におけるlatestバージョンである8.5.35を用いる.
手順
- Docker Tomcat公式イメージをバージョン指定(8.5.35)で取得
$ docker image pull tomcat:8.5.35 8.5.35: Pulling from library/tomcat 54f7e8ac135a: Pull complete d6341e30912f: Pull complete (sniped) d1786b40ed4f: Pull complete Digest: sha256:d6f67aacce64010880a1e9ea6f0ace9fe9e20d39aae0489c8e88b4c14effe3a0 Status: Downloaded newer image for tomcat:8.5.35
- 成功するとイメージ一覧に追加される.
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE tomcat 8.5.35 48dd385504b1 5 days ago 475MB
- 追加されたイメージを用いてコンテナを起動する
$ docker container run -p 80:8080 --name my-tomcat-1 tomcat:8.5.35 (snip) XX-Dec-2018 15:00:37.407 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2327 ms
(なお,今回は先にイメージ取得を行なったが,docker container runすると足りないイメージも取得してくれるので,イメージ取得は省略できる.
いきなりdocker container run..をしても同じ結果となる.)
- 新たにターミナルを開いて以下のコマンドを実行し, コンテナが起動していることを確認
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 82b62a5f6b31 tomcat:8.5.35 "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:80->8080/tcp my-tomcat-1
- ブラウザでhttp://localhost/にアクセスし, Tomcat/8.3.35のトップページが表示されることを確認
- http://localhost/examples/にあるJavaアプリも動くはず
- コンテナとイメージを(目的は果たしたので)削除
# コンテナ停止 $ docker container stop my-tomcat-1 # コンテナ削除 $ docker container rm my-tomcat-1 $ docker container ls # イメージ削除 $ docker image rm tomcat:8.5.35 $ docker image ls
以上
Docker daemon attack surfaceを読んだ
Dockerの公式ドキュメントにセキュリティ関連のページがある.
docs.docker.com
Dockerの仕様と,それに起因するセキュリティ上の注意事項がまとめてある感じ.
今回はそのなかのひとつ"Docker daemon attack surface"を読んでわかったことをまとめてみる.
(これから勉強しようという人が書いているので,かなり初歩的だし,ミスリードがあるかもしれない.間違ってたらごめんなさい.)
ここに書いてあることが常に正しいかどうかはわからない.
設定や使用環境によっては気にしないでよいこともあるかもしれない.
それでも基本的な考え方として知っておくことは無駄ではなさそう.
ポイント
とにもかくにも,信頼されたユーザだけがDocker daemonを操作できるようにすること.
Docker daemonとはDockerの機能を実現するdaemonのことで,dockerコマンドの宛先といったところ.
操作コマンドの使用を制限するのは当たり前のことにも思えるが,なぜ大事なのか.
もう少し詳しく
Dockerコンテナはホストとディレクトリを制限なく共有する仕様となっている.
設定次第では,コンテナからホスト側のファイルシステムにアクセスすることも可能となりうる.
例えば外部から任意のコンテナを構築可能なサーバを立ててしまうと,悪意のあるユーザにコンテナの外のホストごとやられ放題となってしまう.
第三者によってC2サーバに使われてしまったり,ボットネットに組み込まれてしまうかもしれない.
そのようなリスクを踏まえ,Docker CLIのREST APIはバージョン0.5.2以降はUNIXソケットを使う仕様になっている.
Docker Engine release notes | Docker Documentation
0.5.2 (2013-08-08)
Builder: Forbid certain paths within docker build ADD
Runtime: Change network range to avoid conflict with EC2 DNS
API: Change daemon to listen on unix socket by default
それまでのTCPソケットによる待ち受けに比べ,従来のUNIX権限チェックを適用することでサーバを守れるため,リスクを減らせるという判断だ.
現在でも設定変更によってREST APIをHTTP経由で叩くことも可能だが,その場合はVPNを張ったり,HTTPSを使うなどでAPI向けの通信を保護したほうがよい.
これ以外にもDockerデーモンは,docker loadやdocker pullなどのイメージ読み込みに対しても脆弱である.
開発者が知らないうちに悪性なイメージを使っていて,それをリリースしてしまう,ということがあるかもしれない.
これに対してはまずバージョン1.3.2でサンドボックス上に展開するような仕様に変更され,さらに1.10.0(下記リンク)からはdocker imageをチェックサムで管理するようにすることで,正規のイメージを保護している.
blog.docker.com
使用しているイメージが意図したものであるかどうかは,IDを見ればよい.
最後に,Dockerを公開する場合は他のサービスと混在させないようにしつつ,必要なサービスはすべてコンテナでまかなうとよい.
(もちろんsshやログ保存系などの管理ツールは入れてもいい,と書いてある.)
Ubuntu18.04にDockerをインストールする
VirtualBox VMのUbuntu 18.04にDocker CEをインストールする.
参考にしたサイト
環境
- Host: macOS (Mojave)
- Guest: Ubuntu 18.04 (Oracle VirtualBox)
インストールするもの
- Docker CE stable (version 18.09.0)
手順
- 先にインストール済みのDockerをアンインストールしたい場合、以下コマンドを実行.(初めてインストールする場合は不要)
$ sudo apt-get remove docker docker-engine docker.io
- aptインストールの際にHTTPS通信するためのパッケージをインストール.
$ sudo apt-get update $ sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
- DockerのPGP鍵を追加し, apt-keyが "9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88" であることを確認.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88 (snip) Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
- Dockerのレポジトリを追加.
$ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
- Dockerをインストール.
$ sudo apt-get update $ sudo apt-get install docker-ce
- dockerコマンドでHello-Worldコンテナを実行し、成功メッセージが出ればインストール完了.
$ sudo docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. (snip)
dockerコマンド実行時のsudoを不要にする方法(任意)
Docker daemonはUnix socketにバインドされ, 通常rootでしかアクセスできない.
root以外のユーザでsudoせずにdockerコマンドを実行するためには, そのユーザをdockerグループに追加する手順が必要.
セキュリティ上の観点から, 信頼されたユーザのみを追加すること.
詳細はDocker security | Docker Documentationを参照のこと.
- dockerグループを作成
$ sudo groupadd docker
※インストール後に実施すると「既にある」と怒られるので、同時に作成されているかも
- dockerグループにユーザを追加
$ sudo usermod -aG docker <追加したいユーザ名>
$ docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. (snip)
うまくいかないときは, 公式ドキュメントの対応方法などを確認:
Post-installation steps for Linux | Docker Documentation
Dockerをシステム起動時に自動起動させない方法(任意)
ふつうにインストールすると, Dockerがシステム起動と同時に起動する設定となっている.
これをオフにするためには, 以下のコマンドを実行する.
$ sudo systemctl disable docker
以上.