- 投稿日:2019-01-26T20:00:32+09:00
Dockerのあれこれを断捨離する
はじめに
これも『Docker/Kubernetes 実践コンテナ開発入門』読書会で出てきたのですが、「溜まっていく不要なコンテナやイメージを全消しするコマンドってないのかな」という疑問。それに答えられるコマンドがあったのでそれに関してまとめてみます。
pruneコマンド
以下はPrune unused Docker objectsに書かれている内容ほぼそのままですが、多少例を交えて書いてみます。
様々なDockerオブジェクトをprune(枝刈り)するということですが、 そもそも日本人はpruneという言葉にあまり馴染みがない人が多いように思います。私もその一人ですが、唯一知っている例として、
$ find . -name .git -prune -o -printというようなのがあります。
find
コマンドでたまに使われる用法ですが、「その前の条件に当てはまるものは検索対象から除外」というオプションですね。上記の例だと「名前が.gitであるものは検索対象から外し、そうでなければ(-o
)プリントアウトする(やや脱線しましたが、Dockerではいくつかのオブジェクトに対してprune(枝刈り)する機能が提供されています。
イメージの断捨離
まずはイメージから。Dockerで以下のようにタグ付けしてビルドすることはよくあると思います。
$ docker build . -t myimage:latestただこれを繰り返すと前のビルドで作られたイメージが名無しで積まれていくことになります。docker-composeを使ってビルドした場合も、明示的にタグ付けしてなくてもイメージに自動でタグが付くので同様です。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE myimage latest 0663708e2fe9 8 seconds ago 101MB <none> <none> 0ef42d3b2d90 48 seconds ago 85.6MB <none> <none> 6de6344e5c7e About a minute ago 59.3MB <none> <none> f6852a322079 5 minutes ago 20.7MBそんな時に、
docker image prune
を叩いてみると、「danglingイメージを全部消しちゃうけど良い?」という確認がでて、それにy
と答えると、最新のビルドだけ残してキレイに消してくれる!$ docker image prune WARNING! This will remove all dangling images. Are you sure you want to continue? [y/N] y Deleted Images: deleted: sha256:6de6344e5c7e0174e61e60850fd2b8141d45c25130a1d4721277bf50d587665b deleted: sha256:2cd97da5bb5dffe5636663e29d8cc1a0ce466cffc0a7ccc711874e279b81a7b2 deleted: sha256:f6852a32207912f722f8f48f7a8f2e7ff19af7e0ec898b1568b4448eb88083b9 deleted: sha256:5fd80e022f1ae979431fc5ffc5c79fcd4ba17cf3599b438c9945e61aa3262f5f deleted: sha256:0ef42d3b2d90f849ea528387cc431e102b8f4a359da4d01e1bb2f4fe376e8226 deleted: sha256:fd285edd6b4ad162dce41bd15d0127c0cf52dada43af4631776b7e515cabde96 Total reclaimed space: 152.3MB $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE myimage latest 0663708e2fe9 41 minutes ago 101MB"dangling"というのは「ぶらぶらしている、宙ぶらりんな」という意味ですが、ここでは
- タグ付けされていない、かつ
- 現存しているコンテナから参照されていない(動いているか止まっているかは不問)
という条件を満たすもので、要するに消しちゃっても影響なさそうなイメージを自動的に消してくれるというスグレモノです。ちなみに、どのイメージが消されちゃうかを事前に知りたければ以下のコマンドで確認できます。
$ docker image ls --filter dangling=trueそして、
docker image prune
にはオプションがいくつかあります。
-a
-all
タグが付いていてもコンテナから使われていないイメージは全て消去します。なので、可動しているコンテナがない状態だと全てのイメージが消えちゃいます。
-f
--force
実行時に「消しちゃうけど大丈夫?」という確認をスキップするためのオプションです。
--filter
消去するイメージを選択する追加の条件を指定できます。
指定には2つあります。一つは
until
で、絶対時間で「この時刻よりも前のもの」あるいは相対時間で「何秒・何分・何時間前のもの」という指定ができます。例えば以下のような形になります。$ docker image prune --filter until=2019-01-25 # 2019年1月25日以前に作成されたイメージを消す $ docker image prune --filter until=10m # 10分以上前に作成されたイメージを消すもう一つはラベルを指定するやり方で、各々のイメージを作成時にDockerfileの中でLABELコマンドで付加したラベルを検索条件とします。例えば、
$ docker image prune --filter label=maintainer # "maintainer"ラベルが設定されているイメージを消去 $ docker image prune --filter label=maintainer=maint@example.com # "maintainer"ラベルがmaint@example.comに設定されているイメージを消去更に、ラベル指定の場合は
label
の後ろに!
をつけることにより、「条件に当てはまらないイメージを消去」という指定もできます。$ docker image prune --filter label!=maintainer # "maintainer"ラベルが設定されていないイメージを消去 $ docker image prune --filter label!=maintainer=maint@example.com # "maintainer"ラベルがmaint@example.comに設定されていないイメージを消去なおこのfilterオプションでは、どのファイルが消去の対象になるのかの事前確認ができず、ちょっと困っています。
label
はdocker image ls --filter
でチェックできるのですが、label!
だとかuntil
は確認する方法を見つけられていません。実際に消去の実行をしない--dry-run
みたいなオプションがあれば良いのになと思ったりします。コンテナの断捨離
次にコンテナの整理について。コンテナも気がつくと不要なものが溜まっていたりします。特に、
docker container ls
としての何も出てこないので安心していると、実行済みのコンテナがたんまり残っていたりします。確認するには-a
オプションを使います。$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5802c2477245 alpine "ls" 11 seconds ago Exited (0) 10 seconds ago awesome_hellman 247e211d6b59 alpine "ls" 45 seconds ago Exited (0) 44 seconds ago blissful_mclean daa39f115422 alpine "ls" 47 seconds ago Exited (0) 46 seconds ago cranky_lamport実行の終わったコンテナでも
docker restart
で再度起動できるためデフォルトでは自動で消えてくれないです。もし停止と同時にコンテナを消去したければ--rm
オプションを付けてdocker run
すれば良いですが、それでもビルドに失敗したときなどにコンテナが残るため自然と溜まっていってしまいます。そんな時に
docker container prune
を実行すると、imageの時と同様に本当に消すかどうかを聞かれ、y
と答えると綺麗サッパリ消してくれます。対象は「停止中」のコンテナ。$ docker container prune WARNING! This will remove all stopped containers. Are you sure you want to continue? [y/N] y Deleted Containers: be1381d7199a6dcf1083c4ef9792ae78e04044743a6c6e1ce3cd517dc22479ab b9733c0160d16858ba2ef5ee877a23c3249e5313787debdb2c51e5863fdb2d31 f71351f2a878ab343c594675bb4cdff9966220a6d69fbb4d65e22205246525f1 4938b15ff8da0909eef220ce5254647e829fb6257a8ea8cbc9cd8361125f419b 5802c2477245b4f40fa6321a8780fbaac2d194e732b0813f58e305a2a9b444d2 247e211d6b59ce9bc1dbbd0c132d5877e81340c1b9e65d2eff1cf768bd03ebe7 daa39f1154227503b8c0da00153113d25c6305975b8801fbfa5aa317059398e7 Total reclaimed space: 3.831MBそして、このコマンドにもオプションがいくつかあります。
-f
--force
これは
docker image prune
と同様で、実行時に「消しちゃうけど大丈夫?」という確認をスキップするためのオプションです。
--filter
消去するコンテナを選択する追加の条件を指定できます。指定方法もimageと同じで
until
とlabel
。ラベルは基本は元のイメージのものを引き継ぎますが、docker run
で実行する時に上書きもできるのでその点は要注意かもしれません。ボリュームの断捨離
ボリュームも気をつけていないと溜まっていってしまうものの一つです。
docker volume create
コマンドで明示的に作ったり、あるいはdocker run -v <desitination_path>
やDockerfile内のVOLUMEコマンドで無名のボリュームを作ったりしますが、それはコンテナを消去しても自動的には消えません (run --rm
を使った場合に一部例外あり)。
docker volume ls
をすると今現在システムで抱えているボリュームのリストが出てきます。$ docker volume ls DRIVER VOLUME NAME local 0f181d792f4313abb670110c0ee079910fa3ca776463b515093a4fea4219dcc9 local 1d383f8ab7ec848c9e8e7969969f88a92d46d20592e7f3aa6ddb590feab2fb55 local 2c3afd63e16ecbb33bc54e8e7545ee1be5d5568236203dd69c5eeb38e98f9c72 ...ここで
docker volume prune
をしてあげると、使われていない(現存するコンテナから参照されていない)ボリュームはサクッといなくなります。$ docker volume prune WARNING! This will remove all local volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: ... Total reclaimed space: 1.528GB私は1.5GBものスペースを無駄に保持していたようです (^^;
他のpruneコマンド同様に、
docker volume prune
も-f/--force
と--filter
オプションが使えます。使い方は一緒なので説明は割愛させていただきます。ネットワークの断捨離
上記のイメージ、コンテナ、ボリュームに比べると溜まりにくいしそもそもデータ量もそれほどないので使う機会は少ないかも知れませんが、
docker network create
で明示的に作成したものは自動では消えないのでルーティングテーブルをシンプルに保ちたい方は定期的にdocker network prune
をやると良いかも知れません。
docker-compose up
で複数コンテナを立ち上げたときには自動でデフォルトのbridgeネットワークが作られますが、docker-compose down
するとそのネットワークは自動削除されるのでホントに出番が少なさそう(一方、自動で作られたボリュームは残り続けます…)。基本は現存するコンテナから参照されていないネットワークが削除されますが、デフォルトで作成されている
bridge
、host
、none
は消えずに残るようです。まとめて断捨離
これまで、個別にpruneするコマンドを紹介してきましたが、実はまとめてキレイにしてくれるコマンドも存在します。それが、
docker system prune
。これをやると、
- 停止中のコンテナ
- どのコンテナからも使われていないネットワーク
- 宙ぶらりんな(タグがなくどのコンテナからも参照されていない)イメージ
- ビルドキャッシュ
を全て消してくれます。最後のはビルドの速度を早めるために持っている中間結果を破棄するもので、ビルド時に
--no-cache
をつけるとそれを破棄した状態からビルドをはじめてくれますが、当然ビルドが終わった後にはキャッシュが残るわけで、キャッシュだけを削除するというコマンドは今まで無かったように思います。さらに、
--volume
オプションをつけて起動すると
- どのコンテナからも使われていないボリューム
も合わせて消してくれます。また、これにも
-f/--force
オプションがあるので「実行するか一々確認しなくても良いよ」という男気のある方は是非ともご活用ください(笑)。なお、個別にpruneしていくのも良いのですが、コンテナ以外のイメージ、ボリューム、ネットワークはコンテナから参照されていることを消す条件にしているので、先に不要なコンテナが消えていないと消せません。そういった順序関係を気にしたくなかったら
docker system prune
で一気にやってしまうのも手かなと思います。ただし、必要なモノを消してしまう可能性もあるのであくまでも自己責任でお願いします。まとめ
pruneコマンドに関してまとめてみました。書き始めたときにはすごく短いエントリになるかと思っていたら意外と長くなりました(^^;
ただ、書きながらボリュームやネットワークに関して自分はあまりわかっていなかったと再認識し、そういう意味でも書いた意味があったかなと思います。
- 投稿日:2019-01-26T16:26:23+09:00
コンテナイメージの実体を見てみる
これは何?
コンテナイメージの実体を見てみる話です。
概念と使い方はわかるけど、「コンテナイメージっていったい何者なんだろう」と思っていたので中を見てみました。
認識違いがあったら教えて頂けると非常に嬉しいです。環境とか
- Docker version 18.09.1, build 4c52b90
題材として適当なコンテナイメージを用意する
$ docker pull node/8.15.0-alpine$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE node 8.15.0-alpine 5c0c5c94503f 4 weeks ago 66.3MBコンテナイメージをtarにする
$ docker save node:8.15.0-alpine > node.tar$ ls -ltr -rwxrwxrwx 1 xxx xxx 69734400 Jan 26 14:37 node.tartarを解凍してみる
$ tar -xvf node.tar 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/ 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/VERSION 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/json 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/layer.tar 5c0c5c94503f7310f50e73e8bcaa584eab5e5256ac34b9745589b64bb8fa09bb.json 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/ 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/VERSION 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/json 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/layer.tar eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/ eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/VERSION eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/json eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/layer.tar manifest.json repositoriesこれがコンテナイメージの実体のようです。
上でdocker images
した時に表示されたイメージIDと同じものがありますね。
種類を分けるとこんな感じでしょうか。
- buildされたコンテナイメージの情報
- 5c0c5c94503f7310f50e73e8bcaa584eab5e5256ac34b9745589b64bb8fa09bb.json
- レイヤーの情報
- 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc
- 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac
- eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f
- メタ情報
- manifest.json
- repositories
buildされたコンテナイメージの情報
めちゃくちゃ長いです。たくさん情報持ってるんですね。
レイヤー名とかも確認できますね。5c0c5c94503f7310f50e73e8bcaa584eab5e5256ac34b9745589b64bb8fa09bb.json{ "architecture":"amd64", "config":{ "Hostname":"", "Domainname":"", "User":"", "AttachStdin":false, "AttachStdout":false, "AttachStderr":false, "Tty":false, "OpenStdin":false, "StdinOnce":false, "Env":[ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NODE_VERSION=8.15.0", "YARN_VERSION=1.12.3" ], "Cmd":["node"], "ArgsEscaped":true, "Image":"sha256:e615719cc465120b3f6a8a76ad4a39464a3d65be67f99c0bd90b4a847a00d651", "Volumes":null, "WorkingDir":"", "Entrypoint":null, "OnBuild":null, "Labels":null }, "container":"d29ae8e85f8f1b00dbc79c2160e202969205c1429dcc31553b18585f27248ff7", "container_config":{ "Hostname":"d29ae8e85f8f", "Domainname":"", "User":"", "AttachStdin":false, "AttachStdout":false, "AttachStderr":false, "Tty":false, "OpenStdin":false, "StdinOnce":false, "Env":[ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NODE_VERSION=8.15.0", "YARN_VERSION=1.12.3" ], "Cmd":[ "/bin/sh", "-c", "#(nop) ", "CMD [\"node\"]" ], "ArgsEscaped":true, "Image":"sha256:e615719cc465120b3f6a8a76ad4a39464a3d65be67f99c0bd90b4a847a00d651", "Volumes":null, "WorkingDir":"", "Entrypoint":null, "OnBuild":null, "Labels":{} }, "created":"2018-12-27T01:40:51.334534029Z", "docker_version":"18.06.1-ce", "history":[ { "created":"2018-12-21T00:21:29.97055571Z", "created_by":"/bin/sh -c #(nop) ADD file:2ff00caea4e83dfade726ca47e3c795a1e9acb8ac24e392785c474ecf9a621f2 in / " }, { "created":"2018-12-21T00:21:30.122610396Z", "created_by":"/bin/sh -c #(nop) CMD [\"/bin/sh\"]", "empty_layer":true }, { "created":"2018-12-27T01:22:27.078806811Z", "created_by":"/bin/sh -c #(nop) ENV NODE_VERSION=8.15.0", "empty_layer":true }, { "created":"2018-12-27T01:40:46.64036283Z", "created_by":"/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps binutils-gold curl g++ gcc gnupg libgcc linux-headers make python \u0026\u0026 for key in 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 FD3A5288F042B6850C66B31F09FE44734EB7990E 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 DD8F2338BAE7501E3DD5AC78C273792F7D83545D C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 B9AE9905FFD7803F25714661B63B535A4C206CA9 77984A986EBC2AA786BC0F66B01FBB92821C587A 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 4ED778F539E3634C779C87C6D7062848A1AB005C A48C2BEE680E841632CD4E44F07496B3EB3C1762 B9E2F5981AA6E0CD28160D9FF13993A75599653C ; do gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys \"$key\" || gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys \"$key\" || gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) \u0026\u0026 make install \u0026\u0026 apk del .build-deps \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt" }, { "created":"2018-12-27T01:40:46.898832094Z", "created_by":"/bin/sh -c #(nop) ENV YARN_VERSION=1.12.3", "empty_layer":true }, { "created":"2018-12-27T01:40:51.183517333Z", "created_by":"/bin/sh -c apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \u0026\u0026 for key in 6A010C5166006599AA17F08146C2130DFD2497F5 ; do gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys \"$key\" || gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys \"$key\" || gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz\" \u0026\u0026 curl -fsSLO --compressed \"https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc\" \u0026\u0026 gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \u0026\u0026 mkdir -p /opt \u0026\u0026 tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \u0026\u0026 ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \u0026\u0026 ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \u0026\u0026 rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \u0026\u0026 apk del .build-deps-yarn" }, { "created":"2018-12-27T01:40:51.334534029Z", "created_by":"/bin/sh -c #(nop) CMD [\"node\"]", "empty_layer":true } ], "os":"linux", "rootfs":{ "type":"layers", "diff_ids":[ "sha256:7bff100f35cb359a368537bb07829b055fe8e0b1cb01085a3a628ae9c187c7b8", "sha256:734b6a5256135b58db8ecef74e164d2682722f2b208467bf484392ee87509645", "sha256:1f3213370fe13af42ae5e55610b7e64d7c995edf4f95ebdfa4671456812c38dd" ] } }レイヤーの情報
レイヤーと思われるtarの中身を見てみます。
- 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/layer.tar
- 84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/layer.tar
- eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/layer.tar
5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/layer.tar
$ tar -xvf 5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/layer.tar bin/ bin/arch bin/ash bin/base64 bin/bbconfig ~~~ etc/alpine-release etc/apk/ etc/apk/arch etc/apk/keys/ etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub ~~~ var/run var/spool/ var/spool/cron/ var/spool/cron/crontabs var/tmp/果てしないものが展開されましたので中略しています。
途中でalpine
という文言もチラホラ見えたので、これはOS?eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/layer.tar
$ tar -xvf eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/layer.tar etc/ etc/apk/ etc/apk/protected_paths.d/ etc/apk/world etc/group ~~~ usr/local/lib/node_modules/npm/node_modules/stringify-package/index.js usr/local/lib/node_modules/npm/node_modules/stringify-package/package.json usr/local/lib/node_modules/npm/node_modules/strip-ansi/ usr/local/lib/node_modules/npm/node_modules/strip-ansi/index.js usr/local/lib/node_modules/npm/node_modules/strip-ansi/license ~~~ usr/sbin/ usr/share/ var/ var/cache/ var/cache/misc/これも果てしないので中略。
ただ、思いっきりnode_modules
を展開していたのでわかりやすかったです。nodeのレイヤーですね。メタ情報
manifest.json
とrepositories
には、メタ情報が入ってるようです。manifest.json[ { "Config":"5c0c5c94503f7310f50e73e8bcaa584eab5e5256ac34b9745589b64bb8fa09bb.json", "RepoTags":["node:8.15.0-alpine"], "Layers":[ "5491dce778832e33c284cd8185100e76d6daa18f8cbc32458c706776894127fc/layer.tar", "eaabbaf2e7fe2603c758103f3f9397a82ea9c1f39e421735753afef370323a1f/layer.tar", "84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac/layer.tar" ] } ]repositories.{ "node":{ "8.15.0-alpine":"84f3cb797bec406c8818fd5b1deaad92efd6776bb451c974175373102cfe72ac" } }実際のDockerfileとの対応
開発者の皆様がDockerfileを上げてくれているので、
node:8.15.0-alpine
のDockerfileを見てみます。このDockerfileは以下の6つの命令から成ります。
- FROM
- ENV
- RUN
- ENV
- RUN
- CMD
Dockerfileをbuildする際にレイヤーを新たに作り出す命令というのは
RUN
、ADD
、COPY
の3つだけですから、tarを解凍して確認できた3つのレイヤーは
- FROM(alpineのベースイメージのレイヤー)
- RUN
- RUN
と対応していると思われます。(たぶん)
まとめ
- コンテナイメージをtarにすれば人間が中身を確認できる
- 内容は大きく3種類
- コンテナイメージ情報json
- 各レイヤーのリソースや設定情報もろもろ
- メタ情報json
- レイヤーの中には、当たり前だが各プロダクトを構成するファイルがちゃんと詰め込まれている
感想
知らなくてもコンテナ使う上では困らないと思いますが、なんだかよくわからないまま使うのはイヤなので見てみました。
レイヤー情報などわかりやすく格納されていて、かなり納得できました。
同時に、あらためてコンテナおよびDockerの便利さを再確認できました。
- 投稿日:2019-01-26T16:18:06+09:00
RSelenium のすヽめ
RSelenium でスクレイピングをしようとした時に日本語の記事がほとんどなく、TOEIC200点の英語力に頼るのがしんどかったので設定からデータ取得の流れを置いときます。
以下のページをスクレイピングしてみます。
https://jglobal.jst.go.jp/search/anythings#%7B%22category%22%3A%220%22%2C%22keyword%22%3A%22%E3%82%AB%E3%83%96%E3%83%88%E3%83%A0%E3%82%B7%22%7DDockerの準備
docker のインストールは省略
docker Selenium のイメージを取得します。
docker pull selenium/standalone-chromeSelenium コンテナを立てます。
docker run -d -p 4444:4444 selenium/standalone-chrome以上でdocker の設定は終了です。
Rの準備
RSelenium
を準備します。install.packages("RSelenium") library(RSelenium) remDr = remoteDriver(remoteServerAddr = "localhost", port = 4444, browserName = "chrome") remDr$open()上記により、seleniumコンテナとRの接続が完了しました。
スクレイピングしてみよう
url <- 'https://jglobal.jst.go.jp/search/anythings#%7B%22category%22%3A%220%22%2C%22keyword%22%3A%22%E3%82%AB%E3%83%96%E3%83%88%E3%83%A0%E3%82%B7%22%7D' remDr$navigate(url) Sys.sleep(5) planeHtmlList <- remDr$getPageSource() write(unlist(planeHtmlList), "getPage.html")この時、「ページの読み込み」と「ページの取得」の間隔が狭いとページをうまく取得できないので注意してください。
また、この時、ページの型はlist
であるので注意してください。では、ここからタイトルをスクレイプしてみましょう。
#install.packages("rvest") #install.packages("XML") library(rvest) library(XML) html <- read_html("getPage.html") parsed_doc <- htmlParse(html) title <- xpathSApply(doc = parsed_doc , path = "//a[@href]", xmlValue)できた。
- 投稿日:2019-01-26T15:29:22+09:00
MySQLの文字コードを変更する方法
ProgateでRuby on Railsレッスンで、tweetappというものを作成したので、そのコピーをDockerとGithubを使いながら、開発をしています。
ちなみにRails環境は以下のページを参考に構築しました。
https://qiita.com/reflet/items/f73cac406760ee4ecc13
感謝です(^^)しかし、新規投稿機能のところで、日本語の文字列をDBに保存できない問題に直面。
エラー文は全文は控えてなかったのですが以下のような感じで、文字コードが原因っぽい。
Mysql2::Error: Incorrect string value ,,,,,,いろいろネットで調べて以下の方法で解決したので、メモです。
MySQLのクライアントサーバーとMySQLサーバーの文字コードの確認・変更
#確認したいテーブルを選択 mysql> use DB名 #文字コードを確認 mysql> show variables like 'character%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | latin1 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ #以下のコマンドでUTF-8に変更 mysql> set character_set_client = utf8 mysql> set character_set_connection = utf8 mysql> set character_set_database = utf8 mysql> set character_set_results = utf8「character_set_server」「character_set_system」は「docker-compose.yml」のMySQLにcommandを以下のように追加したらUTF-8に変更できました。
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci既に作成したDBの文字コードの確認・変更
#確認 mysql> show create database DB名; +----------+--------------------------------------------------------------------+ | Database | Create Database | +----------+--------------------------------------------------------------------+ | example | CREATE DATABASE `example` /*!40100 DEFAULT CHARACTER SET latin1 */ | +----------+--------------------------------------------------------------------+ #変更 mysql> alter database DB名 character set utf8;既に作成したMySQLのテーブルカラムの確認・変更
#確認 mysql> show create table テーブル名 \G; *************************** 1. row *************************** Table: posts Create Table: CREATE TABLE `posts` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `content` text CHARACTER SET latin1, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) #変更 mysql> alter table テーブル名 modify カラム名 varchar(255) character set utf8;この時点で日本語に保存できました。
いやーハマっちゃいましたw
これから、カラムを追加したり、新しいテーブルを作成するので、どうなるのでしょうか。とりあえず進めていきます。
- 投稿日:2019-01-26T13:49:49+09:00
PodmanのセキュリティはDockerよりも何が優れているのか?
はじめに
先日、オープンソースのコンテナエンジンPodmanのバージョン1.0.0が公開されました。
Podman | podman.ioPodmanはKubernetesのPodをよりシンプルに柔軟に利用できるように開発されたDocker互換のコンテナエンジンで、Docker Swarm関連を除いたほとんどのDockerコマンドを備えています。
Dockerと比べてアーキテクチャの違いがいくつかありますが、Podmanは特徴の一つとしてセキュリティの強さを謳っています。
この記事ではセキュリティの観点からPodmanの機能に関する調査結果をまとめていきます。目次
rootlessコンテナ
rootless
とは非root権限で制御できることです。
非root権限で動かせるコンテナのため、問題が起きた際の影響範囲を限定することができます。2019年1月現在のDocker 18.09では
rootless
に対応していませんが、rootless
モードの開発が進められています。
Allow running dockerd as a non-root user (Rootless mode) #38050Docker 19.xxで当該機能が追加される......との噂です。
Linux Auditにおける脆弱性の回避
Linuxにはセキュリティイベントを監視する機能として、
Linux Audit
システムが搭載されています。
Red Hat Enterprise Linux 7 第5章 システム監査 - Red Hat Customer Portalその中で利用される一部のフィールド値の扱いが、PodmanとDockerでは異なっており、例えば、Podmanでは
ホスト側から見たloginuid
とコンテナ側から見たloginuid
は同一ですが、Dockerではホスト側から見たloginuid
とコンテナ側から見たloginuid
は異なります。これはDockerコンテナからのログインユーザーを
Linux Audit
が識別できない可能性を表しています。edit_file_and_audit_log$ sudo docker run --privileged -v /:/host fedora touch /host/etc/shadow $ sudo ausearch -f /etc/shadow -i type=PROCTITLE msg=audit(10/10/2018 10:27:20.055:4569) : proctitle=/usr/bin/coreutils --coreutils-prog-shebang=touch /usr/bin/touch /host/etc/shadow type=SYSCALL msg=audit(10/10/2018 10:27:20.055:4569) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x7ffdb6973f50 a2=O_WRONLY|O_CREAT|O_NOCTTY| O_NONBLOCK a3=0x1b6 items=2 ppid=11863 pid=11882 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=touch exe=/usr/bin/coreutils subj=system_u:system_r:spc_t:s0 key=(null) 引用: Podman: A more secure way to run containers | Opensource.com上記コマンドでは、Dockerコンテナを起動してファイル編集を行ない、
Linux Audit
のログを出力していますが、auid=unset
となっており、ユーザーの特定が不可能であることが分かります。この原因はDockerがクライアント・サーバ型のアーキテクチャであることに依るものですが、下記ページが非常に分かりやすかったので詳しく知りたい方はご一読ください。
Intro to Podman (Red Hat Enterprise Linux 7.6 Beta) - RHD Blog参考記事まとめ
Podman | podman.io
Podman: A more secure way to run containers | Opensource.com
Allow running dockerd as a non-root user (Rootless mode) #38050
Red Hat Enterprise Linux 7 第5章 システム監査 - Red Hat Customer Portal
Intro to Podman (Red Hat Enterprise Linux 7.6 Beta) - RHD Blog
Dockerセキュリティ: 今すぐ役に立つテクニックから,次世代技術まで
- 投稿日:2019-01-26T12:46:20+09:00
知識0から始めるRails on Docker
はじめに
Railsの勉強を始めようと思ったが、どうせならDockerを使って仮想環境で開発したい。
しかしどちらも実務で使ったことがないためよくわからない(というかRubyすら触ったことがない)。ということで、一から調べてみた。RailsとDockerの欲張りセット。
筆者はMacBookProを使っているため、MacOS向けの記事となります。tl;td
- Rubyにまつわる各用語の確認、ローカル環境でRailsの導入・起動方法の確認
- 手動でDocker上でのRailsの導入・起動方法の確認
dockerfile
にRailsの導入・起動情報を文書化して格納し、docker-compose
から呼び出して起動対象読者
- わたし
- これからRailsを勉強しようという方
- これからDockerを勉強しようという方
ロードマップ(超簡易版)
最終目標:Dockerによる仮想環境上でRails serverを起動し、開発できるようにする
※RailsのデフォルトサーバーはPumaです。この記事ではデフォルトのままなのでPumaを使いますが、便宜上「Rails server」と呼称します。
- Railsをローカル環境で起動する
- ローカル環境にRubyを導入する
- ローカル環境にRailsを導入する
- Railsプロジェクトを作成し、Rails serverを起動
- Docker環境を構築して仮想環境でRails serverを起動する
- ローカル環境にDockerを導入する
- DockerでRubyを使える仮想環境を構築する
- 仮想環境でRails serverを起動する
dockerfile
とdocker-compose
を使ってコマンド一つでRails serverを起動する
dockerfile
を作成するdocker-compose.yml
を作成し、起動するRailsをローカル環境で起動する
これについては各所でがっつり解説されているので、ここでは流れ・用語の説明と参考資料の紹介にとどめます。
なお、この章の目的はRubyにまつわる各用語とRails serverの起動までの流れについて確認することが目的なので、既にバッチリの方は飛ばしてください。
参考資料:Ruby初学者のRuby On Rails 環境構築【Mac】ローカル環境にRubyを導入する
流れ
Homebrewの導入(更新)-> rbenvの導入 -> Rubyの導入ざっくりHomebrew解説
- MacOSにおけるパッケージ管理ツール
- Rubyのためだけのものではない
- 参考資料:homebrewとは何者か。仕組みについて調べてみた
ざっくりrbenv解説
- Rubyのバージョンを管理するためのツール
- Rubyのバージョン管理をrbenvで、rbenvのバージョン管理をHomebrewで行う(Homebrewは自分でやる)
- 参考資料:rbenvとは?(rbenvを利用したRubyのインストール)
ローカル環境にRailsを導入する
流れ
Bundlerの導入 -> BundlerでGemfileの作成 -> Gemfileの編集 -> Gemの取得(Railsの導入)ざっくりGem解説
- RubyGemsが公開しているライブラリ
- 要はRubyの開発で使える便利なツール群のこと
- RailsもGemの一つ
- 参考資料:Ruby on Rails 初心者必見!パッケージ管理ツール『gem』を徹底解説
ざっくりBundler解説
- Gemの管理ツール
Gemfile
から利用するGemの情報を読み取り、ライブラリを自動で構築してくれるすごいヤツ- この記事では
$ bundle init
と$ bundle install
さえ覚えておけばOK- 参考資料:Bundlerの使い方
- 参考資料:bundle install と bundle updateの違いについて
Railsプロジェクトを作成し、Rails serverを起動
流れ
Railsからプロジェクトを作成 -> Rails serverの起動 -> 接続確認Docker環境を構築して仮想環境でRails serverを起動する
ローカル環境にDockerを導入する
Docker公式から最新版を取得しましょう。
アカウントの登録が必要です。なお、Dockerの基礎的な仕組みやコマンドなどについては、以下の参考資料がおすすめです。
参考資料:Dockerでプログラマが最低限知るべきことが、最速でわかるチュートリアル
docker
参考資料:【図解】Dockerの全体像を理解する -前編-ざっくりDocker解説
- 仮想環境の構築・管理を行うツール
- 擬似的に様々な環境を構築することができ、ローカル環境と本番環境との差異を減らすことができる
- 「本番環境で急に動かなくなった問題」や「環境構築面倒すぎる問題」の救世主……らしい
DockerでRubyを使える仮想環境を構築する
参考資料:RailsアプリをDockerで開発するための手順
ここからが本題です。
まずは利用するイメージを決めます。Docker Hubにruby
という便利なイメージが用意されているので、ありがたく使わせていただきましょう。rubyイメージの取得$ docker pull ruby
イメージが取得できたら早速run……する前に、このイメージについて調べましょう。
イメージの情報を出力$ docker inspect ruby
コマンドを実行すると大量の文字が吐き出されます。
目眩がするかもしれませんが、頑張って大事な記述を確認しましょう。注目するのは以下の場所です。"ContainerConfig": { …… "Env": [ "PATH=/usr/local/bundle/bin:/usr/local/bundle/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "RUBY_MAJOR=2.6", "RUBY_VERSION=2.6.0", "RUBY_DOWNLOAD_SHA256=acb00f04374899ba8ee74bbbcb9b35c5c6b1fd229f1876554ee76f0f1710ff5f", "GEM_HOME=/usr/local/bundle", "BUNDLE_PATH=/usr/local/bundle", "BUNDLE_SILENCE_ROOT_WARNING=1", "BUNDLE_APP_CONFIG=/usr/local/bundle" ], ……
RUBY_VERSION=2.6.0Rubyのバージョンを示しています。Docker Hubでも確認できますが、イメージ本体にも情報がしっかり記されていますね。
このバージョンは重要なので覚えておきましょう。あるいはイメージをpull
する段階で指定してあげてもいいでしょう。BUNDLE_PATH=/usr/local/bundleBundlerのパスが指定されています。Bundlerによる
Gemfile
を使ったGem管理を行えることがわかりますね。ではこのイメージからコンテナを起動しましょう。
適当な名前のディレクトリを作成し、ターミナルの作業フォルダとします。
以降はプロジェクト名をproject_name
とします。
※project_name
以外の名前でも構いません。本記事ではこの名前で統一するということです。rubyイメージからコンテナを起動$ docker run -i -t --name TEST -p 3000:3000 -v "$PWD":/usr/src/project_name ruby /bin/bashまずは各オプションについて。
-i :コンテナのSTDIN(標準入力)にアタッチ。標準入力に入力できる状態にするということ。 -t :疑似ターミナル (pseudo-TTY) を割り当て。ターミナル画面で操作できるようにするということ。 --name :コンテナの名前。今回は'TEST'を指定。 -p :ポートの指定。今回は3000ポートを解放しています。 -v :ボリュームの指定。[ホストPCのディレクトリ指定]:[コンテナ内のディレクトリ指定]。 /bin/bash:コンテナ起動後に実行するコマンド。今回はシェルを指定。上記の説明は簡略したもので語弊を含むので、気になった項目は別途調べることをお勧めします。
-i
と-t
の二つはセットで使う(-it
)ことが多いので是非覚えておきましょう。
ボリュームについては概念が難しいですが、とりあえず[ホストPCで指定したディレクトリ]を[コンテナ内で指定したディレクトリ]として扱えるようにする、程度の理解でいいと思います。参考資料:Dockerリファレンス
うまく起動できたら下のような状態になるはずです。
root@03eb04059b1f:/#
コンテナの中のターミナルを操作しているようなイメージですね。
コンテナの中から一旦抜ける時はcontrol + pq
、再接続するときは$ docker attach [コンテナの指定]
です。
※exit
でも抜けられますが、コンテナが停止してしまうため注意。停止した場合、ポートを閉じてしまうようです。
※$ docker exec
でもコンテナに接続できます。ただし、プロセス接続するごとにプロセスが増えます。仮想環境でRails serverを起動する
それでは今起動したコンテナでRails serverの準備をしましょう。
先ほどコンテナを起動した際に、コンテナ内のproject_name
ディレクトリをボリュームとして指定しました。
指定したディレクトリが作成されているはずなので、そこまで移動しましょう。Railsプロジェクトの確認$ cd /usr/src/project_nameこのディレクトリにRailsプロジェクトを作成していきます。
まずは何をするにもGemfile
が必要なので、Bundlerを使って作成しましょう。Gemfileの作成$ bundle init
次にRailsを導入していきます。
Gemfile
を編集する必要がありますが、これはコンテナ内で行う必要はありません。Gemifile
を作成したディレクトリはコンテナ起動時にホストPC側のディレクトリとセットでボリューム指定したため、ホストPC側の指定したディレクトリにもGemfile
が作成されています。このGemfile
を編集するだけでOKです。Gemfile# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - # gem "rails" + gem "rails"コンテナ内のGemfile確認に反映されているか確認$ cat Gemfileこれで
Gemfile
の準備ができたので、GemのインストールとRailsプロジェクトの作成を行いましょう。Gemのインストール$ bundle install $ bundle exec rails new .
rails exec .
は作業ディレクトリに対してRailsプロジェクトを作成します。
実行するとGemfile
の上書き確認をされるので許可しましょう。ローカル環境ではこの時点でRails serverを起動できましたが、
ruby
イメージから作成したコンテナではまだRails serverは起動できません。
ですが、なぜ起動できないか確認するためにも一度試してみましょう。起動確認(失敗する).$ bundle exec rails serverエラーメッセージ(最後のみ抜粋)/usr/src/project_name/vendor/bundle/ruby/2.6.0/gems/execjs-2.7.0/lib/execjs/runtimes.rb:58:in `autodetect': Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
ExecJS::RuntimeUnavailable
というエラーについて調べてみると、どうやらJavaScriptランタイムというものが必要のようです。
今回はnode.js
を導入することにしましょう。
参考資料:rails sコマンド実行時に「Could not find a JavaScript runtime.」とエラーが出る場合の対処法
ruby
イメージではyum
コマンドは対応していないようなので、apt-get
を使ってインストールしましょう。
参考資料:apt-get - パッケージの操作・管理 - Linuxコマンドnode.jsのインストール$ apt-get update $ apt-get install nodejs完了したら今度こそRails serverが起動できるはずです。
Rails_server起動$ bundle exec rails serverhttp://localhost:3000/に接続して起動できているか確認しましょう。
dockerfile と docker-compose を使ってコマンド一つでRails serverを起動する
ここからは今まで行ってきたことを設定として文書化していきます。
先ほどまで使用していたコンテナはもう使わないので、$ exit
で停止しておきましょう。
ただし、作成したRailsプロジェクトはそのままにしておいてください。参考資料:Dockerfile リファレンス
参考資料:Compose ファイル・リファレンス
参考資料:RailsアプリをDockerで開発するための手順dockerfile を作成する
まず、前の章で行ったことを整理しておきましょう。
ruby
イメージからコンテナを作成(本記事ではバージョン2.6.0)- ポート3000:3000を開放し、ボリュームを指定してコンテナを起動
- コンテナ内でRailsプロジェクトを作成
- コンテナに
node.js
をインストール- Rails serverを実行
dockerfile
を書くということは、これらの作業を文書化していくということです。それでは
dockerfile
を書いていきます。Railsプロジェクトを作成したディレクトリにdockerfile
という名前でファイルを作成し、編集していきます。
まずは使用したイメージの情報です。dockerfileFROM ruby:2.6.0
:2.6.0
はバージョン情報です。指定しなければ最新版が自動で選択されますが、固定させた方がいいでしょう。
これはRubyのバージョンと同じなので、もし違うバージョンからRailsプロジェクトを作成したならそのバージョンに合わせてください。次にポートの開放とボリューム指定ですが、
dockerfile
ではホストPCのディレクトリを指定することはできません(後でdocker-compose.yml
で指定します)。よって、ここではポートの開放だけを行います。dockerfileFROM ruby:2.6.0 EXPOSE 3000ここでポートの開放を行なっても、
run
コマンドやdocker-compose.yml
で指定しなければ直接接続できないので注意してください。次はコンテナ内でRailsプロジェクト作成ですが、これは後でボリューム指定により共有する予定なので必要ありません。
ですが、Gemfile
が無くてはGemのインストールができず、rails
コマンドが実行できません。
そこで、Gemfile
だけをコンテナ内にコピーしてインストールすることにします。dockerfileFROM ruby:2.6.0 ENV APP_ROOT /usr/src/project_name WORKDIR ${APP_ROOT} COPY Gemfile ${APP_ROOT} COPY Gemfile.lock ${APP_ROOT} RUN bundle install EXPOSE 3000各コマンドは以下の通りです。
ENV [key] [value] …… 環境変数の定義。 WORKDIR [ディレクトリ指定] …… 作業ディレクトリの指定 COPY [ソース指定] [保存先指定] …… ファイルのコピー。 RUN [コマンド] …… コマンドの実行。これでコンテナ内でも
rails
コマンドが利用できるようになります。最後に
node.js
のインストールとRails serverの起動です。dockerfileFROM ruby:2.6.0 ENV APP_ROOT /usr/src/project_name WORKDIR ${APP_ROOT} RUN apt-get update && \ apt-get install -y nodejs COPY Gemfile ${APP_ROOT} COPY Gemfile.lock ${APP_ROOT} RUN bundle install EXPOSE 3000 CMD bundle exec rails serverRailse sever の起動が
RUN
ではなくCMD
なのは、コンテナの立ち上げが完了してから実行してほしいからです。
もしRUN
で書いてしまうとそこで動作が止まってしまい、いつまでもコンテナが立ち上がらないということになってしまいます。では、これでうまく動作するかどうか確認してみましょう。
dockerfileからイメージの作成と起動$ docker build .エラーが出ずにRails serverの起動までできればOKです。
docker-compose.yml を作成し、起動する
では、先ほど作成した
dockerfile
を使ってdocker-compose.yml
を作っていきましょう。
先ほどと同じく、Railsプロジェクトのディレクトリに作成し、以下の通りに編集してください。docker-compose.ymlapp: build: . ports: - '3000:3000' volumes: - .:/usr/src/project_nameapp: …… アプリケーションの名前。今回はappとした。 build: …… docker-composeのパス指定。今回は同一ディレクトリにある。 ports: …… 開放するポートの指定。 volumes: …… ボリュームの指定。これで完了です。では起動してみましょう。
docker-composeからの起動$ docker-compose up -dhttp://localhost:3000/に接続して、いつものアレが表示されたらOKです!
ちなみに、ホストPCのディレクトリを参照しているため、ファイルを編集すると即座に反映されます。Gemfile
と同じですね。おわりに
というわけで、起動できました。とりあえず動いたので満足。
- 投稿日:2019-01-26T09:57:54+09:00
Prometheus on Dockerでデータを永続化する方法
背景
PrometheusをDockerで利用しようとしていた
作り直すたびに監視データも初期化されるため、データ永続化をしたい対象環境
> docker-compose version docker-compose version 1.23.2, build 1110ad01 docker-py version: 3.6.0 CPython version: 3.6.6 OpenSSL version: OpenSSL 1.1.0h 27 Mar 2018 > docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE prom/prometheus v2.6.1 5517f7057e72 9 days ago 97.8MBちなみに、本記事で利用するコードはこちらにあります
方法
/etc/prometheus/data
がローカルストレージになっている> docker-compose exec prometheus ls -la /etc/prometheus total 12 drwxr-xr-x 1 nobody nogroup 4096 Jan 25 03:00 . drwxr-xr-x 1 root root 4096 Jan 25 06:04 .. lrwxrwxrwx 1 nobody nogroup 39 Jan 15 20:13 console_libraries -> /usr/share/prometheus/console_libraries lrwxrwxrwx 1 nobody nogroup 31 Jan 15 20:13 consoles -> /usr/share/prometheus/consoles/ lrwxrwxrwx 1 root root 11 Jan 15 20:13 data -> /prometheus -rw-r--r-- 1 root root 682 Jan 24 06:48 prometheus.yml > docker-compose exec prometheus ls -la /etc/prometheus/data/ total 4 drwxr-xr-x 5 nobody nogroup 170 Jan 25 06:01 . drwxr-xr-x 1 root root 4096 Jan 25 06:04 .. drwxr-xr-x 4 nobody nogroup 136 Jan 25 03:19 data -rw-r--r-- 1 nobody nogroup 0 Jan 25 06:01 lock drwxr-xr-x 3 nobody nogroup 102 Jan 25 06:01 walなので、こいつをローカルの適当なdataディレクトリとマウントしてあげれば、良い
そのときのdocker-compose.ymlとDockerfileとprometheus.ymlは下記となる
docker-compose.ymlversion: '2' services: prometheus: build: . ports: - "9090:9090" volumes: - $PWD/prometheus-data:/etc/prometheus/dataFROM prom/prometheus ADD prometheus.yml /etc/prometheus/prometheus.ymlglobal: scrape_interval: 15s external_labels: monitor: 'codelab-monitor' scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090']これで下記のコマンドで起動します
> docker-compose up -d Creating network "prometheus-test_default" with the default driver Creating prometheus-test_prometheus_1 ... doneグラフ(httpリクエスト合計)を見ると、正しく起動でき、グラフが上昇しているのがわかります
ここから、コンテナを落として、再度起動してみます
> docker-compose down Stopping prometheus-test_prometheus_1 ... done Removing prometheus-test_prometheus_1 ... done Removing network prometheus-test_default > docker-compose up -d Creating network "prometheus-test_default" with the default driver Creating prometheus-test_prometheus_1 ... doneすると、下記のように一度コンテナを落とした時のグラフも見えるようになります
失敗談
下記2点をダブルで行っていて、
- prometheus.ymlをDockerfileでADDしたものをbuild
/etc/prometheus/
をカレントディレクトリとマウントビルドで追加したymlがマウントしたせいで削除されてしまい、起動時にprometheus.ymlが見当たらずにエラーが出ちゃって小一時間悩んでた
> docker-compose up Creating network "prometheus-test_default" with the default driver Creating prometheus-test_prometheus_1 ... done Attaching to prometheus-test_prometheus_1 prometheus_1 | level=info ts=2019-01-25T03:19:16.5079408Z caller=main.go:243 msg="Starting Prometheus" version="(version=2.6.1, branch=HEAD, revision=b639fe140c1f71b2cbad3fc322b17efe60839e7e)" prometheus_1 | level=info ts=2019-01-25T03:19:16.5080482Z caller=main.go:244 build_context="(go=go1.11.4, user=root@4c0e286fe2b3, date=20190115-19:12:04)" prometheus_1 | level=info ts=2019-01-25T03:19:16.5080827Z caller=main.go:245 host_details="(Linux 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 433cf28249ba (none))" prometheus_1 | level=info ts=2019-01-25T03:19:16.5082197Z caller=main.go:246 fd_limits="(soft=1048576, hard=1048576)" prometheus_1 | level=info ts=2019-01-25T03:19:16.5088957Z caller=main.go:247 vm_limits="(soft=unlimited, hard=unlimited)" prometheus_1 | level=info ts=2019-01-25T03:19:16.5120108Z caller=main.go:561 msg="Starting TSDB ..." prometheus_1 | level=info ts=2019-01-25T03:19:16.5125678Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090 prometheus_1 | level=info ts=2019-01-25T03:19:16.5382688Z caller=main.go:571 msg="TSDB started" prometheus_1 | level=info ts=2019-01-25T03:19:16.5388817Z caller=main.go:631 msg="Loading configuration file" filename=prometheus.yml prometheus_1 | level=info ts=2019-01-25T03:19:16.539723Z caller=main.go:430 msg="Stopping scrape discovery manager..." prometheus_1 | level=info ts=2019-01-25T03:19:16.5398383Z caller=main.go:444 msg="Stopping notify discovery manager..." prometheus_1 | level=info ts=2019-01-25T03:19:16.540191Z caller=main.go:466 msg="Stopping scrape manager..." prometheus_1 | level=info ts=2019-01-25T03:19:16.5409244Z caller=main.go:440 msg="Notify discovery manager stopped" prometheus_1 | level=info ts=2019-01-25T03:19:16.5410353Z caller=main.go:426 msg="Scrape discovery manager stopped" prometheus_1 | level=info ts=2019-01-25T03:19:16.5411454Z caller=main.go:460 msg="Scrape manager stopped" prometheus_1 | level=info ts=2019-01-25T03:19:16.5413125Z caller=manager.go:664 component="rule manager" msg="Stopping rule manager..." prometheus_1 | level=info ts=2019-01-25T03:19:16.5416848Z caller=manager.go:670 component="rule manager" msg="Rule manager stopped" prometheus_1 | level=info ts=2019-01-25T03:19:16.5489596Z caller=notifier.go:521 component=notifier msg="Stopping notification manager..." prometheus_1 | level=info ts=2019-01-25T03:19:16.5493186Z caller=main.go:615 msg="Notifier manager stopped" prometheus_1 | level=error ts=2019-01-25T03:19:16.5501995Z caller=main.go:624 err="error loading config from \"prometheus.yml\": couldn't load configuration (--config.file=\"prometheus.yml\"): open prometheus.yml: no such file or directory" prometheus-test_prometheus_1 exited with code 1参考
- 投稿日:2019-01-26T07:43:12+09:00
docker error記録
macOS10.13.6
Safari 12.0.2(13606.3.4.1.4)
Docker Desktop Community 2.0.0.2(30215)
で、アプリでloginした状態で、runしようとした。$ docker run -it kaizenjapan/100pon /bin/bash docker: Error response from daemon: Bad response from Docker engine. See 'docker run --help'.なぜかエラーになった。コマンドラインでloginしてみた。
$ docker login Authenticating with existing credentials... Login Succeeded KM-S10:~ administrator$ docker run -it kaizenjapan/100pon /bin/bash Unable to find image 'kaizenjapan/100pon:latest' locally latest: Pulling from kaizenjapan/100pon 05d1a5232b46: Download complete 33529d049adc: Downloading 62.4MB/94.96MB be72550a31b7: Downloading 61.89MB/1.522GB 40cab810eef6: Waiting 90a7cfada776: Waiting 63b10c589b27: Waiting 3b74f2e93e93: Waiting 4ad328879d5f: Waiting 53bb48f40962: Waiting 7430ebce441f: Waiting 152f700bなぜかエラーにならない。
何度か、この現象が現れたことがある。記録
- 投稿日:2019-01-26T01:51:22+09:00
MetabaseとMySQL環境をDockerで作る
はじめに
株価などネットから取得したデータをMySQLに格納し、
それを可視化したかったのでMetabsaeを試してみました。
環境作成にあたり、Dockerを利用しています。環境
- Mac OS X 10.14.2
- Docker version 18.09.0
- docker-compose version 1.23.2
参考
今回やりたい構成
ディレクトリ構成
. ├── Data │ └── mysql_data └── Docker └── docker-compose.yml永続化のためmysql_dataにMySQLのファイルを置きます。
環境作成
イメージがないこと確認
$ docker-compose images Container Repository Tag Image Id Size ----------------------------------------------docker compose用のファイル準備
docker-compose.ymlでみて欲しいところは以下
links
にmysqlと記載することで、Docker内はmysqlで名前解決できる。
volumes
にローカルのファイルをDockerコンテナにマウントする設定を記載することによってMySQLのデータをローカルに保存している。その結果データを永続化できる。docker-compose.ymlversion: "3" services: metabase: container_name: metabase image: metabase/metabase ports: - "3000:3000" links: - mysql mysql: container_name: mysql image: mysql:5.7.22 ports: - "3306:3306" environment: MYSQL_DATABASE: stock MYSQL_USER: stock MYSQL_PASSWORD: stock MYSQL_ROOT_PASSWORD: root volumes: - ../Data/mysql_data/:/var/lib/mysqlイメージを取得
$ docker-compose create WARNING: The create command is deprecated. Use the up command with the --no-start flag instead. Pulling mysql (mysql:5.7.22)... 5.7.22: Pulling from library/mysql be8881be8156: Pull complete c3995dabd1d7: Pull complete 9931fdda3586: Pull complete bb1b6b6eff6a: Pull complete a65f125fa718: Pull complete 2d9f8dd09be2: Pull complete 37b912cb2afe: Pull complete 79592d21cb7f: Pull complete 00bfe968d82d: Pull complete 79cf546d4770: Pull complete 2b3c2e6bacee: Pull complete Pulling metabase (metabase/metabase:)... latest: Pulling from metabase/metabase 4fe2ade4980c: Already exists 6fc58a8d4ae4: Pull complete 819f4a45746c: Pull complete cfead1870569: Pull complete 80eef12953dc: Pull complete 8ea161a68113: Pull complete db7c1ab963fb: Pull complete Creating mysql ... done Creating metabase ... done $ docker-compose images Container Repository Tag Image Id Size -------------------------------------------------------------- metabase metabase/metabase latest 0e41d8de8452 221 MB mysql mysql 5.7.22 6bb891430fb6 355 MB起動
$ docker-compose up -d Starting mysql ... done Starting metabase ... done-dをつけてデタッチドモードにしないと、ターミナルに戻ってこれない。
動作確認(MySQL)
$ mysql --host=127.0.0.1 --user=stock --password Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.22 MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | stock | +--------------------+ 2 rows in set (0.02 sec)Metabaseの設定
初期セットアップ
http://localhost:3000/setup
にアクセスdocker-compose.ymlの
links
に記載したmysqlがホスト名今回は事前にデータをMySQLに表を作成していたので、MySQLに入っている表の一覧が表示される。
表の名前をクリックすると、勝手にSummaryしている。
もちろん表のデータから色々なグラフ(円グラフや棒グラフ、線グラフ)などをSQLからも作成可能。
おまけ
停止
$ docker-compose stop Stopping metabase ... done Stopping mysql ... done起動(環境削除していない場合)
$ docker-compose start Starting mysql ... done Starting metabase ... done環境削除
コンテナを停止し、そのコンテナとネットワークを削除
$ docker-compose down $ docker-compose down Stopping metabase ... done Stopping mysql ... done Removing metabase ... done Removing mysql ... done Removing network docker_default環境削除(imageも削除)
上に加えて、imageも削除
$ docker-compose down --rmi all Removing metabase ... done Removing mysql ... done Removing network docker_default Removing image mysql:5.7.22 Removing image metabase/metabase
- 投稿日:2019-01-26T00:53:46+09:00
さくっと分析環境構築
欲しい分析環境
AzureVM上にdockerでpostgre日本語環境を立ち上げる。
だいぶ簡単になったが、半年やらなかったら忘れそうなので備忘録に。
GPU使うDeepLearningとか以外はだいたいこの環境でなんとかなる。Azure data science vm for Linux
- Microsoft R Server Developer エディションと Microsoft R Open
- Anaconda Python ディストリビューション (バージョン 2.7 および 3.5)
- JuliaPro
- スタンドアロン Spark インスタンスと単一ノードの Hadoop (HDFS、Yarn)
- JupyterHub - R、Python、PySpark、Julia カーネルをサポート
- Vowpal Wabbit
- XGBoost, LightGBM
- 開発ツールとエディター (RStudio、PyCharm、IntelliJ、Emacs、vim)
postgres日本語環境
分析用にSQL環境が欲しかった。ただし、日本語が混じったデータだったのが少し面倒。
HOW TO
VMの立ち上げ
MacketPlaceのDatascience用Imageからさくっとデプロイ
細かい構成は省略。
Ubuntuのlocaleを日本語へ
sudo locale-gen ja_JP.UTF-8 sudo /usr/sbin/update-locale LANG=ja_JP.UTF-8そして再度ログインでlocaleがja_JP.UTF-8になっています。
docker-composeのインストール
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # バイナリに対して実行権限を追加 chmod +x /usr/local/bin/docker-composeDockerfile作成
適当なディレクトリにDockerfileとcomposeファイルを作成する。
DockerfileFROM postgres:latest RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 ENV LANG ja_JP.UTF-8docker-compose.yamlversion: '2' services: db: image: db volumes: - ./postgresql:/var/lib/postgresql ports: - "5432:5432" environment: POSTGRES_USER: username POSTGRES_PASSWORD: password POSTGRES_DB: testdb LANG: ja_JP.UTF-8DockerImageを作成、コンテナ起動
sudo docker build -t db sudo docker-compose up -d雑記
会社でVisualStudioサブスクリプションが購入していて、Azureが月6000円使えるのでAzureを使っています。
Standard DS3 v2 (4 vcpu 数、14 GB メモリ):1時間25.65円SQL叩ける環境ほしいな〜。おっ、やっぱクラウドサービスでてるじゃ〜〜ん。
…………………たけぇよ。というわけで、無料のOSSでデータ分析に向いてるというpostgresqlを利用することに。
またデータが日本語混じりのきったねぇデータなので、ロケール変更しました。
一度頑張って普通にpostgresインストールして同環境を作ったんだけど、環境ぶっ壊して再構築する時にキレそうになり(笑)、ついにdockerを覚える機会になった。遅いよ。
いい勉強になった。dockerさまさまですわ。
参考