Ubuntu 22.04 から openjdk-19 が消えた話 ── nginx-clojure の Docker build が壊れた原因と Java 17 への退避
ある日突然、これまで何年も通っていた docker build が、「openjdk-19-jdk-headless が見つからない」というエラーで失敗するようになりました。
ベースイメージは ubuntu:22.04、コンテナ内では nginx-clojure を組み込んだ Nginx をビルドしている、というよくある構成です。
本記事では、なぜこの問題が起きたのか、そしてなぜ nginx-clojure が非 LTS の Java 19 を要求していたのかを調べた記録をまとめます。
同じように Docker build が壊れて困っている方、あるいは「LTS じゃないバージョンを依存ライブラリが要求してくる現象」とどう向き合うか考えている方の参考になれば幸いです。
問題の現象
壊れた Dockerfile の該当箇所は以下のようなシンプルな apt-get install です。
apt-get -y install openjdk-19-jdk-headlessこれがある日から、「Unable to locate package openjdk-19-jdk-headless」のような形で失敗するようになりました。
このコンテナは nginx-clojure というモジュールを Nginx に組み込んでビルドするため、Java(OpenJDK)が必須です。
ビルドが通らないとイメージを更新できず、デプロイパイプラインが止まる、というインパクトの大きい問題でした。
原因 ── openjdk-19 は Ubuntu の universe から正式に削除されている
結論から言うと、openjdk-19 系のパッケージは Ubuntu 22.04 (jammy) の universe から正式に削除されています。
これは推測ではなく、Ubuntu Foundations Team による公式アナウンスがあります。
2025 年 9 月 2 日付で Ubuntu Discourse の Announcements カテゴリに「OpenJDK 19 removal from Ubuntu 22.04 LTS (Jammy Jellyfish)」というタイトルでアナウンスが掲示されました。
要旨は「OpenJDK 19 はインテリム(非 LTS)リリースで上流が EOL に達したため、jammy LTS の universe から 2025 年 10 月までに削除する」というもので、その後 Foundations Team Updates の作業ログでも実施が確認できます。
削除対象は openjdk-19 ソースから生成される全バリアント(-jdk / -jdk-headless / -jre / -jre-headless / -jre-zero / -dbg / -doc / -source)で、jammy / jammy-updates / jammy-security のすべてから消えています。
Ubuntu 22.04 の universe には、リリース当初は openjdk-8 / 11 / 17 / 18 / 19 など複数のバージョンが入っていましたが、非 LTS バージョン(OpenJDK 12, 13, …, 18, 19)はサポート期間が短いため、上流の EOL に合わせて順次削除されてきた、というのが Ubuntu 側の方針です。
OpenJDK 19 自体は Oracle のリリースモデル上、2022 年 9 月にリリースされ、2023 年 3 月には次の 20 が出てサポート終了という、わずか半年寿命のバージョンでした。
Ubuntu 側がこれを長期間維持するインセンティブはなく、今回の削除は方針どおりの正規の措置と言えます。
| OpenJDK | 種別 | リリース | Ubuntu 22.04 universe |
|---|---|---|---|
| 11 | LTS | 2018-09 | 維持 |
| 17 | LTS | 2021-09 | 維持 |
| 18 | 非 LTS | 2022-03 | 削除済み |
| 19 | 非 LTS | 2022-09 | 削除済み |
| 21 | LTS | 2023-09 | 維持 |
表のとおり、apt から取得し続けたいなら LTS 系(11/17/21)に揃えるのが現実的、ということになります。
そもそもなぜ nginx-clojure は Java 19 を指定していたのか
ここで気になる疑問が出てきます。
Java の LTS は 8, 11, 17, 21 と続いており、普通に考えれば 17 LTS を指定するのが自然です。
それなのに、なぜ Dockerfile では非 LTS の openjdk-19-jdk-headless を使っていたのでしょうか。
nginx-clojure の README を確認すると、サポート対象 Java バージョンとして以下のように記載されていました。
- 「Support Java 8, 9, 10, 11, 12, 19」
- 「Support to use jdk19 built-in coroutine viz. Continuation」
2 行目が決定的でした。
nginx-clojure はJDK 19 でビルトインで導入された Continuation API(Project Loom 由来)を使う機能をサポートしているため、機能フルセットを使うときの推奨バージョンとして 19 を挙げていたのです。
Project Loom と Continuation API ── なぜ 19 だったのか
Project Loom は、Java に軽量スレッド(Virtual Threads)と協調的な実行制御(Continuation)を導入する OpenJDK のプロジェクトです。
このうち jdk.internal.vm.Continuation という内部 API が JVM に実装として組み込まれたのが、JDK 19 です。
nginx-clojure はリクエスト処理にコルーチン的な仕組みを使っているため、JVM ネイティブの Continuation が使えると、独自実装よりもシンプルかつ効率的に処理を書けます。
これが、nginx-clojure 側で「Java 19」が前面に出ていた理由です。
| バージョン | Project Loom 関連の主な状況 |
|---|---|
| JDK 17 | Continuation / Virtual Threads は未導入 |
| JDK 19 | Virtual Threads がプレビュー導入。jdk.internal.vm.Continuation が利用可能に |
| JDK 21 | Virtual Threads が正式機能化(LTS) |
本来なら、nginx-clojure を Continuation 込みで使いたい場合の現代的な選択は JDK 21 LTS です。
ただし nginx-clojure 0.6.0 の README が更新されたタイミングでは 21 がまだリリース前後だったため、明示されているのが 19 のまま、という事情があります。
17 にダウングレードしても本当に動くのか
「19 は Continuation のために指定されている」とわかったことで、次の論点が見えてきます。
Continuation 機能を実際に使っていなければ、17 にダウングレードしても問題ないのでは?
nginx-clojure の README をさらに読むと、サポート対象として「Java 8, 9, 10, 11, 12, 19」と並んでいることがわかります。
17 が明示されていないのは「テストしていないだけ」であり、17 が動かないという意味ではないと読むのが自然です。
判断材料として、nginx-clojure を起動するときの jvm_options 設定を確認しました。
具体的には、運用中のサービスでは以下のような --add-opens しか指定していませんでした。
--add-opens=java.base/java.lang=ALL-UNNAMED--add-opens=java.base/sun.nio.cs=ALL-UNNAMED--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
もし Continuation 機能を使っていれば、--add-opens=java.base/jdk.internal.vm=ALL-UNNAMED のようにJDK 内部モジュールを開く設定が必要になるはずです。
その指定がないということは、Continuation の機能を実際には使っていない、と判断できます。
この事実から、17 へのダウングレードによる機能的な影響はほぼ無い見込み、と判断できました。
対応 ── Dockerfile を 17 に書き換える
調査で方針が立ったので、Dockerfile を Java 17 に書き換えます。
変更点は 2 行のみです。
変更前
openjdk-19-jdk-headless
ln -s /usr/lib/jvm/java-19-openjdk-amd64 /usr/lib/jvm/default-jvm変更後
openjdk-17-jdk-headless
ln -s /usr/lib/jvm/java-17-openjdk-amd64 /usr/lib/jvm/default-jvmローカルで docker build を実行したところ、無事に成功しました。
nginx の ./configure 段階で参照している jni.h も Java 17 のヘッダで問題なくコンパイルが通り、ビルド成果物まで作られています。
教訓 ── 非 LTS の Java を本番で使うリスク
今回の問題は、非 LTS の Java バージョンを本番イメージで使い続けるリスクを浮き彫りにしました。
OpenJDK の非 LTS バージョンは半年で次のバージョンに置き換わる前提で設計されており、ディストリビューションの apt リポジトリも、これに合わせて遅かれ早かれパッケージを削除します。
これは「いつかは壊れる」既定路線であり、今回の Docker build 失敗は時間の問題で発生していたと言えます。
同じ轍を踏まないために、依存ライブラリの README に非 LTS バージョンが明示されていた場合、以下の判断軸を持っておくと安全です。
- そのバージョン固有の機能を本当に使っているかを
jvm_optionsや--add-opensから確認する - 使っていなければ、直近の LTS(17 または 21)にピン留めして運用する
- 本当に必要なら、apt ではなく公式 OpenJDK バイナリ(Adoptium / Temurin など)を直接ダウンロードしてイメージに同梱する
3 の方法は apt の都合に左右されないので、非 LTS をどうしても使い続けたい場合の現実的な選択肢になります。
まとめ
- Ubuntu 22.04 の universe からは、非 LTS の OpenJDK(18, 19 など)は上流 EOL に合わせて順次削除されている。openjdk-19 については 2025 年 9 月の Ubuntu Foundations Team の公式アナウンスで削除がアナウンスされ、同年 10 月に実施済み。apt から取得することはできない。
- nginx-clojure が 19 を明示していた理由は、JDK 19 で導入された Continuation API を使う機能のため。19 が必須なわけではない。
- Continuation 機能を使っていない(
--add-opens=java.base/jdk.internal.vm系の指定が無い)プロジェクトでは、Java 17 LTS にダウングレードして問題ない。 - 長期的には、依存先が非 LTS を要求してくる場合の方針(LTS にピン留め / 公式バイナリ同梱)を決めておくと、今回のような事故を未然に防げる。
「ある日突然 Docker build が壊れる」系の障害は、原因が apt 側のパッケージ削除という自分のコード以外の場所にあるため、慣れていないと特定に時間がかかります。
同じ問題に遭遇した方の参考になれば幸いです。
