この記事について
この記事は、
- 開発時に私個人がよく使うdockerコマンド
- 開発時に気になったdockerコマンドの細かい挙動
- コンテナを支えるネットワーク・ボリュームといった裏の仕組み
だけに絞って書き残したものです。
「よく使うコマンドだけ手っ取り早く知りたい」「コンテナという概念は知っている状態から、もっとdockerシステムについての理解を深めたい」という人には役立つかもしれません。
注:「コンテナについての一からの解説が欲しい」「dockerコマンドにはどういう機能があるのかを網羅的に知りたい」という方のニーズは満たせていません。
使用する環境・バージョン
- Mac OS Mojave 10.14.5
- Docker version 19.03.8
Containers
コンテナの新規作成・起動
docker run
は指定したイメージから新しくコンテナを作成・起動するコマンドです。
ただし、コンテナの元になるイメージ(Dockerfile
のFROM
命令で指定されたもの)がローカルにまだインストールされていない場合、DockerデーモンがそのコンテナイメージをDocker Hub(Docker社が運営するPaaS型のDocker Registry)から自動でダウンロードし、イメージからコンテナを起動します。
この挙動から、docker run
は「docker pull
→docker create
→docker start
」と同じ動作であると言えます。
参考:さわって理解するDocker入門 第1回 Dockerのイメージ・コンテナ管理の仕組み
コマンドオプションについては以下の通りです。
-
-p XXXX:YYYY
: localhost:XXXXをコンテナポートYYYYにリダイレクト -
-d
: デタッチモード(コンテナ内に入らずに、バックグラウンドで作動させる)での起動
$ docker run -p 80:3000 -d <起動したいイメージ名>
ここで注意したいのは、docker run
コマンドは「イメージからの新規作成」であるという点です。
そのため、docker run ImageA
というコマンドを二回叩くと、 ImageAを使用したコンテナが2つできることになります。
# 1回目のdocker run
$ docker run -p 80:8080 -d ImageA
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd1e156a0d6a ImageA "go run main.go" 39 seconds ago Up 38 seconds 0.0.0.0:80->8080/tcp cool_buck
$ docker stop dd1e156a0d6a
# 2回目のdocker run
$ docker run -p 80:8080 -d ImageA
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
55f3cccb4b33 ImageA "go run main.go" 3 seconds ago Up 2 seconds 0.0.0.0:80->8080/tcp jolly_pasteur
# さっきと違うコンテナIDのものが立ち上がってることが確認できる
$ docker stop 55f3cccb4b33
# 存在するコンテナ一覧の確認
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55f3cccb4b33 ImageA "go run main.go" 3 seconds ago Exited (2) 4 minutes ago jolly_pasteur
dd1e156a0d6a ImageA "go run main.go" 7 minutes ago Exited (2) 6 minutes ago cool_buck
# ImageAを元にしたコンテナが2つ立ち上がってることが確認できる
そのため、「既に存在するコンテナを起動させる」という場合は、次のdocker start
コマンドを使用する必要があります。
指定コンテナの起動
既に存在する停止中コンテナを起動したい場合は、docker start
を使います。
コンテナの指定は、コンテナIDかコンテナ名を使います。
$ docker start <container ID>
# または
$ docker start <container Name>
備考: コンテナIDやコンテナ名を知りたい場合は、後述するdocker ps
コマンドを使います。
コンテナの停止
ある特定のdockerコンテナを停止させるには、docker stop
を使います。
$ docker stop <container ID>
# または
$ docker stop <container Name>
備考: コンテナIDやコンテナ名を知りたい場合は、後述するdocker ps
コマンドを使います。
コンテナ一覧の確認
docker ps
コマンドで、現在稼働中のコンテナ一覧が確認できます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55f3cccb4b33 ImageA "go run main.go" 3 seconds ago Up 2 seconds 0.0.0.0:80->8080/tcp jolly_pasteur
停止中のコンテナまで含めた全てのコンテナを確認したい場合は、オプション-a
をつけます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55f3cccb4b33 ImageA "go run main.go" 3 seconds ago Up 2 seconds 0.0.0.0:80->8080/tcp jolly_pasteur
dd1e156a0d6a ImageA "go run main.go" 7 minutes ago Exited (2) 6 minutes ago cool_buck
これら2つのコマンドで、以下のことが確認できる。
- CONTAINER ID : コンテナID
- IMAGE : そのコンテナの元となったイメージ
- COMMAND : コンテナ起動時にコンテナ中で実行されたコマンド(
Dockerfile
のCMD
命令にあたる) - CREATED : 作成日時
- STATUS : 起動中か、起動中でないなら停止した日時
- PORTS : ホストポートとコンテナポートの接続状態
- NAMES : コンテナ名
削除
docker rm
コマンドで、指定されたIDのコンテナを削除できます。
コンテナを削除しても、そのコンテナの元となったイメージが残ることに注意してください。
$ docker rm <docker ID>
<docker ID>
# または
$ docker rm <docker Name>
<docker Name>
削除対象コンテナを複数指定すると、それらの一括削除が可能です。
$ docker rm <docker ID 1> <docker ID 2>
<docker ID 1>
<docker ID 2>
起動していないコンテナを一括削除したい場合は、docker container prune
で可能です。
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
# 以下削除処理
参考:dockerでいらないimage,container,networkを一括削除する
参考:Dockerのあれこれを断捨離する
ログの出力
dockerアプリで出たログを出力して見るには、docker logs
コマンドを使います。
これはコンテナ停止中でもログ取得が可能です。
$ docker logs <container ID>
# または
$ docker logs <container Name>
docker内部に入る
docker内に実際に入ってコマンドを実行したいという場合は、以下のコマンドを実行します。
$ docker exec -it <container Name> /bin/bash
# 以下、コンテナ内部
root@<container ID>:/#
このように、このコマンドを使うと、ルートユーザーとしてログインすることになります。
コンテナ情報の確認
コンテナ情報一覧の取得
指定コンテナに関する全ての情報を取得するには、docker inspect
コマンドを利用します。
$ docker inspect <container ID>
しかし、如何せんこれでは全ての情報が一気に出力されるので、そこから自分の知りたい情報だけを探すのが大変です。そのため、知りたい情報だけをピンポイント出力するオプションをつけるのが一般的です。
コンテナに割り振られたIPアドレスの取得
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container ID>
172.18.0.6
コンテナに割り振られたMACアドレスの取得
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' <container ID>
02:42:ac:12:00:06
コンテナ内で設定された環境変数の取得
$ docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' <container ID>
MYSQL_ROOT_USER=root
MYSQL_ROOT_PASSWORD=pass
MYSQL_DATABASE=sampledb
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
GOSU_VERSION=1.12
MYSQL_MAJOR=5.7
MYSQL_VERSION=5.7.30-1debian10
参考:Docker-docs-ja公式ドキュメント inspect
参考:[Docker]docker inspcetコマンドでコンテナの情報を確認する
docker-compose
docker-compose.yml
に記述した設定を元にコンテナ群を起動したい場合は、以下のdocker-compose
コマンドを使います。
コンテナ群の起動
以下のコマンドで、カレントディレクトリにあるdocker-compose.yml
に沿ったコンテナ群が起動できます。
$ docker-compose up
Starting app_service1 ... done
Starting app_service2 ... done
# 以下コンテナログが流れる
オプションをつけない状態では、デオフォルトでフォアグラウンドモードで起動され、以降ターミナルにコンテナログが流れてきます。
バックグラウンドで起動したい場合は、オプション-d
をつければOKです。
$ docker-compose up -d
Starting app_service1 ... done
Starting app_service2 ... done
$
# バックグランド起動だと同ターミナルで引き続きコマンドラインの使用が可能
また初回起動時には、これらのコンテナ群を繋ぐユーザ定義・ブリッジ・ネットワーク(app_default)も自動で作成されます。
(ネットワークについての詳細は後述)
コンテナ群の停止
フォアグラウンドモードでの起動だった場合は、ターミナルでCtrl+C
を押すだけです。
バックグラウンドモードの場合は、docker-compose stop
コマンドを使います。
$ docker-compose stop
Stopping app_service1 ... done
Stopping app_service2 ... done
$
イメージの再ビルド
コンテナアプリのソースコードを変えた場合は、もう一度コンテナをビルドしないと、現存するコンテナにソース変更が反映されません。
そのため、ソースコードの変更をコンテナに反映させるためには、docker-compose build
コマンドを使って再ビルドしてから起動という手順をたどる必要があります。
$ docker-compose build
# 以下ビルド処理の様子がログで流れる
$ docker-compose up
特定の一個のサービスだけbuildしたいなら、docker-compose build <サービス名>
でサービスを指定すればOKです(サービス名はdocker-compose.ymlに記述したものです)。
削除
docker-compose.yml
から作成したコンテナ群+ネットワークの削除は以下のコマンドで可能です。
$ docker-compose down
Removing app_service1 ... done
Removing app_service2 ... done
Removing network app_default
ただし、使用されていたイメージやボリュームは削除されないので、それも消したい場合は別途作業が必要です。
Images
既存のDockerfileからイメージを作成する
docker build
はDockerfileからimageを作成するコマンドです。
Dockerfileがあるディレクトリで実行すれば、-t
オプションでつけたタグ名のイメージが作成されます。
# 最後の.はカレントディレクトリを意味するドットなので必要
$ docker build -t ImageA .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ImageA latest 6c97772719d3 17 seconds ago 919MB
(以下略)
一覧の確認
docker images
で、現在存在するイメージを確認できます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ImageA latest 6c97772719d3 17 seconds ago 919MB
このコマンドで確認できる項目は以下の通り。
- REPOSITORY : イメージ名
- TAG : タグ名
- IMAGE ID : イメージのID
- CREATED : 作成日時
- SIZE : メモリ容量
repository・tagの追加
今あるイメージにリポジトリ・タグ名を新しく追加するためには以下のコマンドを使います。
(作った後も、<現repository>:<現tag>は残ります)
$ docker tag <現repository>:<現tag> <新repository>:<新tag>
レジストリにpush
dockerレジストリにログインしている状態で以下のコマンドを実行することで、レジストリへのdockerイメージ登録ができます。
$ docker push <pushしたいイメージのrepository>:<pushしたいイメージのtag>
レジストリへのログイン方法は後述。
削除
docker rmi
コマンドで、指定されたIDのイメージを削除できます。
$ docker rmi <image ID>
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b
Deleted: sha256:9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63
現在存在しているコンテナに使われていないイメージを一括削除したい場合は、docker image prune
コマンドを使います。
$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
# 以下削除処理
Registries
Dockerレジストリとは、dockerイメージの公開・保存・配布を行うサービスのことです。
(例)Docker Hub, ECRなど
リポジトリにログイン
$ docker login --username <your-user-name> --password <your-password> <loginURL>
リポジトリからログアウト
$ docker logout <loginURL>
Networks
dockerのネットワーク概要
コンテナを単独で起動している分では、dockerのネットワークの仕組みがどうなっているのかはあまり意識しないことが多いでしょう。
ここでは、コマンドを紹介する前に、そもそもdockerネットワークがどういうものなのかを確認します。
まず、dockerインストール時にすでに存在するデフォルトネットワークについて説明します。
上図引用:Docker Compose入門 (3) ~ネットワークの理解を深める~
none
このネットワークを使うように指定されたコンテナには、外部のネットワークに繋ぐインターフェースが一切設置されません。
もちろんコンテナホストのPCと繋がるインターフェースも設置されないので、用途としてはネットワーク接続を必要としない開発環境を用意するときでしょう。
host
この設定では、コンテナとホストがネットワークインターフェースを共有するものです。なので、コンテナのeth0とホストのeth0がそのまま繋がります。
これを利用すると、コンテナがホストマシンと同じIPアドレスを持つようになります。
bridge
この設定では、ホストの任意のポートをコンテナのポートにマップすることで、コンテナ外部のネットワークに接続します。
例えば、先ほど紹介したdocker run -p 80:3000
というコマンドは、bridgeで「コンテナの3000番ポートをホストの80番ポートに繋ぐ」という設定をしていることになります。
コンテナーホスト間のポートマッピングは、ホストマシンのLinuxカーネル内部に作られるイーサネット・ブリッジによって行われています(この仮想ブリッジにはdocker0という名前がついています)。
上図引用:第29回 Docker Networkingの基礎知識 標準的なネットワークを理解する (4/5)
コンテナ内部とdocker0仮想ブリッジは、veth(Virtual Ethernet Tunnel)によって接続されています。vethペアのうち、コンテナ側のインターフェースは、コンテナ内ではeth0として振る舞います。残ったホスト側の方は、docker0ブリッジにつながるインターフェースとなります。
docker0ブリッジには、ホストマシンのeth0にも繋がっています。
そのため、コンテナから外部への通信は、docker0ブリッジを経由し、そこでブリッジが提供するNAT機能を用いることで行うことになります。
ただし、このbridgeネットワークには名前解決機能がありません。
例えば、bridgeネットワークに同時にcontainer1
とcontainer2
というコンテナ2つが接続されているときに、container1
からcontainer2
に向けて通信するためには、宛先にcontainer2
という名前を使うことができず、container2
コンテナに付与されたプライベートIPアドレスをわざわざ調べてそれを使う必要があるということです。
コンテナに付与されるプライベートIPは、起動ごとにdockerが空いているIPを割り振るため不定です。そのため、コンテナ間通信に生のIPアドレスとそのまま使うのは避けるべきです。
そのため、同時に起動している他のコンテナと通信したいという場合は、次に挙げるdocker-conposeを利用したネットワークを利用します。
参考:Docker-docs-ja公式ドキュメント Docker0 ブリッジのカスタマイズ
参考:Dockerのネットワークの仕組み
参考:Docker の基本学習 ~ Docker のネットワーク
参考:Docker network 概論
docker-composeで作成されるネットワーク
上図引用:Docker Compose入門 (3) ~ネットワークの理解を深める~
docker-compose.yml
からコンテナを起動させた場合には、このようなユーザ定義・ブリッジ・ネットワークがデフォルトで作成されます。
仕組みとしては、上で挙げたbridgeネットワークと同じです。違いとしては、これにはDNS設定がされるので、bridgeネットワークでは不可能だったコンテナ間名での名前解決ができます。
参考:Docker入門(第五回)〜コンテナ間通信〜
一覧確認
docker network ls
コマンドで現在存在するネットワーク設定一覧を確認できます。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
af74802186be bridge bridge local
a26bb8a73819 app_default bridge local
c987a5c599df host host local
551c3f676ee0 none null local
デフォルトネットワーク3つと、docker-compose.yml
からできたユーザ定義・ブリッジ・ネットワークが1つ確認できました。
このコマンドで、以下のことがわかります。
- NETWORK ID: ネットワークID
- NAME: ネットワークの名前
- DRIVER: 元となったドライバ
- SCOPE: ネットワークのスコープ
ネットワークの状態の確認
コンテナと同様に、inspect
コマンドでネットワークの詳細設定を確認することができます。
$ docker network inspect <network Name>
削除
特定のネットワークを削除は、docker network rm <name>
で可能です。
$ docker network rm <network Name>
Volumes
一覧確認
docker volume ls
でボリューム一覧が観れる。
$ docker volume ls
DRIVER VOLUME NAME
local app_db-volume
local app_redis-volume
ボリュームの状態の確認
コンテナ・ネットワークと同様に、inspect
コマンドで詳細設定を確認することができます。
$ docker volume inspect <volume name>
[
{
"CreatedAt": "2020-06-20T16:44:05Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "app",
"com.docker.compose.version": "1.23.2",
"com.docker.compose.volume": "db-volume"
},
"Mountpoint": "/var/lib/docker/volumes/app_db-volume/_data",
"Name": "app_db-volume",
"Options": null,
"Scope": "local"
}
]
削除
特定のボリュームを削除するためには、docker volume rm <name>
で可能。
$ docker volume rm <volume Name>
どこのコンテナにもアタッチされていないボリュームを一括削除するには、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
# 以下削除処理