Error [libGL.so.1: cannot open shared object file]

ImportError: libGL.so.1 の直し方(opencv-python をサーバや Docker で import して落ちるとき)

FIX SUMMARY verified
Applies when
python:3.12-slimopencv-python (links GUI shared libs absent on headless Linux)import cv2 from opencv-python on a headless/slim Linux missing libGL.so.1

Verified: reproduced in python:3.12-slim, then the libGL.so.1: cannot open shared object file signature was gone after the fix (exit 0).

手元では動いていた OpenCV を使うコードが、Docker のイメージやサーバ、CI に載せた途端、import cv2 の行で次のエラーを出して止まることがあります。

ImportError: libGL.so.1: cannot open shared object file: No such file or directory

これは Python のパッケージが壊れているのではありません。opencv-python が表示(GUI)まわりの共有ライブラリに依存していて、そのライブラリが OS に入っていないために出ます。libGL.so.1 は OpenGL の共有ライブラリで、画面描画を持たないサーバや軽量イメージには入っていないことが多いのです。

サーバや Docker で使うなら、直し方は opencv-python の代わりに opencv-python-headless を入れることです。

なぜ出るのか:GUI 用の共有ライブラリが OS に無い

pip install opencv-python で入る OpenCV は、画像をウィンドウに表示する機能(cv2.imshow など)を含んでいます。その機能を動かすため、wheel の中身は libGL.so.1 のような OS 側の共有ライブラリに動的リンクしています。デスクトップ環境の Linux にはこれらが揃っているので、手元では問題になりません。

ところが、画面を持たない環境(Docker の slim イメージ、CI、サーバ)には、GUI 用の共有ライブラリが入っていませんimport cv2 は起動時にこの共有ライブラリを探し、見つからないと libGL.so.1: cannot open shared object file で止まります。これは Python の版でもパッケージの版でもなく、OS に入っているパッケージの違いで起きる、環境依存のエラーです。

なぜ手元では出ないのか

「開発機(デスクトップ Linux や、GUI ライブラリが揃った環境)では動くのに、Docker や CI でだけ落ちる」というのが典型です。手元には libGL などが最初から入っていて、コンテナの軽量イメージには入っていない、という差です。落ちている環境で、その共有ライブラリがあるかどうかは、エラーに出ている名前(libGL.so.1 など)で見当がつきます。

サーバや CI で画像をウィンドウに表示する必要はまずありません。読み込み・加工・保存だけなら、表示機能は不要です。そこが直し方の分かれ目になります。

直し方:opencv-python-headless に替える

サーバや Docker のように画面を持たない環境では、表示機能を省いた opencv-python-headless を使えば、OS 側に GUI 用ライブラリを足さずに済みます。中身の cv2 は同じで、imread / imwrite / 画像処理はそのまま使えます。違うのは、GUI 用の共有ライブラリに依存しない点です。

pip uninstall -y opencv-python
pip install opencv-python-headless

requirements.txt でも、opencv-pythonopencv-python-headless に書き換えます。両方を同時に入れないでください(同じ cv2 を提供するので競合します)。これで OS 側に追加のライブラリを入れなくても import cv2 が通ります。

どうしても opencv-python(GUI つき)が必要な場合は、不足している共有ライブラリを OS 側に入れます。Debian / Ubuntu 系なら、次のように apt で足します(Dockerfile の root ユーザーならそのまま、ホストで直接入れるなら sudo を付けます)。

apt-get update && apt-get install -y libgl1 libglib2.0-0

libgl1libGL.so.1 を、libglib2.0-0 が関連する共有ライブラリを提供します。パッケージ名はディストリビューションで異なり、ここでは python:3.12-slim の土台である Debian 12(bookworm)の名前です。古い案内では libgl1-mesa-glx、新しい版(Ubuntu 24.04 や Debian 13 など、t64 移行後)では libglib2.0-0t64 のように変わるので、使っている土台イメージに合わせてください。Dockerfile なら、pip install の前後でこの apt-get install を実行する行を足します。ただし、画面表示が要らないのにこれらを入れるのは、イメージを重くするだけです。サーバ用途では headless を選ぶほうが軽く済みます

切り分け(うまくいかないとき)

  • libGL.so.1 以外の共有ライブラリが無い、と出る:opencv-python は複数の共有ライブラリに依存していて、環境によって最初に見つからないものが変わります。実測では libglib2.0-0 由来のライブラリ(libgthread-2.0.so.0 など)が芋づるで要ることがありました。ほかにも libSM.so.6(X11 セッション管理)のような名前が報告される例もあります。根本対処は同じで、headless に替えるか、エラーに出ている共有ライブラリ名をその OS のパッケージ検索で照合して apt で足します。
  • 新しい opencv-python を入れたら、今度は libxcb.so.1 が無い、と出た:opencv-python の版によって、リンクしている共有ライブラリが変わります。新しい版では libGL ではなく別の名前になることがあります。いずれにせよ、サーバなら headless に替えるのがいちばん確実です。
  • headless に替えても直らないopencv-pythonopencv-python-headless が両方入っていないか確認してください。両方あると、同じ cv2 の置き場所を後から入れたほうが上書きし、片方を uninstall するとファイルが欠けて壊れることがあります。pip uninstall opencv-python opencv-python-headless で一度両方消してから、headless だけを入れ直します。opencv-contrib-python を使っている場合は、その headless 版 opencv-contrib-python-headless に替えます。
  • 本当にウィンドウ表示(cv2.imshow)がしたい:それはサーバ/コンテナでは別の準備(X サーバや仮想ディスプレイ)が要る話で、headless では実現できません。表示が要るなら opencv-python + GUI ライブラリの構成にし、表示先のディスプレイも用意します。

検証環境

  • python:3.12-slim、ネットワーク有り
  • 再現:pip install "opencv-python==4.10.0.84" の後、import cv2ImportError: libGL.so.1: cannot open shared object file で終了コード 1
  • 修正:pip install "opencv-python-headless==4.10.0.84" の後、同じスクリプトが終了コード 0

再現から修正までは errfix の検証ハーネスが機械的に確認しています。GUI ライブラリを持たない slim イメージで opencv-pythonimport cv2 が落ちること、opencv-python-headless に替えると同じコードが通ることを、再現→修正→シグネチャ消滅として通しました。apt install libgl1 libglib2.0-0 で共有ライブラリを足す方向でも通ることを実測しています。新しい opencv-python(5 系)では欠ける共有ライブラリが libxcb.so.1 に変わることも確認しました。

検証(machine-verified)

この修正は python:3.12-slim のバージョン固定コンテナ内で再現し、修正後に libGL.so.1: cannot open shared object file のシグネチャが消えることを機械で確認しています。

verify — run-case.mjs
$ node run-case.mjs python/opencv-libgl-not-found
● reproduce libGL.so.1: cannot open shared object file present ✓
● apply fix exit 0
● re-run libGL.so.1: cannot open shared object file gone ✓
PASS verified · python:3.12-slim · signature gone