【随時更新中】Docker・Docker Composeでよく使用するコマンドとオプションの一覧と考え方・使い方まとめ

Docker_CLI

こんにちはフロントエンドエンジニアのまさにょんです!

今回は、Docker・Docker Composeでよく使用するコマンドとオプションについて考え方と使い方をまとめていきます。

わかりやすさ重視で、すべてDockerの新型CLIの書き方で、統一してまとめているので、その点は注意してください。

新型CLI何それって方は、ぜひこちらを見てみてください。

また、今回の記事は、実践 Docker – ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本 にて、

Dockerを学習(引用・参照)しながら、まとめた記事になります。

目次

Docker Image系のコマンド・オプション

所持しているイメージを一覧表示する

docker image ls

イメージを削除する(Containerが存在していない状態)

docker image rm < IMAGE ID  >

# または、、、

docker image rm < REPOSITORY:TAG >

イメージを強制的に削除する(Containerも同時に削除する)

Containerが存在する状態で、イメージを削除しようとすると次のエラーが発生します。

Error response from daemon: conflict: unable to remove repository reference.

(翻訳: デーモンからのエラー応答: 競合: リポジトリ参照を削除できません)

上記のエラー対応としては、docker container rm コマンドでコンテナを削除してから、docker image rm を実行するか、

または、次のように-f オプションを付与して、イメージを強制的に削除する方法があります。

-f オプションを使用してのイメージ削除は、イメージに紐づいているContainerも同時に削除します。

docker image rm -f < REPOSITORY >

Docker Container系のコマンド・オプション

起動中のコンテナだけを一覧表示する

docker container ps

# または、、、

docker container ls

停止中も含めて、すべてのコンテナを一覧表示する

docker container ls でも同じオプションを使用することができます。

docker container ps --all

# または、、、

docker container ps -a

イメージを使用して、コンテナを作成・起動する

docker container runコマンドではIMAGE ID またはREPOSITORY:TAG を指定して、コンテナを新しく作成&起動することができます。

docker container run < IMAGE ID >

# または、、、

docker container run < REPOSITORY:TAG >

バックグラウンドで、コンテナを作成・起動する

-d または、--detach を使用することで、バックグラウンドでコンテナを新しく作成・起動することができます。

docker container run -d < IMAGE ID > 

# または、、、

docker container run -d < REPOSITORY:TAG >

コンテナに名前を付与して、コンテナ内部のターミナルに接続する

docker container run --name app --rm -it docker-practice:app bash

停止中のコンテナを削除する

docker container rm < CONTAINER ID >

# または、、、

docker container rm < NAMES >

起動中のコンテナでも強制的に削除する

docker container rm -f < CONTAINER ID >

# または、、、

docker container rm -f < NAMES >

ボリュームを作成する

コンテナのファイルを保持するには?

コンテナ内で作成されたファイルはコンテナの削除とともに全て廃棄されます

そうなると ログやデータを次起動するコンテナに引き継げない ので開発に不自由してしまいます。

そこで、Docker にはホストマシンとコンテナでファイルを共有する方法がいくつか用意されています。

1つの方法であるボリュームを使い、DB コンテナのデータベースのデータが消失しないようにします。

ボリュームとは?

ボリュームはコンテナ内のファイルをホストマシン上で Docker が管理してくれる仕組み です。

ホストマシン側のどこに保存されているかは関心がなくとにかくデータを永続化したい という場合に有用で、

たとえばデータベースのデータの永続化に活用できます。

コンテナの特定のディレクトリをボリュームとしてホストマシン側で管理すれば、

コンテナが削除されてもデータが消失しなくなります。

ボリュームの作成

docker volume create [option]

# db-volume という名前で、ボリュームを作成する
docker volume create --name db-volume
オプション意味用途
--nameボリューム名を指定ID ではなく名前で扱えるようにする

ボリュームの確認

ボリューム一覧を確認するには、 volume ls を使います。

docker volume ls

