GPUをフル活用する！DockerでChromeを音声付き・高速描画でホストPCに表示する方法

## はじめに

前回の記事では、Dockerで動作するChromeを音声サポート付きでホストPCのXサーバーに表示する方法を詳しく解説した。

https://qiita.com/rairaii/items/4e8ea4e82abd6b0ceb6e


本記事では、Docker内でGoogle ChromeをGPU有効化して動作させる方法を確認する。最初にGPUを有効にするための基本設定を行い、その効果を確認する。

## DockerでGPUを有効にする

DockerでGPUを有効にするためには、ホストマシンのGPUデバイスをコンテナ内に共有する必要がある。これを実現するために、　`--device /dev/dri`オプションを使用する。このオプションにより、コンテナ内のアプリケーションがホストのグラフィックデバイスにアクセスし、ハードウェアアクセラレーションを利用できるようになる。

### 使用するDockerfile

前回の記事で作成した`Dockerfile`を利用する。このDockerfileを使用することで、コンテナを簡単にビルドして音声サポート付きのGoogle Chromeを実行できる。

前回の記事でDockerイメージをすでに作成済みであれば[GPUを有効にしてDockerイメージを起動する](https://qiita.com/rairaii/items/398541a16dccc608fc9a#gpu%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%97%E3%81%A6docker%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B)から進めれば良い

#### Dockerfileを作成する

適当なディレクトリに`Dockerfile`を作成する

```bash
# 適当なワークディレクトリに移動
mkdir -p /tmp/test
cd /tmp/test

# 上記のDockerfileの内容をコピペして作成
vi Dockerfile
```

```Dockerfile:Dockerfile
FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive
ENV DISPLAY=:0
ENV PULSE_SERVER=unix:/run/user/1000/pulse/native

RUN apt-get update && \
    apt-get install -y wget pulseaudio socat alsa-base \
    libcanberra-gtk-module libcanberra-gtk3-module \
    fonts-ipafont-gothic fonts-ipafont-mincho fonts-noto-cjk \
    language-pack-ja dbus-x11 && \
    wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
    apt-get install -y ./google-chrome-stable_current_amd64.deb --no-install-recommends && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# D-Busの設定と起動を行うスクリプトを作成
RUN echo "#!/bin/bash\n\
/etc/init.d/dbus start\n\
export XDG_RUNTIME_DIR=/run/user/\$(id -u)\n\
mkdir -p \$XDG_RUNTIME_DIR\n\
chmod 700 \$XDG_RUNTIME_DIR\n\
chown \$(id -un):\$(id -gn) \$XDG_RUNTIME_DIR\n\
export DBUS_SESSION_BUS_ADDRESS=unix:path=\$XDG_RUNTIME_DIR/bus\n\
dbus-daemon --session --address=\$DBUS_SESSION_BUS_ADDRESS --nofork --nopidfile --syslog-only &\n\
exec \"\$@\"" > /start.sh && chmod +x /start.sh

CMD ["/start.sh", "google-chrome", "--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage"]
```

#### Dockerイメージを作成する
```bash
# chrome起動用のDockerイメージを作成
docker build -t ubuntu24_chrome .
```


### GPUを有効にしてDockerイメージを起動する

以下のコマンドを実行して、GPUを有効にした状態でUbuntu 24.04ベースのDockerコンテナを起動する。このコンテナ内でGoogle Chromeを動作させる。

```bash:ホストPCで実行
docker run -it --rm \
  --name ubuntu24 \
  --env="DISPLAY=$DISPLAY" \
  --env="PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native" \
  --volume="$HOME/.Xauthority:/root/.Xauthority:rw" \
  --volume="${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native" \
  --volume="/etc/machine-id:/etc/machine-id:ro" \
  --volume="/run/user/$(id -u)/pulse:/run/user/$(id -u)/pulse" \
  --network=host \
  --device /dev/dri \
  ubuntu24_chrome /bin/bash
```

### DockerでGPUが利用可能か確認

コンテナ内でGPUが正しく利用できるかどうかを確認する。まず、mesa-utilsをインストールし、glxinfoコマンドを使ってGPUの状態を確認する。

```bash:Docker内で実行
apt-get update
apt-get install -y mesa-utils
glxinfo | grep "OpenGL renderer"
```
実行結果として、以下のようにGPUの名前が表示される場合、GPUが有効化されていることが確認できる。

```bash: IntelのGPUが有効の場合
OpenGL renderer string: Mesa Intel(R) Graphics (RPL-S)
```

```bash: GPUが無効の場合
MESA: error: Failed to query drm device.
glx: failed to create dri3 screen
failed to load driver: iris
failed to open /dev/dri/card1: No such file or directory
failed to load driver: iris
OpenGL renderer string: llvmpipe (LLVM 17.0.6, 256 bits)
```

## GPUが無効・有効の場合

### Chromeの起動方法の違い

GPUの有効・無効に応じて、Chromeの起動方法を使い分ける。以下は、その違いを示す例である。

```bash: Chromeの起動方法の違い
# GPU無効でChromeを起動
google-chrome --no-sandbox --disable-gpu --disable-dev-shm-usage

# GPU有効でChromeを起動
google-chrome --no-sandbox  --disable-dev-shm-usage
```

必要に応じてDockerからホストPCのXサーバーに接続するために以下のコマンドをホスト側のPCで実行しておく

```bash:ホストPCで実行
xhost +
```

### Chromeのレンダリングステータスの確認


Google ChromeがGPUを使用してレンダリングしているかどうかを確認するには、`chrome://gpu`にアクセスする。以下の表は、GPU無効時と有効時のレンダリングステータスの違いを示している。


| GPU無効 | GPU有効|
|:-:|:-:|
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/e04f88d2-bd32-04e1-ca79-54dc6e62cad9.png)| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/9e954c2b-0d26-75ef-9123-fbcdc8947c0e.png)|
|ソフトウェアで描画する設定|ハードウェアアクセラレーションが有効|

### ベンチマーク

GPUの有効化によるパフォーマンスの違いを確認するために、[Spacerocks](https://webglsamples.org/spacerocks/spacerocks.html)というWebGLベンチマークを使用する。下の表は、GPUが無効な場合と有効な場合のフレームレートの違いを示している。


| GPU無効 | GPU有効|
|:-:|:-:|
|![nogpu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/1a7611a4-32c8-6475-5312-d728c81a3971.gif)|![gpu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/4c3f41b5-f6cc-a4b9-5c4d-2ad999a4abe6.gif)|
|6fps|60fps|


## まとめ

本記事では、Dockerコンテナ内でGoogle Chromeを動作させる際にGPUを有効化する方法についてまとめ。GPUを利用することで、グラフィックスのレンダリング速度が大幅に向上し、Chromeの動作が快適になる。これにより、Webアプリケーションの開発やテスト環境をより実際のユーザー環境に近い形で構築することが可能になる。


## `xhost +`を使わずに実現する方法
https://qiita.com/rairaii/items/879f5d23d96b1053417e