社内でDocker入門講座を開催した時に作った資料。
公式ドキュメント
Dockerとはなんぞや
- Dockerは仮想化技術の一つ(VirtualBOX, HyperVと同じくくり)
- OS(カーネル)の上にコンテナ層を作ることを発明した
- Linuxしか動かせないが、その代わり軽くて速い
- コンテナはDockerイメージ(isoイメージみたいなやつ)をもとに生成できる
- 色々なDockerイメージがDockerHubで公開されている
何が嬉しいの?
- 起動が早くてキビキビ動くので、取り回しやすい
- リソース消費量が少ないので、1プロセス1コンテナみたいな世界が可能になる
- イメージのサイズが小さいのとDockerHubがあるおかげで公開がとても楽
インストール
公式サイトでDocker Desktopのインストーラーをダウンロードしてインストールしてください。
WindowsにDocker toolboxをインストールしている記事を見かけることがありますが、2020年2月時点ではDocker toolboxは廃止されて非推奨となっているようです。
基本的なコマンド一覧
結構種類があって大変ですが、この後ひとつひとつ実行して動作確認していきます。
コンテナ操作系
コマンド | 用途 |
---|---|
docker run | コンテナを生成して起動する |
docker exec | コンテナ内でコマンドを実行する |
docker ps | コンテナの状態を参照する |
docker stop | コンテナを停止する |
docker start | コンテナを起動する |
docker rm | コンテナを削除する |
docker logs | コンテナのログを参照する |
Dockerイメージ操作系
コマンド | 用途 |
---|---|
docker images | Dockerイメージの一覧を参照する |
docker rmi | Dockerイメージを削除する |
docker commit | コンテナに対して行った変更をDockerイメージとして保存する |
docker build | DockerfileからDockerイメージを作成する |
docker login | Dockerイメージのリポジトリサイトにログインする |
docker push | リポジトリにDockerイメージを格納する |
他にも色々ありますので、気になる人はdocker --help
で確認してみてください。
チュートリアル1(コンテナを操る)
チュートリアル1ではdockerコマンドを実際に叩いてみて、Dockerに慣れていきましょう。
NginxをDocker上で起動する
以下の通りdocker run
コマンドを実行してください。
$ docker run -d -p 8080:80 --name=nginx nginx:latest
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
bc51dd8edc1b: Pull complete
66ba67045f57: Pull complete
bf317aa10aa5: Pull complete
Digest: sha256:ad5552c786f128e389a0263104ae39f3d3c7895579d45ae716f528185b36bc6f
Status: Downloaded newer image for nginx:latest
6a4692e3ff5f601b1c81c7a720888251b5b7ac3fe0d02bb90de736488a35f28b
docker run
を実行すると、DockerHubからDockerイメージがダウンロードされ、それを使ってコンテナが生成されます(docker run のオプションについてはマニュアルを参考にしてください)。http://localhost:8080 にアクセスするとNginxが起動しているのが確認できるかと思います。
コマンド内のnginx:latest
という部分がDockerイメージの識別子になります。Dockerイメージは{リポジトリ名}:{タグ}
で一意に識別されるので覚えておいてください。latestタグは最新バージョンのDockerイメージに付与されるタグです。もしdocker run
実行時にタグを省略した場合は、latestタグが使用されます。
コンテナの状態を確認してみる
docker images
でDockerイメージの一覧を表示できます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2073e0bcb60e 44 hours ago 127MB
Dockerイメージの一覧にnginxが追加されているかと思います。これが先程docker run
実行時にDockerHubからダウンロードされたDockerイメージです。
次にコンテナの状態をdocker ps
で確認しましょう。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e3aa2d731f3 nginx:latest "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp nginx
Nginxのコンテナが作成されていて、STATUSがUp(稼働中)であることが分かります。
Nginxのコンテナ内でBashを実行する
コンテナ内で何かしらのコマンドを実行したいときは、docker exec
を使います。
$ docker exec -it nginx /bin/bash
root@4e3aa2d731f3:/#
Nginxのコンテナ内で実行されたBashに繋がったかと思います。ここでls -l
コマンドでNginxのログフォルダを確認してみてください。
root@4e3aa2d731f3:/# ls -l /var/log/nginx
total 0
lrwxrwxrwx 1 root root 11 Feb 2 08:06 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Feb 2 08:06 error.log -> /dev/stderr
ログファイルではなく、標準出力、標準エラー出力に繋がれたシンボリックリンクがありました。基本的にコンテナの世界ではログは標準出力および標準エラー出力に出力するのが習わしとなっています。そうすると、出力した文字列がDockerによってホストOSに転送され、docker logs
コマンドで参照することができるようになります。Nginxコンテナもこれに倣ってログを標準出力、標準エラー出力に吐くよう作られているわけです。では一旦exit
でシェルを抜けて、docker logs
コマンドを実行してみましょう。
Nginxのログを見てみる
$ docker logs nginx
172.17.0.1 - - [04/Feb/2020:03:48:15 +0000] "GET /robots.txt HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" "-"
2020/02/04 03:48:15 [error] 6#6: *1 open() "/usr/share/nginx/html/robots.txt" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /robots.txt HTTP/1.1", host: "localhost:8080"
172.17.0.1 - - [04/Feb/2020:03:48:15 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" "-"
172.17.0.1 - - [04/Feb/2020:03:48:16 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost:8080/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" "-"
2020/02/04 03:48:16 [error] 6#6: *2 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
先程アクセスしたログが確認できるかと思います。ちなみにdocker logs -f
としてやると、tail -f
のようにログの追記を監視することができます。
コンテナを停止して起動する
コンテナを停止するときはdocker stop
です。
$ docker stop nginx
nginx
コンテナが停止し、http://localhost:8080 にアクセスできなくなっているはずです。docker ps
で状態を確認します。
$ docker ps
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Nginxのコンテナが表示されなくなりました。ただしNginxのコンテナは停止しているだけで削除されたわけではありません。停止しているコンテナも含めて表示するにはdocker ps -a
とやります。
$ docker ps -a
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e3aa2d731f3 nginx:latest "nginx -g 'daemon of…" About an hour ago Exited (0) 2 minutes ago nginx
このようにNginxのコンテナが表示され、STATUSがExitedであることが確認できます。このコンテナを再度起動するにはdocker start
を実行します。
$ docker start
nginx
もう一度docker ps
コマンドを叩くと、またNginxコンテナが表示され、STATUSがUp(稼働中)であることが分かります。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e3aa2d731f3 nginx:latest "nginx -g 'daemon of…" About an hour ago Up 23 seconds 0.0.0.0:8080->80/tcp nginx
コンテナを削除する
コンテナの削除はdocker rm
です。ただし、起動中のコンテナは削除できませんので、いったんdocker stop
で停止してから削除してください。
$ docker stop nginx
nginx
$ docker rm nginx
nginx
これでコンテナが削除されるため、docker ps -a
を叩いてもNginxは表示されません。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Dockerイメージを削除する
先程コンテナは削除しましたが、Dockerイメージはまだ残っています。後片付けとしてDockerイメージも削除しましょう。docker rmi
コマンドで削除できます。
docker rmi nginx:latest
Untagged: nginx:latest
Untagged: nginx@sha256:ad5552c786f128e389a0263104ae39f3d3c7895579d45ae716f528185b36bc6f
Deleted: sha256:2073e0bcb60ee98548d313ead5eacbfe16d9054f8800a32bedd859922a99a6e1
Deleted: sha256:a3136fbf38691346715cac8360bcdfca0fff812cede416469653670f04e2cab0
Deleted: sha256:99360ffcb2da18fd9ede194efaf5d4b90e7aee99f45737e918113e6833dcf278
Deleted: sha256:488dfecc21b1bc607e09368d2791cb784cf8c4ec5c05d2952b045b3e0f8cc01e
この状態でdocker images
コマンドを叩くと、NginxのDockerイメージが削除されていることが確認できるかと思います。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
以上でチュートリアル1は完了です。
ここまでの知識で、DockerHub上で公開されているDockerイメージが利用できるはずです。最近はOSSの配布をDockerで行うことが増えてきました。Dockerを使うと複雑なアプリケーション(3層アーキテクチャとか)でも簡単にインストールできます。また、コンテナはホストOSの環境と切り離されているため、ローカルPCの環境が汚れてしまう恐れもありません。コンテナを削除すると環境もろとも綺麗に削除されます。この気軽さがDockerを使う大きなメリットの一つです。DockerHubには様々なDockerイメージが公開されているので、ぜひ色々動かしてみてください。
チュートリアル2 (Dockerイメージをカスタマイズする)
dockerコマンドに慣れたら、次のステップとしてオリジナルのDockerイメージの作成に挑戦してみましょう。チュートリアル2ではPythonの開発環境用にDockerイメージを作成します。
Docker HubでPythonを検索
DockerHubにアクセスします。アカウントを持っていない人はサインアップしてください。Pythonで検索すると、PythonのDockerイメージが見つかるかと思います。
DockerHubには、公式のイメージだけでなく個人が作った信頼性の低いDockerイメージも公開されています。DockerHubを使う際は、「VERIFIED PUBLISHER」や「OFFICIAL IMAGE」のラベルがあるかどうかや、ダウンロード数、スター数を参考にして信頼性を確認するようにしましょう。
ではPythonを選択して、Tagsをクリックしてタグを表示してください。
様々なタグがあることが確認できるかと思います。Pythonの場合、Python自体のバージョンと、OSのバージョンでタグが付けられているようです。ここでは3.8.1-buster
を使うことにします。busterというのはDebianというOSのバージョン10のコードネームです。つまり、Debian10にpythonがインストールされた状態のDockerイメージということになります。
コンテナを起動
docker run
でコンテナを起動します。名前はmypythonにしました。Dockerイメージのサイズが大きいので割と時間がかかります。
$ docker run -d -it --name mypython python:3.8.1-buster
Unable to find image 'python:3.8.1-buster' locally
3.8.1-buster: Pulling from library/python
dc65f448a2e2: Pull complete
346ffb2b67d7: Pull complete
dea4ecac934f: Pull complete
8ac92ddf84b3: Pull complete
a3ca60abc08a: Pull complete
9253bd2ee3f6: Pull complete
fad96c8dce44: Pull complete
ec0f51d2752d: Pull complete
ff10001c6dc3: Pull complete
Digest: sha256:db86894e8fcdb6ca371e1143cbc646ef554ca83c5a85dc4a13f427e085153bb5
Status: Downloaded newer image for python:3.8.1-buster
39c933d7c9a31329b8be6e3aaba62f1454f7089844b2351da5c050a3ffff5e61
起動できたら、コンテナ内のBashに接続して、Pythonのバージョンを確認してみます。
docker exec -it mypython /bin/bash
root@35c8bacc3411:/# python --version
Python 3.8.1
root@35c8bacc3411:/# pip --version
pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
ちゃんとバージョン3.8.1がインストールされているのが確認できます。
コンテナをカスタマイズ
このコンテナを開発環境用にカスタマイズしていきます。なんでも良いですが、今回は開発にPandasが必要になったという想定で、Pandasをインストールしてみます。
root@35c8bacc3411:/# pip install pandas
Collecting pandas
Downloading pandas-1.0.0-cp38-cp38-manylinux1_x86_64.whl (9.9 MB)
|████████████████████████████████| 9.9 MB 10.1 MB/s
Collecting numpy>=1.13.3
Downloading numpy-1.18.1-cp38-cp38-manylinux1_x86_64.whl (20.6 MB)
|████████████████████████████████| 20.6 MB 591 kB/s
Collecting pytz>=2017.2
Downloading pytz-2019.3-py2.py3-none-any.whl (509 kB)
|████████████████████████████████| 509 kB 10.0 MB/s
Collecting python-dateutil>=2.6.1
Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
|████████████████████████████████| 227 kB 11.2 MB/s
Collecting six>=1.5
Downloading six-1.14.0-py2.py3-none-any.whl (10 kB)
Installing collected packages: numpy, pytz, six, python-dateutil, pandas
Successfully installed numpy-1.18.1 pandas-1.0.0 python-dateutil-2.8.1 pytz-2019.3 six-1.14.0
root@35c8bacc3411:/# python
Python 3.8.1 (default, Feb 2 2020, 08:37:37)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>> exit()
root@35c8bacc3411:/#
インストールできました。次にこのコンテナを使って新しいmypythonという名前のDockerイメージを作成します。exit
でシェルを抜けて、docker commit
を実行します。
xxxxxの箇所はご自身のDockerHubのユーザー名に置き換えてください。
$ docker commit mypython xxxxx/mypython:3.8.1-buster
sha256:8e8066959b691698077fc78988dbc09d77a7e586b010e690f9e22ed093da9b80
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xxxxx/mypython 3.8.1-buster 80db86c8f1ae 5 seconds ago 1.1GB
python 3.8.1-buster eeadc22d21a9 47 hours ago 933MB
xxxxx/mypythonという名前のDockerイメージが作成されているのが確認できます。
コンテナをDockerHubで公開する
このmypythonをDockerHubで公開して、他の人とシェアできるようにしてみます。それほど難しい操作は必要なく、docker login
コマンドでDockerHubにログインし、docker push
するだけで簡単に公開できます。
$ docker login
(ご自身のID・パスワードでログインしてください)
$ docker push xxxxx/mypython:3.8.1-buster
これで、DockerHubのマイページにmypythonが表示されているはずです。DockerHubにアクセスして確認してみましょう。
このようにDockerイメージ化することで、開発環境をチームで共有することが可能になります。Dockerが実行環境の差異を吸収してくれるので、もしチームの中にWindowsユーザーとMacユーザーとLinuxユーザーが混在していたとしても環境差異でハマることが殆どありません。環境差異に悩まなくて良いのもDockerの大きなメリットの一つです。
Dockerイメージを作成するもう一つの方法
先程行ったDockerイメージのカスタマイズでは、
- カスタマイズのベースとなるDockerイメージを使ってコンテナを起動
- コンテナ内のBashに接続
- 何かしらをインストール
- docker commitコマンドでオリジナルのDockerイメージを作成
という流れでDockerイメージを作成しましたが、それとは別にdocker build
コマンドを使う方法もあります。docker build
を使った方法では、まずDockerfileを作成します。(Dockerfileというファイル名です。拡張子はありません。)
以下がDockerfileの例です。上記の手順の1〜3をスクリプトで自動化するようなイメージです。
FROM python:3.8.1-buster
RUN pip install pandas
そして、Dockerfileのあるフォルダ上で、docker build
コマンドを実行すると、xxxxx/mypythonという名前のDockerイメージが自動的に作成されます。
$ docker build -t xxxxx/mypython:3.8.1-buster .
Sending build context to Docker daemon 300.6MB
Step 1/3 : FROM python:3.8.1-buster
---> eeadc22d21a9
Step 2/3 : RUN pip install pandas
---> Running in 290d7be35a90
Collecting pandas
Downloading pandas-1.0.0-cp38-cp38-manylinux1_x86_64.whl (9.9 MB)
Collecting numpy>=1.13.3
Downloading numpy-1.18.1-cp38-cp38-manylinux1_x86_64.whl (20.6 MB)
Collecting python-dateutil>=2.6.1
Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Collecting pytz>=2017.2
Downloading pytz-2019.3-py2.py3-none-any.whl (509 kB)
Collecting six>=1.5
Downloading six-1.14.0-py2.py3-none-any.whl (10 kB)
Installing collected packages: numpy, six, python-dateutil, pytz, pandas
Successfully installed numpy-1.18.1 pandas-1.0.0 python-dateutil-2.8.1 pytz-2019.3 six-1.14.0
Removing intermediate container 290d7be35a90
---> e67c3fa0fb05
Step 3/3 : ENTRYPOINT /bin/bash
---> Running in 16b989c8b647
Removing intermediate container 16b989c8b647
---> f50c90e2b7df
Successfully built f50c90e2b7df
Successfully tagged xxxxx/mypython:3.8.1-buster
この方法はDockerイメージの作成を自動化できるため、何度もDockerイメージを作成する必要がある場合に向いています。一般的にCIツールと組み合わせて自動化することが多いです。Dockerfileの構文を覚える必要があるので今回は時間的に解説できませんが、興味がある方は、Dockerfile リファレンス、Best practices for writing Dockerfiles などを読んでみてください。
以上でチュートリアル2は完了です。
Docker Tips
Dockerに関するTipsをいくつか紹介します。
docker runのオプション
以下のオプションを常に付けることをおすすめします。
オプション | 意味 |
---|---|
-d | バックグラウンドで実行 |
–rm | コンテナ停止時に自動的にコンテナを削除 |
–name {名前} | コンテナに名前を付ける |
-d
を常に付ける理由は、Dockerコンテナを不用意に停止させないためです。例えば、-d
を付けずに実行すると、
$ docker run -it --name mypython python:3.8.1-buster /bin/bash
root@da3508c54ee2:/# exit
exit
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
というように、プロセスが終了するとコンテナが停止してしまいます。デタッチ/アタッチという仕組みもありますが、それをやるなら-d
を使うほうが簡単です。
$ docker run -d -it --name mypython python:3.8.1-buster
13b59f84fc3d68f53c244e0801c336f6f439dce75a359ac1b5f05e96753c1bd9
$ docker exec -it mypython /bin/bash
root@13b59f84fc3d:/# exit
exit
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
13b59f84fc3d python:3.8.1-buster "/bin/bash" 9 seconds ago Up 7 seconds mypython
このように、コンテナのシェルにはdocker exec
で接続します。この方法だとシェルを抜けてもコンテナは停止しません。停止したいときはdocker stop
で明示的に停止します。
--rm
を付ける理由としては、コンテナを停止状態で置いておく必要がないからです。なのでコンテナを停止したら勝手に削除してくれたほうがコンテナを削除する手間が省けます。コンテナの中で作成したファイルを消したくないというケースはあるかと思いますが、それであればdocker run
時にホストOSのフォルダをマウントしてホストOS側に保存するか、もしくはdocker commit
でDockerイメージ化したほうが安全です。「コンテナを誤って削除してしまった」という事故を防げます。
--name
を付ける理由は、これをしないとDockerに割り当てられたランダムな単語を使ってコンテナの操作をしなければならなくなるからです。
$ docker run -d -it --rm python:3.8.1-buster
783aab3c9c46dda9ad44e8289871f1ac0594698ef85799b93da43587b357f336
d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
783aab3c9c46 python:3.8.1-buster "/bin/bash" 1 second ago Up Less than a second romantic_rhodes
というように、この場合ではromantic_rhodes
という名前か、もしくはCONTAINER IDを使わなければならず、操作性が低くなります。
docker runのコマンドが長くて見づらい
オプションが多くなった場合は、バックスラッシュで改行すると見やすいです。 (Windowsはキャレットで改行できる?)
$ docker run \
-d \
-it \
--rm \
--name mypython \
python:3.8.1-buster
Dockerイメージのゴミを削除したい
Dockerを使っていると、Dockerイメージのゴミが溜まってきます。そんなときはdocker system prune
とやると掃除できます。たまに実行すると良いかと思います。
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: koirand/mypython@sha256:09973f3e3a51d59d5d57306b928a3c24ee4cbd8baeda46ab60e3810e38c1d9d4
deleted: sha256:80db86c8f1ae595cedd7d909156bd0638e21ab7c6b6da48af57fff58bdd30e31
deleted: sha256:70eca39dc93885416684888ad63f2e68133c848e0708ffba0681d5938cfb6936
deleted: sha256:142edfeafc60e404b5038812ede95e8a5fb902b6e041231d9e0304eab7127a37
deleted: sha256:ef94e002c5727977623f12810fc8e8c45c8c89d80ec1d613c059e85b222bc61f
deleted: sha256:3f70246ee63ab87ba8717df29a81c7b5eb0812493da7e03b0c23363ec3513661
deleted: sha256:f5e1b6e88039e92cad924d47fafe4c0c533914cf2d8d136396f47e22e99a6f62
deleted: sha256:7d31605ba9a91ad8c70438b2dbb8fee6f599b165137f03a58b918274dbd106eb
deleted: sha256:930f81dcf389890495ca1103ab4361718b4dc51a1d149b88454424566e76293b
deleted: sha256:899090de47ef18ae38c91752ae5d3d91bcea683c0b7a1610d92a56a61f82e694
deleted: sha256:014bf9ec8a38021ca309be775d9bbd55be782417b03e79b53fda9e43dc1261d4
deleted: sha256:05e4bef6d74ab30ceda651deaf8cf5098493ae4b3637f80cc84d0d4d39e008a8
deleted: sha256:a2e778d0eb88ab6a02ff378eb3605d9bdf34fef5545427a22312bb0cb85729ef
deleted: sha256:f1c46cc442566e473088a0cd5ea74e6da8bcbe4456f041e461e721d7c2f29e8c
deleted: sha256:66e1bbe79ff4646f032b7aeaa8acda8bf28fbac489dc55a403cb2d025a56ee9a
deleted: sha256:96c1612de1b3dea0b223faafdbde1553e17697468b5951456d338105bf208de3
Total reclaimed space: 447.5MB
VSCode拡張機能
VSCodeの便利な拡張機能を紹介します。
Docker - Visual Studio Marketplace
これを入れると、ツールバーにDockerアイコンが表示され、コンテナの操作をGUIで行うことができます。(さっき紹介したゴミの削除もできます。)
Remote - Containers - Visual Studio Marketplace
これはまだプレビューですが、VSCodeからコンテナに直接アクセスできる革命的な拡張機能です。
エイリアス
毎回docker
を打つのがダルいという人はエイリアスを設定すると良いかと思います。
alias d="docker"
以上、Docker入門講座でした。お疲れさまでした。