手元では動いていた 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-python を opencv-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
libgl1 が libGL.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-pythonとopencv-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 cv2がImportError: libGL.so.1: cannot open shared object fileで終了コード 1 - 修正:
pip install "opencv-python-headless==4.10.0.84"の後、同じスクリプトが終了コード 0
再現から修正までは errfix の検証ハーネスが機械的に確認しています。GUI ライブラリを持たない slim イメージで opencv-python の import cv2 が落ちること、opencv-python-headless に替えると同じコードが通ることを、再現→修正→シグネチャ消滅として通しました。apt install libgl1 libglib2.0-0 で共有ライブラリを足す方向でも通ることを実測しています。新しい opencv-python(5 系)では欠ける共有ライブラリが libxcb.so.1 に変わることも確認しました。