LoginSignup
56
42

docker-compose で一向にビルドがはじまらない、もしくは起動しない。はたまた忘れたころに起動する。

Last updated at Posted at 2019-08-24

docker-compose updocker-compose build しても building <サービス名> と出たまま先に進まない。ハングしているような感じで固まる。

Docker Desktop の設定(Preferences)で [Resources]-[File sharing] には、該当ディレクトリの親ディレクトリは含まれています。そもそも、さっきまで正常に動いていました。それが急に動かなくなったのです。何もしていないのに。

TL; DR (今北産業)

  1. 大量のファイルを、裏で Docker daemon が読み込んでいる可能性があります。
  2. docker-compose を使わずに docker build -t test:local . と Docker でビルドしてみて永遠と転送していたらビンゴです。
  3. .dockerignore で、大量ファイルのあるディレクトリを除外しておき、docker-compose.json 内で別途マウントしましょう。

🐒 docker-composedocker compose の違い

2023/01/24 現在、docker-composedocker compose のように、docker のサブコマンドとしての利用が推奨されています。元々 docker-compose は Python 言語による実装だったのですが、docker-compose v2 と同等の機能を Go 言語で実装したものが compose です。

Windows や macOS などで Docker Desktop を利用している場合はデフォルトで内包されています。Linux の場合はパケージマネージャーで追加インストールするか、$HOME/.docker/cli-plugins にバイナリを設置する必要があります。

compose サブコマンドは、動作が速くなっただけでなく、別途 Python のインストールも不要になりました。つまり docker-compose rundocker compose run と同等です。しかし、この記事では docker-compose の記載のままにします。適宜 docker compose と置き換えてお読みください。

TS; DR (わかれば簡単なことに気づくまでの細かいこと)

さっきまで docker-compose run --rm <name_service> で動いていた、機械学習の写経用コンテナが起動しなくなりました。「おかしいな」と、docker-compose build --no-cache とビルドしなおしても同じです。

起動しないと言うより、止まったままの状態が続いたのです。

buildの場合
$ docker-compose build --no-cache
Building sample_service1 ← ここでハングってる

そこで、Ctrl+c で処理を止め、写経と言えば坊主ということで --verbose を呼んでみました。
:bellhop: チリン

build時の詳細
$ docker-compose build --no-cache
Building sample_service1 ← ここでハングってる
^CERROR: Aborting.

$ docker-compose --verbose build --no-cache
compose.config.config.find: Using configuration files: ./docker-compose.yml
...省略...
compose.service.build: Building sample_service1
compose.cli.verbose_proxy.proxy_callable: docker build <- (path='~/Desktop/Sample', tag='samp
le:local', rm=True, forcerm=False, pull=False, nocache=True, dockerfile=None, cache_from=None
, labels=None, buildargs={}, network_mode=None, target=None, shmsize=None, extra_hosts=None,
 container_limits={'memory': None}, gzip=False, isolation=None, platform=None) ← ここで止まる

どうも、上記 compose.cli.verbose_proxy.proxy_callable:docker-composedocker build を呼び出した処理で止まったままです。

Docker がイメージを pull する際、たまにネットワークが重かったり pull 先が重い場合に反応が遅れることはあるのですが、体感的にいつも以上の時間がかかっています。

切り分け(やったこと):

  • docker-compose build --no-cacheNG(現象同じ)
  • docker-compose down からの docker-compose upNG(現象同じ)
  • docker-compose stop からの docker-compose upNG(現象同じ)
  • docker-compose psNG(起動中コンテナなし)
  • docker container prune -f docker image prune -f からの docker-compose build --no-cacheNG(現象同じ)
  • docker-compose logsNGAttaching to が出るだけ)
  • ホスト OS の再起動 → NG(現象同じ)
  • docker run --rm hello-world:latestOK(起動する)
  • docker-compose の "Hello World!"OK(起動する)

以上の切り分けにより、dockerdocker-compose 自体は生きているものの「現在の Dockerfiledocker-compose.yml に問題がありそう」と判断できそうです。

