概要
- 手を動かしながら docker コマンドの基礎を学びます。
- Docker イメージを使い、どのようにコンテナを動かすかを理解します。
- イメージを自動構築し、Docker Hub にアップロードします。
- Dockerfile の基本と、CMD と ENTRYPOINT の違いを理解します。
- 所要時間は約15~30分です。
発表資料(Dockerライフサイクルの基礎)の中からハンズオン部分だけを抽出したものです(コピー&ペーストの確認用)。こちらを副読資料として、あわせてご覧ください。
- Dockerライフサイクルの基礎 地雷を踏み抜けろ!
- http://www.slideshare.net/zembutsu/docker-underlying-and-containers-lifecycle
ハンズオン内容
ドキュメントの Get Started with Docker の内容をベースにしています。鯨が喋る whalesay イメージを実行します。また、自分で Dockerfile を使って自分だけの whalesay イメージを Docker Hub のリポジトリ上にアップロードします。
事前準備
Docker を動かすための環境が必要です。インストールやセットアップの方法については、各ドキュメントをご覧ください。
ハンズオン
練習1. hello-world コンテナの実行
Docker が正常に使えるかどうかを確認します。 hello-world
という名前のイメージを使い、サンプルプログラムを実行します。
コンテナを実行するには、 docker run
コマンドを使います。書式は以下の通りです。
$ docker run <オプション> イメージ名:タグ <コマンド>
それでは、 hello-world
コンテナを実行します。
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
03f4658f8b78: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com
For more examples and ideas, visit:
https://docs.docker.com/userguide/
初回実行時、ローカル環境上に hello-world
イメージがないため、Docker Hub からイメージを自動的にダウンロードします。その後、コンテナとしてイメージを実行しました。
もう一度同じ docker run hello-world
コマンドを実行します。今度はローカルに既にイメージがありあますので、ダウンロードは発生しません。今あるイメージを使い、すぐにコンテナを起動できます。
練習2. イメージの確認と取得
ローカル環境上のイメージ一覧を確認するには docker images
コマンドを使います。先ほどの「hello-world」イメージがダウンロード済みかどうかを確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 690ed74de00f 6 months ago 960 B
次は Docker Hub から docker/whalesay
イメージをダウンロードします。ダウンロードするには docker pull
コマンドを実行します。
$ docker pull docker/whalesay
- これは
docker
ユーザのwhalesay
イメージを取得するという意味です。 - 「ユーザ名/」が無い場合や「library/」は公式イメージ(Docker社の精査済み)です。
再度 docker images
コマンドを実行し、whalesay
イメージがローカルにあるかどうか確認します。
$ docker images
hello-world latest 690ed74de00f 6 months ago 960 B
docker/whalesay latest 6b362a9f73eb 10 months ago 247 MB
なお、このイメージが置いてある場所をリポジトリと呼びます。このリポジトリやイメージの詳細な情報は Docker Hub 上でも確認できます。
練習3. イメージの実行
whalesay
イメージを使い、メッセージを表示するコンテナを実行します。 whalesay
イメージは Ubuntu 14.04 をベースに、cowsay
という鯨がメッセージを表示するプログラムが入っています。
docker
で whalesay
イメージの中にある cowsay
プログラムを実行します。
$ docker run docker/whalesay cowsay hello world
_____________
< hello world >
-------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
練習4. Dockerfile の作成
Dockerfileは、自動的にDockerイメージを構築(build)する時に必要になるファイルです。イメージを構成する全ての要素を記述します。
作業用ディレクトリを作成し、移動します。
$ mkdir mywhale
$ cd mywhale
任意のテキストエディタで Dockerfile
という名前のファイルを作成します。また、中身は以下のようにします。
FROM docker/whalesay:latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a | cowsay
-
FROM
RUN
CMD
はイメージ構築時の命令です。 -
FROM
は構築時の元になるイメージを指定します。これは先ほどと同じ whalesay です。 -
RUN
はコンテナの中でコマンドを実行します。fortunes プログラムのセットアップです。 -
CMD
はコンテナ実行時にデフォルトで実行する命令です。
練習5. イメージの構築
イメージを構築するには docker build
コマンドを使います。ここでは docker build
コマンドで「docker-whale」イメージを作成します。
$ docker build -t docker-whale .
-
-t
はイメージ名:タグ
を指定するオプションです。 - コマンドの最後に
.
(ドット記号)が必要です。現在(.
)のディレクトリをコンテキスト(イメージ内容)として指定し、そこにある Dockerfile を使ってイメージの自動構築を命令します。
再び docker images コマンドを実行し、イメージが作成されているかどうかを確認します
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-whale latest 2869f3029cd4 About a minute ago 274.9 MB
hello-world latest 690ed74de00f 6 months ago 960 B
docker/whalesay latest 6b362a9f73eb 10 months ago 247 MB
練習6. 新しいイメージを実行
作成したイメージ docker-whale
を使ってコンテナを実行します。
$ docker run docker-whale
______________________________________
/ Keep hands and feet away from moving \
\ parts at all times. /
--------------------------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
- Dockerfile で指定した CMD 命令を指定した
fortune
プログラムを実行し、その結果を cowsay プログラムに渡しています。 -
fortune
プログラムは、この docker-whale イメージの中にあるものです。 - 実行するたびに
fortune
プログラムをコンテナの中で実行します。都度、表示するメッセージが変わります。
練習7. イメージの詳細を確認
イメージの詳細を表示する docker inspect コマンドで、構築したイメージの情報を調べます。Cmd
セクションが、先ほど CMD 命令で指定したコマンドになっていることを確認します。
$ docker inspect docker-whale
(省略) "Cmd": [
"/bin/sh",
"-c",
"#(nop) CMD [\"/bin/sh\" \"-c\" \"/usr/games/fortune -a | cowsay\"]"
この方法を使えば、それぞれのイメージが、デフォルトでどのようなコマンドを実行するか、実行前に確認できます。このほかにも、環境変数・ポート情報・ネットワーク・ボリュームに関する各種の情報が確認できます。
次はイメージの構築履歴を docker history
コマンドで確認します。
$ docker history docker-whale
IMAGE CREATED CREATED BY SIZE COMMENT
2869f3029cd4 21 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/usr/g 0 B
dece11a04bd5 21 minutes ago /bin/sh -c apt-get -y update && apt-get insta 27.82 MB
(省略)
この1行1行がイメージ・レイヤです。先ほどの Dockerfile に記述した命令と対応していることに注意します。
練習8. Docker Hub に登録・ログイン
作成したイメージを Docker Hub で公開するため、まずはアカウントを作成します。既にお持ちであれば、次に進みます。
https://hub.docker.com/ にアクセスし、ユーザ名・パスワード・登録用のメールアドレス(認証に必要)を入力します。
- 登録は無料ですが、プライベート(非公開)のリポジトリを作る場合は課金が必要です。
- メールの件名は「Please confirm email for your Docker Hub account」(Docker Hub アカウント用のメールアドレスをご確認ください)です。本文中のリンクをクリックします。
練習9. リポジトリの作成
- Docker イメージを置く場所をリポジトリ(repository)と呼びます。
- ブラウザで Docker Hub を開き、
Create Repository
(作成)ボタンを押します。
- リポジトリ名は
docker-whale
とします(任意の名称も選択できますが、その場合は後の手順を都度変更願います)。 - 簡単な説明(必須)と詳細説明を追加できます。
- Visibilityは public(公開)か private(非公開)を選べます。
- 最後に「Create」ボタンを押すと、作成完了です。
練習10. イメージのタグ付け
改めて docker images で docker-whale のイメージ ID を確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-whale latest 2869f3029cd4 About a minute ago 274.9 MB
イメージ(ID)には、複数のイメージ名やタグを付けられます。docker tag
コマンドを使い、docker-whale イメージに Docker Hub 上のユーザ名を割り当て(タグ付け)ます。
$ docker tag イメージID ユーザ名/docker-whale:latest
例:
練習11. Docker Hub にログイン
docker login
コマンドを実行し、コンソール上から Docker Hub にログインします。
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: ユーザ名 ←自分のユーザ名
Password: ←パスワード
Login Succeeded
- 認証情報(アクセス用トークン)は
~/.docker/config.json
に保管されます。
練習12. Docker Hub に送信
Docker Hub 上のリポジトリに送信するには docker push コマンドを使います。先ほど docker tag
でタグ付けした「ユーザ名/docker-whale」イメージを送信します。
$ docker push ユーザ名/docker-whale
The push refers to a repository [docker.io/ユーザ名/docker-whale]
1f572a10291b: Pushed
5f70bf18a086: Mounted from docker/whalesay
d061ee1340ec: Mounted from docker/whalesay
d511ed9e12e1: Mounted from docker/whalesay
091abc5148e4: Mounted from docker/whalesay
b26122d57afa: Mounted from docker/whalesay
37ee47034d9b: Mounted from docker/whalesay
528c8710fd95: Mounted from docker/whalesay
1154ba695078: Mounted from docker/whalesay
latest: digest: sha256:b597a0451116a63e5eaaa3b3214c77042f180a31c303522db998b37e2c2ddd12 size: 8095
ブラウザでDocker Hub を開き、リポジトリの状態を確認します。
練習13. イメージの削除と再実行
ローカルのイメージは docker rmi
(remove imageの意味)コマンドで削除できます。先ほど作成したイメージを削除します。イメージIDもしくはイメージ名やタグを指定して削除します。
$ docker rmi –f docker-whale
$ docker rmi –f ユーザ名/docker-whale
-
-f
は強制削除のオプションです。
イメージを Docker Hub から取得・実行します。
$ docker run ユーザ名/docker-whale
- ローカルにイメージはありません。Docker Hub からイメージをダウンロードして実行します。
以上が、最も簡単なコンテナのライフサイクルになります。
後片付け
- 不要なイメージは
docker rmi
コマンドで削除できます。 -
docker run
コマンドの処理内容を思い出します。 - コマンドを実行する度に、毎回イメージレイヤを作成しています。
-
docker ps -a
コマンドを実行すると、全てのイメージレイヤを表示します。
コンテナ(のイメージ・レイヤ)を削除するコマンドはdocker rm
removeの意味です。
次のコマンドで、停止中のコンテナを一括削除します。
$ docker rm $(docker ps -aq)
- 「-a」は全て「-q」はイメージIDのみ表示するオプションで、結果を docker rm に送ります。
- 同様に「docker rmi $(docker images -q)」でイメージの全削除も可能です。
ハンズオン(Dockerfile活用編)
CMD 命令の理解
ping を実行するコンテナを通して、挙動の違いを理解していきます。まず、ping を実行する myping コンテナを作成します。そのため、ディレクトリを作成し、移動します。
$ mkdir myping
$ cd myping
Dockerfile を作成し、中身を以下のようにします。
FROM busybox
CMD ["ping","-c","10","127.0.0.1"]
- Busybox という小さな Linux ディストリビューション上の
ping
コマンドを実行する命令です。
イメージ myping
を構築します。
$ docker build -t myping .
myping
イメージを使ったコンテナを実行します。
$ docker run --rm myping
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.217 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.193 ms
64 bytes from 127.0.0.1: seq=3 ttl=64 time=0.095 ms
64 bytes from 127.0.0.1: seq=4 ttl=64 time=0.095 ms
64 bytes from 127.0.0.1: seq=5 ttl=64 time=0.173 ms
64 bytes from 127.0.0.1: seq=6 ttl=64 time=0.100 ms
64 bytes from 127.0.0.1: seq=7 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: seq=8 ttl=64 time=0.092 ms
64 bytes from 127.0.0.1: seq=9 ttl=64 time=0.094 ms
--- 127.0.0.1 ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 0.090/0.123/0.217 ms
-
--rm
オプションは、コンテナ実行後、自動的にイメージレイヤを破棄します。都度、docker rm を実行する必要がないため、コマンドとして使う場合に便利です。 - Dockerfile の
CMD [“ping”,“-c”,“10”,“127.0.0.1”]
は、自分自身に対して ping を 10 回実行するという意味です。
次は myping コンテナの引数に sh
を指定して実行します。
$ docker run –i -t myping sh
/ #
-
-i
はコンテナの標準入出力を有効にします。 -
-t
は疑似ターミナルを有効にします。 -
exit
で終了します。
sh
コマンドを指定したため、CMD 命令は無視されました。
ちなみに、busybox イメージや Ubuntu イメージを実行時、オプションを何も指定しなくてもシェルが起動するのは、各 Dockerfile の CMD 命令でシェルが指定されているからです。
- Ubuntu イメージの Dockerfile
CMD [“/bin/bash”]
- Busybox イメージの Dockerifle
CMD [“sh”]
このように CMD 命令は、コンテナ実行時にコマンドを指定すると無視されます。
ENTRYPOINT との比較
Dockerfile を開き、CMD
命令を ENTRYPOINT
に書き換えます。
FROM busybox
ENTRYPOINT ["ping"]
再度イメージを構築します。バージョン 1.1
をタグ付けします。
$ docker build -t myping:1.1 .
構築したイメージ myping:1.1
を実行します。
$ docker run --rm myping:1.1
BusyBox v1.24.2 (2016-03-18 16:38:06 UTC) multi-call binary.
Usage: ping [OPTIONS] HOST
(省略)
-q Quiet, only display output at start
and when finished
-p Pattern to use for payload
何も指定しなくてもコマンドを実行するという意味では、CMD
も ENTRYPOINT
も同様の処理です。しかし、docker run
でコマンドの引数を付けると挙動が違います。
- CMD … docker run に引数があれば、CMD は無視する
- ENTRYPOINT … docker run に引数があれば、ENTRYPOINT のコマンドの引数として引数をあつかう。CMD は無視する。
myping:1.1 に IP アドレスを付けて実行します。
$ docker run --rm myping:1.1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.149 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.160 ms
64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.222 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.149/0.177/0.222 ms
-
ctrl+c
で中断します(通常の ping コマンドです)
ENTRYPOINT がある場合、あくまでも ENTYPOINT に記述したコマンドやオプションは docker run 実行時に固定です。これを上書きするには docker run 時に --entrypoint
オプションを使います。
次の Dockerfile を作成し、 myping イメージを構築します。
FROM busybox
CMD ["127.0.0.1"]
ENTRYPOINT ["ping","-c","3"]
引数を付けない場合と付けた場合で myping を実行し、それぞれの結果を比較します。
付けない場合:
$ docker run myping
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.130 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.311 ms
64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.171 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0%
付けた場合:
$ docker run myping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=56 time=1.812 ms
64 bytes from 8.8.8.8: seq=1 ttl=56 time=1.802 ms
64 bytes from 8.8.8.8: seq=2 ttl=56 time=1.863 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.802/1.825/1.863 ms
- ENTRYPOINT と CMD があれば、CMD は ENTRYPOINT に対するオプションになります。
- コンテナ実行時のオプションがあれば、ENTRYPOINT の引数としてオプションを使います。
- ENTRYPOINT は、あたかもコマンドを実行するようにコンテナを扱えるようにします。
以上です。おつかれさまでした
更に詳しく知るには?
ドキュメント:
元の発表スライドには、もう少し細かい解説や背景も紹介しています。