ある日、プログラミングコンテストの準備をしている最中、Docker が動かなくなりました。具体的には以下のエラーが出ました。

$ docker run hello-world
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: unable to retrieve OCI runtime error (open /run/containerd/io.containerd.runtime.v2.task/moby/ec41588606fcd4b3a6c71d48fdcf01836f5e5899066c17748b111bd8cfd73cf0/log.json: no such file or directory): runc did not terminate successfully: exit status 127: unknown.

何が起こったのかの解明が面倒だったので解説します。

前提

ICPCプログラミングコンテストはオンサイトコンテストで、大会側が選手用のコンピュータをすべて用意します。インストールするソフトウェアも大会側で準備し、どのような環境になるかは事前に公開していますインストール可能なイメージの公開もしています

プログラミングコンテストなので、選手用のコンピュータではプログラムが書けて実行できるようになっています。プログラムのコンパイラオプションや実行オプションが審判サーバの環境とほぼ同じになるように、コンパイル/実行用スクリプトがそれぞれのプログラミング言語に対して提供されています

列挙されているスクリプトのうち、C/C++を実行するスクリプトである runc / runcpp / rungcc / rung++ は、去年までは用意されていませんでした。C/C++ の実行プログラムは単に与えられたプログラムを実行するだけなので、無意味だと思われていたからです。しかし、世界大会でそれらが提供されているとの情報もあり、今年からこれらのスクリプトも提供することにしました。

一方、プログラミングコンテストを開催するには、選手のコンピュータ以外にもコンテスト管理用コンピュータが必要です。これらも選手用のコンピュータと同じものを使い、選手用のソフトウェアをインストールしたのちに、 Ansible などを用いて追加のソフトウェアを導入しています。コンテスト管理用コンピュータでは、例えば Prometheus を動かして、選手マシンの監視を行っています。いろいろなソフトウェアの組み合わせを一度に立ち上げるために、 Ansible や Docker Compose を活用しています。

事件

さて、ここで、去年まで管理用コンピュータで動いていた Docker が動かなくなりました。 docker run はエラーで止まってしまい、ろくなメッセージを出しません。なぜでしょう。

解答

runc が C の実行スクリプトと、 Docker のランタイム runc とで名前が被っていました。 Docker が runc を呼び出そうとしたところ、前者の実行スクリプトが呼ばれるようになってしまっていました。そのため、 runc の引数がそのまま実行されて、exit code 127, すなわち “Command not found” が返ってきていたのでした。