# [ 実行結果 ]  
DRIVER    VOLUME NAME
local     db-volume

DB コンテナにボリュームをマウントする

作成したボリュームは、コンテナ起動時にマウントして使います。

container run には --volume オプションと --mount オプションというほぼ同じことができるオプションがあります。

–volume オプションによるマウント

docker container run                                  \
    --name db                                         \
    --rm                                              \
    --detach                                          \
    --platform linux/amd64                            \
    --env MYSQL_ROOT_PASSWORD=rootpassword            \
    --env MYSQL_USER=hoge                             \
    --env MYSQL_PASSWORD=password                     \
    --env MYSQL_DATABASE=event                        \
    --volume docker-practice-db-volume:/var/lib/mysql \

–mount オプションによるマウント

--mount オプションは key=val 形式で設定を列挙 して指定します。

主なキーは type と source と destination で、ほかに readonly のような任意オプションのキーもあります。

また、source は src など、destination は dst や target などの略記も存在します。

ボリュームをマウントするには type に volume を指定します。

source はボリューム名の docker-practice-db-volume を指定します。

destination は /var/lib/mysql を指定します。

docker container run                                                     \
    --name db                                                            \
    --rm                                                                 \
    --detach                                                             \
    --platform linux/amd64                                               \
    --env MYSQL_ROOT_PASSWORD=rootpassword                               \
    --env MYSQL_USER=hoge                                                \
    --env MYSQL_PASSWORD=password                                        \
    --env MYSQL_DATABASE=event                                           \
    --mount type=volume,src=docker-practice-db-volume,dst=/var/lib/mysql \
    docker-practice:db

ボリュームの詳細を確認する

docker volume inspect docker-practice-db-volume
[
    {
        "CreatedAt": "2023-04-02T22:28:02Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/docker-practice-db-volume/_data",
        "Name": "docker-practice-db-volume",
        "Options": {},
        "Scope": "local"
    }
]

バインドマウントとは

バインドマウントは、ホストマシンの任意のディレクトリをコンテナにマウントする 仕組みです。

ホストマシンとコンテナ双方がファイルの変更に関心がある という場合に有用で、たとえばソースコードの共有などに活用できます。

ソースコードのディレクトリをコンテナにバインドマウントしてホストマシン側と共有すれば、

ホストマシンでコードを変更した際に同期や転送が不要 になります。

バインドマウントはボリュームと違い 既存のディレクトリをそのままマウントする ので、事前作成などはありません。

バインドマウントも --volume オプションと --mount オプションどちらでも行えます。

バインドマウントの実体と注意

バインドマウントの実体は そのままホストマシンのファイルシステム です。

つまりバインドマウントはボリュームと比べると 実体の面倒を見ているのが Docker ではなく自分 であり、それが ホストマシン上 であるという違いがあります。

「仮想環境だから」と安易に rm -rf * でもして、もしそこにバインドマウントしたディレクトリが含まれていたら、削除はホストマシンに波及します

Docker の公式も まずはボリュームを検討し、どうしてもだめならバインドマウントを使え と言っています。

COPY とバインドマウントの使い分け

COPY とバインドマウントはどちらもホストマシンのファイルをコンテナで扱えるようにする機能ですが、

用途 と 反映タイミング を理解しておかないと扱いを間違えやすいので整理しましょう。

COPY は image build をするタイミングでイメージにファイルを含める ため、コンテナが起動すればファイルが存在 します。

また 元ファイルの変更を行ってもコンテナには反映されない ため、image build の再実行が必要 になります。

COPY の用途には次のようなものが挙げられるでしょう。

  1. 設定ファイルなど、コンテナによって変えない かつ 滅多に変更しない ものを配置する場合
  2. 本番デプロイ時のソースコードなど、即起動できる配布物を作る 場合

対してバインドマウントは イメージではなくコンテナに行う ため、

同じイメージを使ってもファイルの存在はコンテナ起動のオプションによって異なります。

また ホストマシンでファイルを変更するとコンテナに即時影響します

