🐋

DockerでOpenGL開発環境

2024/10/27に公開

はじめに

この記事ではDockerでOpenGLを使ったプログラミングができる環境を構築する方法を説明していきます。今回作成する環境はGUIアプリを表示するための環境としても使用可能です。

なぜDocker


Dockerを使うことで、OpenGL開発環境の構築において環境依存の問題を軽減し、異なるシステム間でも同一の環境を簡単に再現可能にします。これにより、開発者間での動作の一貫性を保つことで、効率的に共同開発することができます。また、初心者の方のトラブルを解決しやすくすることができます。

本題

Dockefile

Dockerfile
FROM debian:bookworm

RUN apt-get update && \
    apt-get install -y x11-apps \
    mesa-utils \
    git \
    g++ && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

compose.yml

compose.yml
services:
  app:
    build: 
      context: .
      dockerfile: Dockerfile
    tty: true
    network_mode: "host"
    user: ${USER_ID}:${GROUP_ID}
    environment:
      DISPLAY: $DISPLAY
    volumes:
      - type: bind
        source: /tmp/.X11-unix
        target: /tmp/.X11-unix
      - type: bind
        source: .
        target: /app
    working_dir: /app

実行方法

下記のコマンドを実行することでコンテナを建てることができます。

$ USER_ID="$(id -u)" GROUP_ID="$(id -g)" docker compose up -d

動作確認

$ docker compose exec app /bin/bash
$ xeyes
$ glxgears

すべて動作するか、fpsは60近くで推移するか確認してください

$ glxinfo | grep OpenGL
OpenGL vendor string: X.Org
OpenGL core profile version string: 4.5 (Core Profile) Mesa 22.3.6
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.5 (Compatibility Profile) Mesa 22.3.6
OpenGL shading language version string: 4.50

使われているMesaのバージョン、使用可能なOpenGLのバージョンを確認することができます。
Mesaのバージョンが低いと使用可能なOpenGLのバージョンも下がります。
debian:bookworm, debian:bullseyeでは、OpenGL 4.5まで使用可能でした。(環境によって変化するかもしれません)

解説

  • 仕組みや環境について詳しく知りたい人
  • エラーが出た人
  • なにかうまく行かない点がある人

上記の人向けに各ファイルについて解説していきます。

Dockefile

FROM debian:bookworm-slim

今回はX11を使っていてMesa 22を使っているdebian:bookwormをベースイメージにしました。

RUN apt-get update && \
    apt-get install -y x11-apps \
    mesa-utils \
    git \
    g++ && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

OpenGLの動作確認用にmesa-utilsを、C++環境用にg++をインストールしています。

compose.yml

user: ${USER_ID}:${GROUP_ID}

Xサーバーと通信するためには認証されたユーザーでなければならないので、UIDとGIDをコンテナ作成時に渡すようにしています。

関連するエラー

$ xeyes
Authorization required, but no authorization protocol specified

Error: Can't open display: :0

Xサーバーに接続するのに失敗しています。Docker内のUID,GIDがローカルの認証されたUID,GIDと一致しているか確認してください。

ローカルで実行
$ xhost
access control enabled, only authorized clients can connect
...:...:username
$ id username
uid=xxx(username) gid=yyy
Docker内で
$ id
uid=xxx gid=yyy

一致していない場合、docker compose up時にUSER_ID,GROUP_IDを設定していない、間違った値を設定していると思われます。記事上方の実行方法を確認し、コマンドが間違っていないか確認してください。
xhostで許可されたホストが存在しない場合xhost +si:localuser:usernameするなどして、xhostで許可する必要があります。

environment, volumes

environment:
  DISPLAY: $DISPLAY
volumes:
  - type: bind
    source: /tmp/.X11-unix
    target: /tmp/.X11-unix

ローカルのXサーバーのソケットとどのソケットに接続するかの情報をコンテナに渡しています。
ローカルのソケットを渡しているので、GUIが表示されるようになります。

コンテナの起動方法について

$ USER_ID="$(id -u)" GROUP_ID="$(id -g)" docker compose up -d

USER_IDとGROUP_IDを外部から渡して起動するようにしています。セキュリティの問題があるので、composeファイルに書くのではなく、環境変数にしています。また、環境変数名をUIDではなくUSER_IDとすることで、bashに設定されているUIDと変数名がかぶらないようにしてあります。
なお今回はUSER_ID="$(id -u)"としているので、USER_ID=$UIDと同じ意味です。

おわりに

DockerでGUIを表示するにあたって、XサーバーやUID,GIDなどLinuxがどのようにしてGUIを表示しているか理解する必要があると感じました。私も今回この記事を作成するにあたって、Linuxについてより詳しくなれたと感じました。もしこの記事に間違いがあったり、GUIが表示されないなどありましたら、コメントしてくださると助かります。

Discussion