目的
dockerをなんとなく使っていた状態から、その仕組みやお作法をきちんと理解した上で使えるよになりたいと思い記事にしてみました。これまでdockerコマンドやDockerfileについてよくわからないまま使っていました。ちゃんとdockerコマンドやDockerHubについて理解するとともに、Dockerfileやdocker-compose.yml を学んでいくのがよさそうかなと思ってます。
Dockerとは
軽量なコンテナ型アプリケーション実行環境
Dockerの特徴
- Docker社が開発
- コンテナ型仮想環境(Dockerエンジン+APP)軽量、高速起動停止
- 仮想マシンと対比される(Hypervisor+ゲストOS+APP)
(仮想化ソフトウェアの代表的なものにVM WareやVirtual Boxがある) - 誰でも同じ環境が素早く作れる(バージョン違いなどの差異が生まれない)
- 基本的にはLinux環境で動いており、ホストOSのカーネルを共有している(カーネルは常に1つ)
- 隔離された実行環境(コンテナ)にすぎない
- 作成した環境を配布できる
- コンテナを破棄して作り直すことが容易である
Dockerイメージ
- オブジェクト指向に例えるとクラスに相当
- Dockerイメージを格納しておくことのできるDockerリポジトリの仕組みがある(Docker Hub)
例「Apacheがインストールされたイメージ」「MySQLがインストールされたイメージ」 - Docker HubはDockerリポジトリであり、プライベートに使うことも、パブリックで公開して使うこともできる。
- 有志の人が便利だと考えて作られたイメージが多種多様既に登録されている
- Dockerファイルを使ってビルドできる($docker build -t ImegeName .)
- 自分で作成したコンテナをDockerイメージとして出力することやDockerHubに登録することもできる。
Dockerイメージの実体
- Dockerコンテナの実行に必要なファイルやメタ情報の集合体
- 抽象的なレイヤの積み重ね(レイヤには親子関係がある)
- 複数のイメージレイヤーが集まって1つのイメージが出来上がっている。
(利用者からは1つのイメージにしか見えない)
Docker Hub
Docker Hub は、Docker社が管理公開しているレジストリ、つまり入れ物である。
そこには、コンテナを構築するためのイメージが置かれている。
gitで言うところのGit Hub に相当する。Git Hubにはソースコードを入れることが多いが、docker Hubにはイメージを入れておき共有することができる。
誰でもアカウントを作成してログインしたら使うことができる。
Docker コマンド(イメージの取得)
dockerコマンドの種類やオプションは多数存在し、必要に応じて調べて覚えていくのがよい。 ここでは、Linuxディストリビューションの中の1つでもあるubuntsイメージを例にDockerHubから取得してコンテナ起動までの流れで記載する。
- $docker search ubuntu
DockerHub上でubuntuイメージを検索する。
ubuntuにも多くの種類のイメージが公開されており、その中から欲しいものを選んで取得する
- $docker image pull ubuntu
DocckerHubからubuntuのイメージを取得する。
(tagを指定しなければデフォルトで:latestタグが使用され最新版を取得する)
- $docker images
ローカルに保存されているDockerイメージの一覧を表示する -a オプションをつけて実行すると、イメージを構成する各レイヤーのイメージも細かく一覧で表示されるようである。
Docker コマンド(コンテナの作成と実行)
- $docker run ubuntu
- $docker run -it centos
イメージからコンテナを生成して起動までを行う。
オプションが何も指定されていない場合はコンテナ起動後すぐに終了する。
(-itオプションは後述)
--name [コンテナ名] も追加してコンテナ名を指定することもできるが、
もし指定しなければdockerによって勝手に名前がつけられるようである。
コンテナ名を変更したければ
- $docker rename [現在コンテナ名] [新コンテナ名]
で変更することができた。
ローカルにイメージが存在しなければdockerがDockerHubからpullして
自動でダウンロードしてくれる。
たとえばhttpdイメージをrunコマンドで指定すると
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
このようにpullしていることが確認できる。
pullとcreateとstartを通して実行してくれるようなのでrunを使えば
爆速でコンテナを使えるようにできるというわけである。
注意としては、docker run の実行のたびにコンテナが新規作成されるということである。実行の度にコンテナが増え続けるので作りすぎに注意が必要である。
- $docker run -it ubuntu
-iと-tのオプションをあわせて-itと指定できるが、これを指定することで
起動したコンテナにログインすることができる。
但し、exitをしてしまうとログアウトすると同時にコンテナも終了してしまう。
この場合、Ctrl+PのあとQを押すと、コンテナを起動したままの状態でログアウトできる。これをデタッチといいバックグラウンドで動作している状態である。
$docker ps -a
で確認してみると、STATUSが Up となっておりExitedされてないことが確認できる。
- $docker attach [コンテナID]
デタッチしたコンテナのIDを指定して上記を実行すると、再びコンテナに接続することができる。
コンテナに接続している状態で
#exit を実行して
$docker ps -a で確認してみると、STATUS がExitedとなっており、ログアウトと同時にコンテナが終了したことを確認できる。
$docker run -it ubuntu /bin/bash
シェルを指定することもできる。
phpが動くコンテナを作成しechoしてみる
$docker run php php -r 'echo 11*22;'
242
Docker コマンド(コンテナの起動・停止)
コンテナを作成する別な方法として
- $docker create -it --name konta ubuntu
これによりイメージからコンテナを作成するところまでができる。
$docker ps -a
で確認するとSTATUSがCreatedになっていて起動まではされてないことがわかる。
次のstartコマンドを実行してもすぐにExitしてしまわないように、
createの時に-itを指定しておく。
- $docker start konta
生成されているコンテナを起動する。
なにもオプション指定がされてない場合には、$docker run -d と同様バックグラウンドで実行される
-a オプションを付けると-dオプション無しと同じ動作になり、コマンドプロンプト#が表示されるが、tty接続されていないため何もコマンドは入力できない。(Ctrl+Cで終了するしかない)
- $docker stop konta
起動しているコンテナを停止する。
$docker ps -a
でSTATUSを確認するとExitになっていることが確認できる。
Docker コマンド(コンテナに接続)
- $docker exec -it konta /bin/bash
- $docker exec konta /bin/ls -la
起動中のコンテナに接続して、コンテナ内でコマンドを実行できるようになる。
上記の場合はbashを起動しているのでbash上でコマンドを実行できる。
後者は、コンテナ内でls -la を実行したのち、すぐにコンテナを終了する。
Docker オプション(-i、-t)
- -i は --interactiveと同じであり、コンテナの標準入力をDockerホストの標準入力と接続する。
- -t は --ttyと同じであり、コンテナ内で疑似的な仮想端末を割り当て、Dockerホストの標準出力と接続する。
※上記はあるサイトからの引用
要するに、
-i はコンテナ側からの出力をコンテナの外側へ出せるようにするものであり
-t は外側からの入力をコンテナ内部へと入力できるようにさせるようなものと考えた。
なので、コンテナに接続してコンテナ上でコマンド操作するといったように、
対話型コマンドを実現させたい場合には、両方をまとめて -it を指定する。
Docker コマンド(run と execの相違)
docker run コマンドは、コンテナを生成し、かつ、起動までも行うようである。
(createとstartを一発で実行するようなものである)
docker exec コマンドは、既に起動中であるコンテナに接続してコンテナ内でコマンドを実行させたい場合に使う。 なのでexecの場合には、コンテナが起動されている必要がある。
Docker コマンド(cp)
コンテナ内にファイルをコピーする。
コンテナは起動中でも停止中でもコピーできるようである。
- $docker run -d -p 8080:80 httpd
httpdイメージを使ってコンテナをバックグラウンドで起動しておく。
-pオプションは外部ポートとコンテナ内部のポートを接続するオプションである。
外部から8080ポートでアクセスすると、コンテナ内の80ポートに接続できるというものである。
任意のファイル (TESTと記載された)test.htmlを用意しておく。
$docker ps でhttpdコンテナが起動中であることを確認し、
$docker exec -it httpd /bin/bash でDocumentRootが
/usr/local/apache2/htdocs
であることを確認しておく。
$docker cp test.html httpd:/usr/local/apache2/htdocs
コピー先は[コンテナ名]:[格納ディレクトリのパス]で指定する。
ブラウザで
http://localhost:8080/test.html
を表示させると TEST という文字が表示されるこたことが確認できた。
cpだけでもまだまだ奥が深いので、別の機会に試してみようと思う。
Docker コマンド(rename)
コンテナを作成する際、--name でコンテナ名を指定しないと、自動的に名前が付けられるようである。
それをあとから変更するためには、rename コマンドを使う。
- $docker rename elegant_dhawan httpd
変な名前elegant_dhawanが付けられてしまったが、あとからhttpdに変更した場合のコマンドである
Docker コマンド(build)
これは、Dockerfileを使ってDockerイメージを生成するためのコマンドである。
ちょうどmakeコマンドのMakefileに相当するようなものだ。
Dockerfileについては別の記事に記載する。
Docker コマンド(commit)
既存のコンテナに対して、いろいろと手を加えて(コンテナ内にファイルを入れたりアプリを入れたりして)自分独自のコンテナへと更新させることができる。
しかし、そのコンテナを削除してしまうと、せっかく作ったオリジナルなコンテナを再度作り直さなければならない。
そこで、自分で作ったコンテナをイメージとして保存しておくことができる。
(そのイメージをDockerHubにアップロードすることも可能だ)
- $docker commit httpd kontaimg
これは、httpdという名前のコンテナをkontaimgという名前のイメージとして保存するという意味だ。
$docker images
で確認するとイメージが出来上がっていることが確認できる。
これにより、kontaimgイメージさえあれば、コンテナを作り直すこともできるし複製もできる。
Docker コマンド(diff)
コンテナ内で変更があった情報の一覧を出力してくれるようだ。
- $docker diff httpd
例えば、初期のコンテナの状態から
$docker cp test.html httpd:/usr/local/apache2/htdocs
このようにファイルをコンテナ内にコピーしたのち、diffを実行してみたら、
C /usr
C /usr/local
C /usr/local/apache2
C /usr/local/apache2/htdocs
A /usr/local/apache2/htdocs/test.html
このように表示される。
CはChange(変更)
AはAdd(追加)
を意味するのだと思う。(Dは削除かな)
A /usr/local/apache2/htdocs/test.html
上記の通り追加されていることが確認できた。
Docker コマンド(info)
Dockerクライアントとサーバーの細かな情報が表示される。
- $docker info
サーバーにおいては、稼働中コンテナ数、停止中コンテナ数、イメージ数など。
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)
scan: Docker Scan (Docker Inc., v0.5.0)
Server:
Containers: 11
Running: 1
Paused: 0
Stopped: 10
Images: 31
Server Version: 20.10.2
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 269548fa27e0089a8b8278fc4fc781d7f65a939b
runc version: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 4.19.128-microsoft-standard
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 12.45GiB
Name: docker-desktop
ID: A3AZ:FLYN:SXFK:7KIM:QMDV:JVMX:HCX5:FLDS:QRND:TYTF:ZQWK:KGQA
Docker Root Dir: /var/lib/docker
Debug Mode: true
File Descriptors: 46
Goroutines: 48
System Time: 2021-01-21T01:37:27.1105279Z
EventsListeners: 2
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Docker コマンド(inspect)
実行してみるとコンテナの細かい情報が表示された。
- $docker inspect httpd
たとえば、コンテナのステータスとか、コンテナ内で設定された環境変数だとか。。
[
{
"Id": "d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53",
"Created": "2021-01-20T11:00:57.1970936Z",
"Path": "httpd-foreground",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 891,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-01-21T01:37:22.5737225Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:683a7aad17d3baed344799b397c55a9ccbc3ddabf0d077862739585ee76d4cb3",
"ResolvConfPath": "/var/lib/docker/containers/d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53/hostname",
"HostsPath": "/var/lib/docker/containers/d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53/hosts",
"LogPath": "/var/lib/docker/containers/d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53/d31a31a707ae8738daae7e3bc6578ea9b52e516aeba2d5d37a9000a6d5768c53-json.log",
"Name": "/httpd",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
]
},
(長いので中略)
"Config": {
"Hostname": "d31a31a707ae",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.46",
"HTTPD_SHA256=740eddf6e1c641992b22359cabc66e6325868c3c5e2e3f98faf349b61ecf41ea",
"HTTPD_PATCHES="
],
"Cmd": [
"httpd-foreground"
],
"Image": "httpd",
"Volumes": null,
"WorkingDir": "/usr/local/apache2",
"Entrypoint": null,
"OnBuild": null,
"Labels": {},
"StopSignal": "SIGWINCH"
},
}
]
Docker コマンド(events)
Docker内部で発生したいろいろなイベントが表示できるようだ。
- $docker events
これを実行した状態で、あるコンテナを削除すると
2021-01-22T11:03:17.486167200+09:00 container destroy 899561fad6098c31e262627a10924d2c73d3a08317a4a4c2f51ed7d29a5d34d0 (image=hoge, name=mystifying_brahmagupta)
このようなメッセージが表示された。
その他にもpullやrunを実行したタイミングなど、イベントが生じた場合には
情報をリアルタイムで表示してくれるようである。
Docker コマンド(history)
Dockerイメージのレイヤー情報を表示してくれる。
- $docker history ubuntu
これを実行すると、下記のような表示がされた。
IMAGE CREATED CREATED BY SIZE COMMENT
f643c72bc252 8 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 8 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 8 weeks ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 8 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 811B
<missing> 8 weeks ago /bin/sh -c #(nop) ADD file:4f15c4475fbafb3fe… 72.9MB
6層から出来ているイメージであることが確認できる。上の方が新しい層のようであり、自分で層を追加したら、上に追加されることが確認できる。
以下のDockerfileでビルドしてみる。
FROM ubuntu
RUN echo "hello konta" > /tmp/konta.txt
$docker build --rm -t test .
Sending build context to Docker daemon 6.144kB
Step 1/2 : FROM ubuntu
---> f643c72bc252
Step 2/2 : RUN echo "hello konta" > /tmp/konta.txt
---> Running in a01822b4152e
Removing intermediate container a01822b4152e
---> c00d6ffcc62a
Successfully built c00d6ffcc62a
Successfully tagged test:latest
$docker history test
IMAGE CREATED CREATED BY SIZE COMMENT
c00d6ffcc62a 16 seconds ago /bin/sh -c echo "hello konta" > /tmp/konta.t… 13B
f643c72bc252 8 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 8 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 8 weeks ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 8 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 811B
<missing> 8 weeks ago /bin/sh -c #(nop) ADD file:4f15c4475fbafb3fe… 72.9MB
上記の通り、一番上に自分が追加した層が追加されていることが確認できる。
となってIMAGEIDが表示されないのはDockerの仕様のようである。
Docker コマンド(コンテナの削除とイメージの削除)
- $docker rm [コンテナID]
これでコンテナを削除できる。
$docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2482e87ac13d httpd "httpd-foreground" 5 days ago Exited (0) 5 days ago elegant_dhawan
d31a31a707ae httpd "httpd-foreground" 5 days ago Exited (137) 4 days ago httpd
07bed7ba48fe jwilder/nginx-proxy "/app/docker-entrypo…" 6 days ago Exited (2) 6 days ago rccpf_proxy_1
上記コンテナ一覧から
2482e87ac13dこのコンテナを削除してみる。
$docker rm 2482e87ac13d
2482e87ac13d
$docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d31a31a707ae httpd "httpd-foreground" 5 days ago Exited (137) 4 days ago httpd
07bed7ba48fe jwilder/nginx-proxy "/app/docker-entrypo…" 6 days ago Exited (2) 6 days ago rccpf_proxy_1
削除されたことが確認できた。
起動中のコンテナは削除できないが、-f オプションを付けると起動中でも強制的に削除されることについても確認できた。
- $docker rmi [イメージID]
これでイメージを削除できる。
$docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
envtest latest 804910d40577 4 days ago 72.9MB
labeltest latest e26e53a9bcc3 4 days ago 72.9MB
test latest c00d6ffcc62a 4 days ago 72.9MB
centoshttpd latest a559de6ce936 4 days ago 250MB
hoge latest f8e58afd17c2 4 days ago 220MB
hello latest cf6b541b21fc 5 days ago 5.61MB
上記コンテナ一覧から
804910d40577このイメージを削除してみる。
$docker rmi 804910d40577
Untagged: envtest:latest
Deleted: sha256:804910d4057780e1175623baf7532ff290d574852bfe53b945f55d7a09bafc83
$docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
labeltest latest e26e53a9bcc3 4 days ago 72.9MB
test latest c00d6ffcc62a 4 days ago 72.9MB
centoshttpd latest a559de6ce936 4 days ago 250MB
hoge latest f8e58afd17c2 5 days ago 220MB
hello latest cf6b541b21fc 5 days ago 5.61MB
削除されたことが確認できた。
-rmオプション指定 (おまけ)
何度もrunを繰り返すと docker ps -a で確認できる停止中のコンテナが量産されてしまう。これを都度 docker rm で消去するのは手間である。これを回避するために、停止した段階でrmも一緒にやってくれるのがこのオプションです。