バインドマウントの用途には次のようなものが挙げられるでしょう。

  1. 開発時のソースコードなど、ホストマシンで変更したいがコンテナに随時反映したい ものがある場合
  2. 初期化クエリなど、イメージを配布する時点では用意できない ものがある場合

2つは イメージに対して行っている か コンテナに対して行っている かが明確に違います。

その点をちゃんと理解しておけば、使い分け も 変更したいならどうすべきか も判断できます。

バインドマウントの要点

  1. バインドマウントは ホストマシンでもファイルに関心がある という用途に向いている
  2. コンテナ内でのファイル削除などが ホストマシンに影響する 可能性がある
  3. イメージに対して行うCOPY とは コンテナに対して行う 点が大きく違う

ポートの公開

コンテナにホストマシンからアクセスするために、ポートの公開について学びます。

ポートの公開とは?

コンテナはホストマシンから隔離されており、コンテナ内で Web サーバや DB サーバを起動してもそのままではホストマシンからアクセスすることはできません。

Web サーバなどいわゆるパブリックネットワークに置くようなコンテナでは、

その問題を解決するために ホストマシンに対して ポートの公開を行うことになります。

ポートを公開して、コンテナを起動するオプション – container run

公開ポートは --publish host-machine:container の形式でマッピングします。

オプション意味用途
-p, --publishコンテナのポートを
ホストマシンに公開する
ホストマシンからコンテナ内の
サーバにアクセスする

このとき host-machine 側のポートは起動する人が自由に決めます が、

1024 未満のポートは特権ポートと呼ばれるあらかじめ用途が決められているポートなるので避けておくのが無難です。

コンテナの 8000 ポートをホストマシンの 8000 ポートに割り当てることも可能ですが、

8000 ポートは使われていることが多いので今回は 18000 ポートにマッピングします。

$ docker container run                        \
    --name app                                \
    --rm                                      \
    --detach                                  \
    --interactive                             \
    --tty                                     \
    --mount type=bind,src=$(pwd)/src,dst=/src \
    --publish 18000:8000                      \
    docker-practice:app                       \
    php -S 0.0.0.0:8000 -t /src

正しく表示されない場合は、--detach オプションを外して出力をよく確認したり、

コンテナに配置されている設定ファイルを bash を使って確認したりしてください。

ホストマシン – コンテナ の通信はできるようにはなりましたが、コンテナ – コンテナ の通信は ポートの公開では解決できません

コンテナ – コンテナ の通信は、ネットワークで対応します。

ポート公開の要点まとめ

  1. ホストマシンからアクセス したい場合は、コンテナのポートを公開する
  2. コンテナ側のポートは、起動しているサービスに合わせる
  3. ホストマシン側のポートは、衝突しないように自分で決める

ネットワークを作成する – network create

docker network create [option] name

ネットワークを指定して、コンテナを起動するオプション – container run

オプション意味用途
--networkコンテナをネットワークに接続ほかのコンテナと通信できるようにする
--network-aliasコンテナにネットワーク内での
エイリアスを設定
ほかのコンテナから指定しやすくする

Docker のネットワークについて

Docker のコンテナはネットワークドライバというもので Docker ネットワークに接続されます。

ネットワークドライバはデフォルトでいくつか用意されており、

たとえばブリッジネットワークやオーバーレイネットワークというものがあります。

ブリッジネットワークにはこのような特徴があります。

  1. ネットワークドライバを特に指定しなかった場合の デフォルト である
  2. 同一の Docker Engine 上のコンテナ が互いに通信をする場合に利用する

オーバーレイネットワークにはこのような特徴があります。

  1. 異なる Docker Engine 上のコンテナ が互いに通信をする場合に利用する

ユーザ定義ブリッジネットワーク

コンテナを起動する際にネットワークドライバについて一切の指定を行わないと、

デフォルトブリッジネットワークが自動的に生成され、コンテナはこのネットワークに接続されます。

