経緯
CircleCI上でローカルマシンで実行しているのと同じdocker-compose.yml
を使ってdocker-compose up
コマンドでローカルと環境を統一した状態で自動テストできるようにしたろ!とCircleCIの公式ドキュメントRun Docker commandsを読んでいると
「Docker実行環境内でDockerイメージをビルドするためには、リモートDocker環境を使ってください。」
とか
「dockerコマンド・docker-composeコマンドを使ってDockerイメージをビルドするためには、ジョブ内でsetup_remote_docker
キーを設定する必要があります。」
という記述が出てきた。
「リモートDocker?よう知らんけど、とりあえず言われて通りやってみるか!」とjobを設定してパイプライン実行させると失敗。ログを確認すると、バインドマウントの設定部分で「ホストマシン側にそんなファイルねぇわ」的なエラーが発生していた。
エラーメッセージ的にとりあえず「リモート」Dockerがあやしすぎるということで調べてみると、「Dockerの動作の仕組み」の理解が足りてないことに気づいた。
この記事はそれらの備忘録。
Dockerの動作の仕組み
![]() |
---|
出典: Docker architecture |
Docker architectureに書かれていることをまとめると、
- Dockerはクライアント・サーバーアーキテクチャである。
- サーバーの構成要素は、Dockerデーモン・イメージ群・コンテナ群
- Dockerクライアントは、実行されたdockerコマンド(イメージのビルド、コンテナの作成・起動、イメージのpush, pull etc.)に対する具体的な処理をDockerデーモンにお願いする(Docker APIのリクエストで)。
- Dockerデーモンは、Dockerクライアントからのリクエストに対する具体的な処理をする。
- Dockerデーモンはクライアントと同じシステム上で動作させることもできるし、リモートで動作しているDockerデーモンにクライアントが接続するといった構成でもいける
リモートのDockerデーモンの利用
How to deploy on remote Docker hosts with docker-compose によると、環境変数DOCKER_HOST
でDockerデーモンが動作しているリモート環境を設定している、または-H
(--host)オプションで直接リモート環境を指定しつつdocker-compose up
を実行することでリモートのDockerデーモンを使って各種dockerコマンドを実行できる模様。
他にもcontextを設定しての方法もある模様。
CircleCIでのdockerコマンド実行
Run Docker commandsには他にも以下のような記述がある。
「リモートDocker環境に使用されるリソースクラスは、ジョブのプライマリコンテナをどのように設定するかによって決定される。」
つまり、プライマリコンテナのVMとリモートDocker環境のVMは異なるということだろう。
先述の情報を合わせると、CircleCIではsetup_remote_docker
によって、おそらく以下のような形で動作しているのだろう。
これなら、バインドマウントの設定でホスト側のファイルないわエラー が出るのも納得できる。
だってリモートDocker側の環境にバインドマウント対象のファイルがごそっとコピーされてるわけじゃないんだもの。イメージビルド時にプライマリコンテナ側にあったファイルはイメージ内にコンテキストとして引き渡されてはいるけれども。
謎な点
Run Docker commandsには以下の記述もある。
「setup_remote_docker
を使用することで、全てのdockerコマンドはプライマリコンテナの起動に使われたのと同じVM上で実行される」
ちょっとよくわかんないけど、今のところは重要でなさそうなので、また問題にぶち当たったら考えることにする。
参考
Docker architecture
リモートホストで動作しているDockerデーモンを使用する
Docker Engineを立ててクライアントからいじる
How to deploy on remote Docker hosts with docker-compose