しかし、それらファイルはいじっていません。となると、別途マウントさせてるスクリプトやイメージなどに原因がありそうです。

そこで、docker-compose を通さず Docker から直接イメージを 1 つ 1 つビルドしてみました。

$ docker build -t test:local .
Sending build context to Docker daemon xxxMB

すると、なんとなんと!上記の xxxMB が永遠とカウントアップされていきます。何やら大量のファイルがコンテキストに送られているではありませんか!

「そうかっ!!学習用のデータ、かっ!!」

🐒  コンテキストとは
context は日本語で「文脈」「文の前後関係」「事情」「背景」「状況」などといった意味があります。しかし、プログラムの世界では「文脈」ではピンとこないケースがあります。
コンテキストは、con-text で構成され、con- の接頭辞は「一緒に」とか「付いに」などの意味を持ち、text は 「組み上げる」「編む」「作る」「構成する」の *teks- から来ています。つまり contextは、何かを「実行」「判断」「作成」する際に添えられた裏付け情報のような意味合いになります。
そのため、Sending build context to ... とは「(Docker イメージの)ビルドに必要な情報を ... に送信中」という意味になります。

実は、機械学習用に用意した大量のデータ・ボリューム(data ディレクトリ)をコンテナにマウントさせていたのですが、軽量のデータで動作確認したいと思いディレクトリ名をリネームしたのを失念していました

元々 data ディレクトリ内のデータ量が多いため .dockerignore で除外して、ビルド後にマウントさていました。しかし、datadata2 にリネームされたことにより、ビルド時にデータ(コンテキスト)として data2 がメモリに読み込まれていたのです。

.dockerignore に記載済みだった data 同様、問題の data2 を追加していつもどおり動くようになりましたとさ。とほほ

.dockerignore
data
data2

dockerdocker compose の違い

docker はコンテナを個別に操作するコマンドで、docker compose(旧 docker-compose) は同じマシン上で仮想ネットワークを作成し、その中で複数のコンテナを操作するツールです。

その上位として、同じネットワーク(LAN)内の複数のマシン間で仮想ネットワークを作成し、その中で複数のコンテナを操作するツールに docker swarm があります。さらにハイ・レベルな、複数ネットワーク(WAN)の間で仮想ネットワークを作成し、その中で複数コンテナの操作をするツールに kubernetes などがあります。

これらの、複数のコンテナや仮想ネットワークの作成・操作を支援するツールを、オーケストレーション・ツールと呼びます。つまり docker compose もオーケストレーション・ツールの 1 つであるため、オーケストレーションの入門としては打ってつけです。

docker は、コンテナを作成&起動すると明示しない限り「docker ネットワーク」と呼ばれる仮想ネットワークにコンテナを設置します。つまり、仮想 LAN 内にサーバ(docker のコンテナ)だけが存在するネットワークを作るということです。

この仮想ネットワークは docker network create <ネットワーク名> で作成することもでき、コンテナを起動する際に --network <ネットワーク名> オプションを付ると、そのネットワークに参加させることができます。

これは、サーバ間通信が必要なものをだけを特定のネットワークに入れておき、隔離することで余計なセキュリティの心配を減らすことができます。

例えば、Web サーバと DB サーバを同じネットワークに置いておき、Web サーバのポート(例えば 80 番ポート)だけを外部に開放(ポートを公開)する、などです。この場合、外部からは直接 DB サーバにはアクセスできません。

しかし、この方法だとコンテナやネットワークを起動するたびにコマンドを打たないといけないので、シェル・スクリプトなどで一発で起動させたいと思うことでしょう。

そんな時に使うのが docker compose です。

docker compose は複数コンテナを起動・操作するためのコマンドです。docker-compose.yml という YAML 形式の設定ファイルに記載された条件でコンテナを起動してくれます。

docker compose を使うと docker-compose.yaml に記載されたコンテナはデフォルトで同じネットワークに設置されます。

そのため、複数コンテナを起動してお互いを連携させたい場合は docker compose の利用が便利です。詳しくは以下の記事を参照ください。

参考文献

関連文献

あわせて読みたい

56
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
42