このデフォルトブリッジネットワークには次のような特徴があります。

  1. コンテナが通信するためには、全てのコンテナ間をリンクする操作が必要になる
  2. コンテナ間の通信は IP アドレスで行う
  3. Docker Engine 上の全てのコンテナ ( たとえば別プロジェクト ) に接続できてしまう

これに対し、自分でブリッジネットワーク(ユーザ定義ブリッジネットワーク)を作成すると、

デフォルトネットワークと比べて次のような利点のあるネットワークに接続できます。

  1. 相互通信をできるようにするには同じネットワークを割り当てるだけでよい
  2. コンテナ間で自動的に DNS 解決を行える
  3. 通信できるコンテナが同一ネットワーク上のコンテナに限られ、隔離度があがる

「コンパイルをしてほしい」「静的コンテンツをホスティングしてほしい」のように

コンテナ間通信を必要としない場合はデフォルトブリッジネットワークで十分 ですが、

「PHP から MySQL を使う」のように、コンテナ間通信を必要とする場合はユーザ定義ブリッジネットワークを使う と判断してよいでしょう。

ユーザ定義ネットワークを作成する

ネットワークの作成は、次のコマンドで行います。

docker network create [option] <name>

この本では特に [option] は指定せず、docker-practice-network という名前のネットワークを作ります。

docker network create docker-practice-network

これでコンテナをネットワークに接続する準備ができました。

ネットワーク一覧を確認する

ネットワーク一覧を確認するには、 network ls を使います。

docker network ls
NETWORK ID     NAME                      DRIVER    SCOPE
6905ce02f3e1   bridge                    bridge    local
7d0ac1503226   docker-practice-network   bridge    local
a99e9af11f39   host                      host      local
2811948d2fd4   none                      null      local

bridge と host と none はデフォルトの必ず存在するネットワークで、

それに加えて1つの bridge ドライバの docker-practice-network があることを確認できます。

App コンテナをネットワークに接続する

ボリュームのときと同様に、作成したネットワークにコンテナを接続するには container run のオプションを追加します。

--network で作成した docker-practice-network を指定するようにコマンドを修正します。

docker container run                          \
    --name app                                \
    --rm                                      \
    --detach                                  \
    --mount type=bind,src=$(pwd)/src,dst=/src \
    --publish 18000:8000                      \
    --network docker-practice-network         \
    docker-practice:app                       \
    php -S 0.0.0.0:8000 -t /src

これで App コンテナがほかのコンテナに接続する準備ができました。

コンテナがネットワークに接続できたことを確認する

コンテナがネットワークに接続できているか確認するには、

ネットワークを検査する network inspect コマンドとコンテナを検査する container inspect コマンドを使います。

docker network inspect docker-practice-network | jq '.[].IPAM.Config'
[
  {
    "Subnet": "172.18.0.0/16",
    "Gateway": "172.18.0.1"
  }
]

次にコンテナの検査をしてみると、Networks に docker-practice-network が設定されており、

IPAddress が 172.18.0.2 になっています。

docker container inspect app | jq '.[].NetworkSettings.Networks'
{
  "docker-practice-network": {
    "IPAMConfig": null,
    "Links": null,
    "Aliases": [
      "4938ec87cf68"
    ],
    "NetworkID": "7d0ac150322661f9991bf2f55c6bfe335f2b5fb13fc555661a7840a95104666a",
    "EndpointID": "01c1b854019725e62a6b370975d0afaaceb5276051851d507b9cb77526c6f2d0",
    "Gateway": "172.18.0.1",
    "IPAddress": "172.18.0.2",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:ac:12:00:02",
    "DriverOpts": null
  }
}

ネットワークの Gateway とコンテナの Gateway が一致していて、

コンテナの IPAddress がそれに続く値になっていれば、ちゃんと設定できています。

DB コンテナをネットワークに接続し、エイリアスを設定する

App コンテナだけネットワークに接続しても意味はないので、DB コンテナもネットワークに接続します。

当然接続するネットワークは App コンテナと同じ docker-practice-network です。

