環境
その1でコンテナの起動方法、その2でコンテナがどんな状態にあるかを確認する方法を書きました。
続くその3ではregistryから取得してきたイメージをもとに自分だけのイメージを作成する方法を書きます。
以下の環境でDockerの基本操作を確認します。
項目 | 今回のシステム |
---|---|
OS | CentOS 7.0 (on VirtualBox) |
Docker | docker-1.3.2 |
Dockerfileからイメージを作る
自分だけのイメージを作成するにはDockerfile
を用いるのが簡単な方法です。
Dockerにはdocker build
というDockerfile
を読み込んでイメージを作るコマンドがあります。
その1ではbashを起動してコンテナ内でRubyをインストールし、Webサーバを立てました。
ここでは具体例としてそれと同じことをDockerfile
を使って実現します。
Dockerfile作成
# "#"で始まる行はコメント行とみなされます。
# Dockerfileは必ずベースとなるイメージを指定するFROMから書きます。
FROM ubuntu:14.04
# MAINTAINERには文字通りDockerfile作成者を記載します。
MAINTAINER smile-0yen smile0yen.1024@gmail.com
# RUNは指定されたコマンドをコンテナ内で実行し、結果をイメージとして保存します。
RUN apt-get install ruby -y
# EXPOSEはコンテナの外に対して開くポートを指定します。
# 親ホストのどのポートにマッピングするかはコンテナ起動時に決定します。
EXPOSE 8080
# WORKDIRによってこの行以降のRUN及びCMDを実行するディレクトリを指定できます。
WORKDIR /opt
# CMDにはコンテナが起動したあとに実行されるコマンドを指定します。
CMD ruby -run -e httpd . -p 8080
Dockerfile
内での命令はインストラクション(Instruction)と呼ばれます。非常にシンプルな記述が特徴です。
大文字である必要はありませんが可読性のために全て大文字で書くことが推奨されています。
インストラクション | 説明 |
---|---|
FROM <イメージ>:<タグ> | ベースとなるイメージを指定します。Dockerfile の先頭は必ずFROMで始めます。 |
MAINTAINER <名前> | イメージの作者を明示します。指定するとイメージ内にAuthor 情報として記録されます。 |
RUN <コマンド> | 任意のコマンドを/bin/sh -c に渡してコンテナ内で実行します。/bin/sh がベースイメージにない場合などexec 形式で(*)でコマンドを実行することも可能です。 |
CMD <コマンド> | コマンドを/bin/sh -c に渡してコンテナ起動時に実行します。ただし、 docker run でコンテナを起動する際に別のコマンドを渡したときにはCMDはそちらで上書きされるため実行されません。 なお、CMDは1つにDockerfileにつき1回しか指定できません。 /bin/sh を使いたくない場合はexec形式(*)で実行します。 |
ENTRYPOINT <コマンド> | CMDと同様にコンテナ起動時に実行するコマンドを指定します。 こちらは docker run で渡された別のコマンドで上書きされません。docker run で渡されたコマンドはENTRYPOINTで指定したコマンドの後ろへコマンドラインオプションとして追加されます。 CMDとENTRYPOINTをどちらも指定した場合、CMDの値は ENTRYPOINTで指定したコマンドのデフォルト引数と解釈されます。 /bin/sh で起動されたくない場合exec形式(*)で実行します。 |
EXPOSE <ポート番号> | コンテナ起動時に内部でLISTENするポートを指定します。 親ホストへのポートマッピングは起動時に別途指定が必要です。 Dockerfile内で親のポートを予め指定することはできません。 |
ENV <変数名> <値> | 環境変数を設定します。 |
WORKDIR <ディレクトリ> |
Dockerfile 内でRUN, CMD, ENTRYPOINTより前に書くとそれらインストラクションの実行ディレクトリを指定できます。 またENVのあとに書けばENVで設定した環境変数を参照できます。 |
USER <ユーザー> |
Dockerfile 内でRUN, CMD, ENTRYPOINTより前に書くとそれらインストラクションの実行ユーザーを指定できます。 |
VOLUME <ディレクトリ> | このインストラクションでマウントポイントを指定しておくと、 そのディレクトリを親ホストや他のコンテナと共有できるように設定します。 |
ADD <コピー元> <コピー先> | ディレクトリ、ファイル(複数可)をコンテナ内にコピーします。 コピー元は docker build 実行ディレクトリからの相対パス(ただし親ディレクトリは不可)、コピー先はコンテナ内の 絶対パスです。指定には正規表現を利用できます。 次のCOPYと異なりコピー元にURLも指定できます。また特定の形式 (identity, gzip, bzip2, xz)で圧縮されたファイルがコピー元の場合は 解凍してからコンテナ内に設置します。 |
COPY <コピー元> <コピー先> | ディレクトリ、ファイル(複数可)をコンテナ内にコピーします。 コピー元は docker build 実行ディレクトリからの相対パス(ただし親ディレクトリは不可)、コピー先はコンテナ内の 絶対パスです。指定には正規表現を利用できます。 |
ONBUILD <インストラクション> |
Dockerfile でbuild したイメージをベースに新たにイメージを作るとき実行したいインストラクションを予め書いておくことができます。 |
(*)exec形式: <インストラクション> [ "実行ファイル","引数1","引数2" ]
の形式。
例. RUN ["/bin/bash", "-c", "echo hello"]
イメージ作成(docker build)
実行例
Dockerfile
からイメージを作るにはdocker build -t <イメージ名:タグ> <Dockerfileパス>
を使います。
-
-t
オプションで作成するイメージに名前とタグをつけることができます。 - コマンドの最後には
Dockerfile
の置かれているディレクトリを指定します。
今回はカレントディレクトリにDockerfile
が置いてある想定で「.」を指定しています。
$ sudo docker build -t web_server .
実行結果確認
指定した名称web_serverで新たにイメージができたことが確認できます。
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
web_server latest 455927c8e660 10 minutes ago 210 MB
(以下略)
コンテナ起動
早速作成したイメージを元にコンテナ起動です。
$ sudo docker run -d -v /tmp/docker:/opt -p 80:8080 web_server
/tmp/docker/test.txt
へ何かメッセージを記載して、起動したサーバへブラウザからアクセスします。
http://localhost:8888/test.txt
*ポート8888を指定しているのは今回の環境ではCentOS 7が起動しているVMの80を8888へフォワーディングしているため。
その1と同様にWebサーバへブラウザからアクセスが確認できれば成功です。
その2で見たようにdocker logs
コマンドでログ確認してみます。
まずは起動中のコンテナのIDを確認。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb5df2b423ea web_server:latest "/bin/sh -c 'ruby -r 18 minutes ago Up 18 minutes 0.0.0.0:80->8080/tcp boring_hopper
IDを指定してコンテナ内のログ出力を見ると確かに先ほどのアクセスが記録されていました。
$ sudo docker logs --tail="3" fb5df
[2015-01-13 15:14:11] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
10.0.2.2 - - [13/Jan/2015:15:14:11 UTC] "GET /test.txt HTTP/1.1" 304 0
- -> /test.txt
イメージの中身を確認する
イメージの更新履歴を確認する docker history
イメージはベースとしたイメージとの差分を積み重ねて作られています。
そのことを端的に確認するにはdocker history <イメージ>
を使います。
実行例
$ sudo docker history web_server
実行例結果
これまでの変更の歴史が全て記録されています。作成時のコマンドが途中で切られていますが
オプション--no-trunc
をつけると実行コマンド全体を確認することができます。
$ sudo docker history web_server
IMAGE CREATED CREATED BY SIZE
455927c8e660 3 days ago /bin/sh -c #(nop) CMD [/bin/sh -c ruby -run - 0 B
9307eadf28da 3 days ago /bin/sh -c #(nop) WORKDIR /opt 0 B
c2bbe183f761 3 days ago /bin/sh -c #(nop) EXPOSE map[8080/tcp:{}] 0 B
c75722c696c8 3 days ago /bin/sh -c apt-get install ruby -y 17.29 MB
e82e1a53528e 3 days ago /bin/sh -c #(nop) MAINTAINER smile-0yen smile 0 B
ed5a78b7b42b 3 weeks ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
8c4b1edcceea 3 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
9a4594fe74ea 3 weeks ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
fe95bf7d5f50 3 weeks ago /bin/sh -c #(nop) ADD file:c032cb16120c7533b5 192.5 MB
511136ea3c5a 19 months ago 0 B
--no-trunc
オプションをつけた場合
$ sudo docker history --no-trunc web_server
IMAGE CREATED CREATED BY SIZE
455927c8e6600f79ba6dda8e03709051a251a1dfb96f634b95959e8bfb0d5174 3 days ago /bin/sh -c #(nop) CMD [/bin/sh -c ruby -run -e httpd . -p 8080] 0 B
9307eadf28dadd4f21ea14024343c69de924d6766494fa73015aec8daf43ae1f 3 days ago /bin/sh -c #(nop) WORKDIR /opt 0 B
c2bbe183f7613773d0dc03670730acc2def499e85efa97074132698918a739d8 3 days ago /bin/sh -c #(nop) EXPOSE map[8080/tcp:{}] 0 B
c75722c696c8ecb42d8d9fc31f0b260845b881a59cc7881fe1761fc7360ba776 3 days ago /bin/sh -c apt-get install ruby -y 17.29 MB
e82e1a53528eaf869bca0a16ea9423853c077d06b0b1bfccfdd6a207790281f2 3 days ago /bin/sh -c #(nop) MAINTAINER smile-0yen smile0yen.1024@gmail.com 0 B
ed5a78b7b42bde1e3e4c2996e02da778882dca78f8919cbd0deb6694803edec3 3 weeks ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
8c4b1edcceea5c11f0a43de6c990036cffbd63f5590cba0075042c66cd90d948 3 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list 1.895 kB
9a4594fe74ea4c14e642b871556f1460f6d332350bf3c772e76ed0059444ff19 3 weeks ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/policy-rc.d && echo 'exit 101' >> /usr/sbin/policy-rc.d && chmod +x /usr/sbin/policy-rc.d && dpkg-divert --local --rename --add /sbin/initctl && cp -a /usr/sbin/policy-rc.d /sbin/initctl && sed -i 's/^exit.*/exit 0/' /sbin/initctl && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes 194.5 kB
fe95bf7d5f5090fdaf5c5d442f9f05211f9cb338107a41ff10c7a46be4be2dea 3 weeks ago /bin/sh -c #(nop) ADD file:c032cb16120c7533b582d0c03b3e19314915f7674c000eda0cd36853005a880e in / 192.5 MB
511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158 19 months ago 0 B
イメージの詳細を確認する docker inspect
イメージに記録されている詳細な情報を確認するにはdocker inspect <イメージ>
を使います。
あまり使うことはないかもしれませんが全ての設定情報をJSON形式で確認できますので便利です。
実行例
$ sudo docker inspect web_server
実行例結果
[{
"Architecture": "amd64",
"Author": "smile-0yen smile0yen.1024@gmail.com",
"Comment": "",
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"/bin/sh",
"-c",
"ruby -run -e httpd . -p 8080"
],
"CpuShares": 0,
"Cpuset": "",
"Domainname": "",
"Entrypoint": null,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"ExposedPorts": {
"8080/tcp": {}
},
(以下略)
まとめ
- イメージ作成の基本は
Dockerfile
へインストラクションを書いてdocker build -t <イメージ名:タグ> <Dockerfileパス>
-
Dockerfile
によってイメージをコードとして管理できる。 - イメージの変更履歴を確認するには
docker history <イメージ>
。 - イメージの詳細情報を確認するには
docker inspect <イメージ>
。