Azure 上の Ubuntu 24.04 LTS で Judge0 を Docker 運用しようとすると、isolate が依存する cgroup v1 の memory.limit_in_bytes が見つからず、実行が失敗することがあります。本記事では原因の見極め方と、確実に復旧できる OS 選定・移行手順を具体的に解説します。
Azure Ubuntu 24.04 で発生する Judge0 のエラー症状
Azure VM(例:Standard B2as v2)に Ubuntu 24.04 LTS を入れ、Judge0(オープンソースのコード実行 API)を Docker コンテナで起動したところ、実行時に以下のようなエラーで落ちるケースがあります。
Cannot write /sys/fs/cgroup/memory/box-X/memory.limit_in_bytes: No such file or directory
Judge0 は内部で isolate というサンドボックスを使い、リソース制限(特にメモリ)を cgroup に書き込むことで実現します。このとき isolate は伝統的に cgroup v1 のファイル(memory.limit_in_bytes など)へアクセスする実装・設定になっていることが多く、該当ファイルが存在しないと Judge0 側では内部エラー(例:status_id 13)として扱われます。
| 項目 | 内容(例) | 重要ポイント |
|---|---|---|
| VM | Azure Standard B2as v2 | VM サイズ起因ではないことが多い |
| OS | Ubuntu 24.04 LTS | cgroup v2 前提の挙動が強い世代 |
| カーネルパラメータ | systemd.unified_cgroup_hierarchy=false cgroup_enable=memory swapaccount=1 | 付けても v1 が期待通りにならない場合がある |
| 見えている状態 | /sys/fs/cgroup/memory/ は存在 | 存在しても「v1 が完全」とは限らない |
| 致命点 | memory.limit_in_bytes が無い | isolate が書けず Judge0 が失敗 |
原因の核心:cgroup v1 の memory.limit_in_bytes が前提の仕組みと、Ubuntu 24.04 の現実
結論から言うと、今回の事故は「Judge0 / isolate が想定する cgroup のインターフェース」と「Ubuntu 24.04(特に cloud 向け構成)が提供する cgroup の実装・既定値」の ミスマッチで起きます。
cgroup v1 と cgroup v2 は“同じ cgroup”でもファイル名も流儀も違う
memory.limit_in_bytes は cgroup v1 のメモリ制限を表す代表的なファイルです。一方、cgroup v2 では設計が変わり、同等の役割は主に memory.max などが担います。つまり、OS が cgroup v2 前提で動いていると、v1 のファイルが無いのは「故障」ではなく「仕様」です。
| 用途 | cgroup v1(レガシー) | cgroup v2(統合階層) | 現場での影響 |
|---|---|---|---|
| メモリ上限 | memory.limit_in_bytes | memory.max | isolate が v1 固定だと v2 環境で失敗 |
| メモリ使用量 | memory.usage_in_bytes | memory.current | 監視・ログの取り方が変わる |
| CPU 制限 | cpu.cfs_quota_us 等 | cpu.max | ツールが v1 前提だと設定不能 |
| 階層構造 | コントローラ別にマウント | 統合階層(単一ツリー) | パスが変わり、ハードコードが壊れやすい |
「/sys/fs/cgroup/memory がある」だけでは安心できない理由
混乱の元はここです。Ubuntu 24.04 で /sys/fs/cgroup/memory/ ディレクトリが存在しても、次のような状態があり得ます。
- cgroup v2 で動いていて、たまたまディレクトリだけ存在している(中身は v1 互換ファイルではない)
- v1 のマウント自体は見えても、期待するファイルが揃わない(部分的・非推奨構成・組み合わせ不整合)
- isolate が想定するパスに対して、実際の制御点が別にある(v2 であれば
/sys/fs/cgroup/配下)
つまり、Judge0 側から見ると「書き込むべきファイルが無い」ため、No such file or directory で止まります。
まずやるべき切り分け:いま本当に cgroup v1 で動いているのか
同じ「cgroup」という言葉でも、v1 と v2 で確認方法が変わります。以下は現場で効く確認セットです。結果を見れば、どこがズレているかが一気に分かります。
| 確認したいこと | コマンド例 | 見え方の目安 | 次の一手 |
|---|---|---|---|
| cgroup の大枠(v2 かどうか) | stat -fc %T /sys/fs/cgroup | cgroup2fs なら v2、tmpfs 等なら要調査 | v2 なら v1 ファイル前提は基本的に破綻 |
| マウント状況(v1 の memory が本当にマウントされているか) | mount | grep cgroup | type cgroup で memory が出るか、type cgroup2 か | v2 のみなら isolate 側の前提を変える必要 |
| memory.limit_in_bytes が存在するか | ls -l /sys/fs/cgroup/memory/memory.limit_in_bytes | 存在しなければ v1 前提アプリは失敗しやすい | OS/構成変更が最短 |
| 自分のプロセスが属する cgroup 形式 | cat /proc/1/cgroup | 0::/ のような表示が多いと v2 の典型 | Judge0/isolate が v1 依存なら方針転換 |
| Docker が認識している cgroup バージョン | docker info | grep -i cgroup | Cgroup Version: 2 等 | コンテナ基盤が v2 なら、v1 固定ツールは要対策 |
上記のどこかで「v2 っぽい」結果が出た場合、isolate が v1 の memory.limit_in_bytes を書く設計のままでは、根本的に噛み合いません。ここで小手先のマウントやディレクトリ作成をしても、カーネル側の制御点が違うため、期待通りに動かないことがほとんどです。
Judge0 / isolate が失敗するメカニズムをもう一段具体的に
Judge0 の多くの構成では、実行ごとに isolate が「箱(box)」を作り、プロセスをその箱に入れて制限をかけます。その際に、メモリ上限をファイル書き込みで設定します(概念的には次のような流れ)。
- 実行用の cgroup ディレクトリを作る(例:
/sys/fs/cgroup/memory/box-0) - 上限を書き込む(例:
echo 268435456 > memory.limit_in_bytes) - プロセスを cgroup に所属させる(例:
cgroup.procsへ PID を書く)
ここで memory.limit_in_bytes が存在しないと、2 が成立しません。結果として isolate は「制限を設定できない=安全な実行環境を作れない」と判断し、Judge0 は実行をエラー扱いにします。
最短・確実な解決策:Azure の Ubuntu を 22.04 LTS(または 20.04 LTS)へ切り替える
現場で「いますぐ Judge0 を安定稼働させたい」「既存の isolate 前提を変えたくない」場合、最も事故が少ないのは OS を Ubuntu 22.04 LTS にすることです。実際に、Ubuntu 24.04 で詰まった構成が Ubuntu 22.04 に変更して解消した事例は珍しくありません。
どの Azure Ubuntu イメージを選べばいいか
Azure には複数の Ubuntu イメージがありますが、Judge0 + isolate のように「レガシーな cgroup v1 前提」が残っているアプリでは、まずは 22.04 LTS を基準に考えるのが安全です。
| Ubuntu バージョン | Judge0(isolate v1 前提)との相性 | 選びどころ | おすすめ度 |
|---|---|---|---|
| 24.04 LTS | そのままだと失敗しやすい(v2 前提のため) | 新しい OS が必要、かつ cgroup v2 対応へ移行できる場合 | 要検証 |
| 22.04 LTS | 解消しやすい(v1 へ寄せる構成が取りやすい) | 安定運用と保守性のバランスを取りたい場合 | 推奨 |
| 20.04 LTS | 動く可能性は高いが、運用面の検討が必要 | 既存資産が 20.04 前提、または互換性最優先の場合 | 条件付き |
特に 20.04 LTS はリリース年が古いため、社内ルールやセキュリティ要件によっては「サポートの取り扱い(更新ポリシー)」を確認してから選ぶのがおすすめです。迷うなら 22.04 LTS が無難です。
Azure Portal での切り替え方(考え方)
Azure VM は「OS をその場で安全に入れ替える」というより、基本は 新しい VM を作って移行するのがトラブルが少ないです。具体的な進め方は次の通りです。
- Ubuntu 22.04 LTS の新規 VM を作成(サイズは現状と同等でOK)
- Judge0 の設定・環境変数・永続データ(PostgreSQL/Redis/ボリューム)を移行
- DNS / Public IP / リバースプロキシ(Nginx 等)を切り替え
- 旧 VM を停止し、問題なければ削除(または保管)
Azure CLI で新規 VM を作る例(22.04 LTS)
自動化したい場合は Azure CLI でイメージを明示して作ると、意図しないバージョン差分を避けられます。
az vm create \
--resource-group RG-NAME \
--name judge0-ubuntu2204 \
--image Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest \
--size Standard_B2as_v2 \
--admin-username azureuser \
--generate-ssh-keys
既存 VM がどのイメージ参照になっているかは、次のように確認できます。
az vm show \
--resource-group RG-NAME \
--name VM-NAME \
--query storageProfile.imageReference
イメージ指定の文字列(URN)は環境により変わることがあるため、組織内で「標準イメージ」を固定して運用する場合は、作成時に必ず明示する運用が安全です。
「VM サイズが原因?」への答え:ほとんどの場合は違う
Standard B2as v2 のようなサイズが直接 memory.limit_in_bytes を消すことは基本的にありません。今回の問題は、CPU/RAM の量ではなく OS の cgroup 実装と既定の cgroup モードの問題です。
もちろん、Judge0 の同時実行数やコンパイル負荷によってはサイズ見直しが必要ですが、「ファイルが無い」という現象はサイズではなく cgroup 方式(v1/v2)に強く依存します。
どうしても Ubuntu 24.04 で運用したい場合の選択肢
「24.04 を使いたい理由」がある場合もあります(新しいドライバ、他システムとの統一、長期運用、パッケージ世代など)。その場合は、次のいずれかに舵を切る必要があります。
| 選択肢 | やること | メリット | デメリット / リスク |
|---|---|---|---|
| Judge0 / isolate を cgroup v2 対応へ寄せる | isolate のバージョン・ビルド・設定を見直し、v2 の制御点(例:memory.max)を扱える構成へ | OS 標準の流れに乗れる | 検証コストが高い。既存手順が崩れる可能性 |
| 別のサンドボックス機構へ切り替える | Judge0 の実行バックエンドを変更、もしくは isolate 以外の仕組みを検討 | cgroup v1 依存を断てる | 安全性・性能・実装難易度のトレードオフが大きい |
| OS は 22.04 にしてアプリを安定稼働優先 | 24.04 の採用を一旦見送り、22.04 を標準にする | 最短で動く。運用が読みやすい | 「最新 OS 統一」の要件があると妥協が必要 |
実務的には、Judge0 を「サービスとして安定提供」するのが目的なら、まず 22.04 で確実に稼働させ、並行して cgroup v2 対応を検証する二段構えが最も失敗しにくいです。
cgroup v1 に寄せる設定を試す場合の注意点
すでに次のようなパラメータを付けてもダメだった、という状況はよくあります。
systemd.unified_cgroup_hierarchy=false cgroup_enable=memory swapaccount=1
この状態でも改善しない場合、原因は「パラメータが効いていない」「効いているが、想定どおりの v1 構成が実現できていない」「Docker/systemd/isolate の組み合わせが噛み合っていない」などが考えられます。確認するポイントは次の通りです。
- /proc/cmdline にパラメータが実際に載っているか(設定したつもりで反映されていない事故が多い)
- cgroup_no_v1 のような v1 を無効化する設定が混ざっていないか
- mount の種類が本当に v1(type cgroup)になっているか、それとも v2(type cgroup2)なのか
- v1 の memory 階層で ルートにも
memory.limit_in_bytesが無いのか、特定のディレクトリだけ無いのか
ただし、ここを深追いすると「OS の世代が前提としている設計」と喧嘩しやすく、時間が溶けます。Judge0 を目的にするなら、OS を 22.04 へ変更する方がコスト対効果が高いケースが多いです。
移行を成功させるための実務チェックリスト
OS を切り替えるだけで動くこともありますが、Judge0 は周辺コンポーネント(DB、キュー、永続ボリューム)を含むため、移行時は次の点を押さえると事故が減ります。
| チェック項目 | 確認内容 | よくある落とし穴 |
|---|---|---|
| Docker / Compose の互換性 | 新 VM で同じ Compose がそのまま上がるか | パッケージリポジトリ差分で Docker の入れ方が変わる |
| 永続データの移行 | DB/Redis/ボリューム/アップロード領域 | コンテナが起動してもデータが空で「動いたように見える」 |
| ネットワーク | NSG、UFW、リバースプロキシ、ポート開放 | 旧 VM だけ許可していて新 VM が疎通しない |
| 性能 | 同時実行数・コンパイル負荷・スワップ設定 | メモリ制限が効くようになり、逆に OOM の見え方が変わる |
| 監視 | ログ、メトリクス、アラートの引き継ぎ | ホスト名や IP が変わって監視が途切れる |
よくある質問
Azure 上の Ubuntu 24.04 だけの既知の制限ですか?
「Azure だから」というより、Ubuntu 24.04 世代の cgroup v2 前提と、Judge0/isolate の cgroup v1 前提が衝突している、と捉えるのが正確です。Azure の Ubuntu イメージはクラウド運用を意識した構成で提供されるため、この衝突が表面化しやすい、という側面はあります。
Ubuntu 20.04 と 22.04 ならどちらがよいですか?
迷ったら Ubuntu 22.04 LTS がおすすめです。運用で重要な「サポート期間」「パッケージの新しさ」「周辺ツールの互換性」のバランスが良く、Judge0 のようなミドルウェアも採用例が多い世代です。20.04 は互換性重視で選ぶ価値がありますが、組織の更新方針(セキュリティ更新の扱い)を確認してからにすると安心です。
Ubuntu 24.04 のまま直したいが、何から着手すべき?
まずは cgroup v2 を前提にした設計へ寄せられるか(isolate の更新・設定変更、Judge0 の実行バックエンドの見直し)を検討してください。もし短期でサービス復旧が必要なら、22.04 へ切り替えて稼働を確保し、並行して 24.04 対応を検証するのが現実的です。
まとめ:Judge0 を確実に動かすなら「OS 選定」が最短ルート
memory.limit_in_bytesは cgroup v1 のメモリ制御ファイルで、cgroup v2 前提の環境では存在しない(または期待どおりに出ない)ことがある- Ubuntu 24.04 LTS(特にクラウド向け構成)では cgroup v2 前提の挙動が強く、Judge0/isolate の v1 前提と衝突しやすい
- 最短で安定させるなら Azure の OS イメージを Ubuntu 22.04 LTS(または 20.04 LTS)へ切り替えるのが現実的
- 将来 24.04 を使うなら、cgroup v2 対応(ツール更新・構成変更)を前提にロードマップを組む

コメント