また、App コンテナから DB コンテナにアクセスする時に使うホスト名を --network-alias オプションを使って設定します。

docker container run                                                                         \
    --name db                                                                                \
    --rm                                                                                     \
    --detach                                                                                 \
    --platform linux/amd64                                                                   \
    --env MYSQL_ROOT_PASSWORD=rootpassword                                                   \
    --env MYSQL_USER=hoge                                                                    \
    --env MYSQL_PASSWORD=password                                                            \
    --env MYSQL_DATABASE=event                                                               \
    --mount type=volume,src=docker-practice-db-volume,dst=/var/lib/mysql                     \
    --mount type=bind,src=$(pwd)/docker/db/init.sql,dst=/docker-entrypoint-initdb.d/init.sql \
    --network docker-practice-network                                                        \
    --network-alias db                                                                       \
    docker-practice:db
1216c252738eace7f9aabb7ef4015c0b35a26cdeb059d965df09c10d06b77ecb

これで DB コンテナがほかのコンテナから db というホスト名で接続される準備ができました。

ネットワークとコンテナの Gateway が一致しているか、コンテナの IPAddress が妥当か、確認してみてください。

docker container inspect db | jq '.[].NetworkSettings.Networks'
{
  "docker-practice-network": {
    "IPAMConfig": null,
    "Links": null,
    "Aliases": [
      "db",
      "1216c252738e"
    ],
    "NetworkID": "7d0ac150322661f9991bf2f55c6bfe335f2b5fb13fc555661a7840a95104666a",
    "EndpointID": "0b3ee46fee9fc831607b0cc3e9cc50e0461985d04529d2d8170edde3d9e0edba",
    "Gateway": "172.18.0.1",
    "IPAddress": "172.18.0.3",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:ac:12:00:03",
    "DriverOpts": null
  }
}

また、DB コンテナにはエイリアスを設定したので Networks の Aliases に db が増えていることが確認できるはずです。

--network オプションを正しく設定できたかは Gateway と IPAddress を、--network-alias オプションを正しく設定できたかは Aliases を、それぞれ確認できれば大丈夫です。

Docker のネットワークの要点

  1. コンテナ同士で通信したいときは 自分でネットワークを作る
  2. 同じネットワーク に接続したコンテナ同士なら通信できる
  3. エイリアス を設定すると ホスト名 で通信できる

Docker Compose系のCLI・コマンド操作

Docker ComposeでDockerfileから Docker Imageを作成(Build)する

docker-compose buildコマンドを使用すると、DockerfileからDocker Imageを再構築できます。

docker-compose buildコマンドは、Dockerfileを使用してイメージをビルドまたは再ビルドします。

docker-compose build

Docker Composeで Containerをバックグラウンドで起動する

次のコマンドで、定義したサービスをバックグラウンドで起動します。

docker-compose up -d

docker-compose up コマンドは、docker-compose.ymlファイルからサービスをビルドし、Containerを起動するためのコマンドです。

-d フラグは、コンテナをデタッチドモードで実行することを指定しています。

Docker Composeで立ち上げた Container の 一括停止・一括削除

Docker Composeで立ち上げたDocker Containerたちは、次のコマンドで、一括停止 & 一括削除できます。

コマンドの実行は、プロジェクト・ルードで行います。

docker-compose down

ちなみに、docker-compose downコマンドに引数は必要ありません。

ちなみに、docker-compose downコマンドに引数は必要ありません。

引数を指定しなくても、このコマンドは、プロジェクト内のdocker-compose.ymlファイルを自動的に探し、実行されます。

つまり、そのDirectory内のdocker-compose.ymlを自動で発見して、定義されている、すべてのサービスのコンテナを停止 & 削除してくれるわけです。

引数に指定したサービスのみを停止・削除するには、docker-compose stopdocker-compose rmコマンドを使用する必要があります。

関連記事

Dockerの学習・参考書

参考・引用

  1. 実践 Docker – ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本

最近の投稿