はじめに
この記事ではDockerコンテナで起動するChromeブラウザをホストPC側のWaylandを使って表示する方法について確認する。
Ubuntu 24.04をはじめとする最近のLinuxディストリビューションでは、X11の代わりにWaylandがディスプレイサーバーとしてデフォルトに設定されています。また、組み込み機器においても、Waylandはその軽量性と効率性から広く利用されている。
DockerコンテナからWaylandアプリケーションをホストPCに直接表示するためには、ホストPCのWaylandディスプレイサーバにコンテナ内のアプリケーションがアクセスできるように設定する必要があります。まずは、シンプルなテスト環境を構築し、WaylandアプリをホストPCで表示させることを確認します。最後に、ChromeブラウザをホストPCで表示させる。
動作環境
項目 | ホストPC | Dockerコンテナ |
---|---|---|
OS | Ubuntu 24.04 | Ubuntu 24.04 |
ディスプレイサーバー | Wayland | n/a |
Waylandをディスプレイサーバーとして選択し、Ubuntuにログインする方法は、下記が詳しい。
WaylandアプリをホストPCで表示する
Waylandがディスプレイサーバーとして動作するUbuntu24.04などの環境をホスト側に用意しているものとして進める。
ホストPCの準備
XDG_RUNTIME_DIRの確認
ホストPCでXDG_RUNTIME_DIR
が正しく設定されているか確認する。
echo $XDG_RUNTIME_DIR
通常、Ubuntuではこのディレクトリは /run/user/$(id -u)
だ。
Wayland環境の確認
ホストPCがWaylandセッションで動作していることを確認します。Ubuntu24.04であれば、Gnomeを使っている場合、デフォルトでWaylandが使われている。
ホストPCでXDG_SESSION_TYPE
がwayland
であることを確認する
echo $XDG_SESSION_TYPE
wayland
と出力されるか確認する。x11
と表示された場合にはログイン時にX11が利用されている。
GPUの確認
ホストPCのGPUを確認する
lspci -v | grep -i --color 'vga\|3d\|2d'
GPUとしてIntel Chipが認識されている
00:02.0 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04) (prog-if 00 [VGA controller])
Dockerの用意
ホストPCにDockerがインストールされていることを確認する。インストールされていない場合は下記のコマンドでインストールする。
sudo apt-get update
sudo apt-get install docker.io
Waylandソケットの確認
Waylandは/run/user/$(id -u)/wayland-0
にソケットを作成する。このソケットにコンテナからアクセスできるようにする。
file /run/user/$(id -u)/wayland-0
/run/user/1000/wayland-0: socket
のようにWaylandソケットの存在が確認できる
Dockerコンテナの設定
Waylandソケットのマウント
コンテナ内からホストのWaylandソケットにアクセスできるように、ソケットをボリュームとしてマウントする。また、Dockerコンテナで XDG_RUNTIME_DIR
をホストPCと同じ値に設定する。
例えば、docker run
コマンドに以下のオプションを追加する。
-v /run/user/$(id -u)/wayland-0:/run/user/$(id -u)/wayland-0:rw \
-e WAYLAND_DISPLAY=wayland-0 \
-e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
WaylandのソケットをマウントしてDocker側からも利用するためにコンテナ内ユーザーのUID/GIDをホストPC側のUID/GIDと揃える必要がある
Wayland対応アプリケーションのインストール
テスト用のWayland対応アプリケーションをコンテナ内にインストールする。weston-terminal
をここではインストールする。
下記のようなDockerfile
を適当なディレクトリに作成する。
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
weston \
&& rm -rf /var/lib/apt/lists/*
Dockerイメージのビルド
wayland-testと名前をつけてDockerイメージを作成する
docker build -t wayland-test .
テスト環境の構築と実行
Dockerコンテナの起動
コンテナ内ユーザーのUID/GIDをホストPC側と揃えて、ホストのWaylandソケットをマウントしコンテナを起動する。
docker run -it \
--user $(id -u):$(id -g) \
-v /run/user/$(id -u)/wayland-0:/run/user/$(id -u)/wayland-0:rw \
-e WAYLAND_DISPLAY=wayland-0 \
-e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--name wayland-test-container \
wayland-test /bin/bash
アプリケーションの実行
コンテナ内でweston-terminal
を実行する。
weston-terminal
表示確認
成功の場合にはweston-terminal
がホストPCのWaylandセッションに表示される。
failed to connect to Wayland display: Connection refused
failed to create display: Connection refused
トラブルシューティング
表示されない場合
コンテナがホストPCのWaylandソケットに正しくアクセスできているか、ソケットのパスとWAYLAND_DISPLAY
変数が正しいかを再確認する。
権限の問題
Waylandソケットにアクセスするため、ホストPCのユーザーIDと同じUIDをDockerコンテナに設定する必要がある。これは、--user $(id -u):$(id -g)
オプションで設定する。
ChromeブラウザをホストPCに表示する
ホストPCがX11の場合との違い
dbus
X11を使用する場合、dbus-x11パッケージをインストールする必要がある。X11環境で動作するDBusセッションバスを提供するためだったが、Waylandでは通常のdbusパッケージで良い。
Chromeの起動方法
Waylandでは--ozone-platform-hint=wayland
オプションを使ってChromeにWaylandを使用するよう指示する。また--enable-wayland-ime
を追加することでWayland上で日本語入力メソッド(IME)のサポートを有効にする。
Dockerfile
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# 必要なパッケージをインストール
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 && \
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 install -y weston mesa-utils sudo &&\
apt-get clean && rm -rf /var/lib/apt/lists/*
RUN echo "#!/bin/bash\n\
set -e\n\
sudo /etc/init.d/dbus start || { echo 'Failed to start dbus'; exit 1; }\n\
export XDG_RUNTIME_DIR=/run/user/\$(id -u)\n\
sudo mkdir -p \$XDG_RUNTIME_DIR || { echo 'Failed to create XDG_RUNTIME_DIR'; exit 1; }\n\
sudo chmod 700 \$XDG_RUNTIME_DIR || { echo 'Failed to chmod XDG_RUNTIME_DIR'; exit 1; }\n\
sudo chown \$(id -un):\$(id -gn) \$XDG_RUNTIME_DIR || { echo 'Failed to chown XDG_RUNTIME_DIR'; exit 1; }\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
# ホストのUIDとGIDを利用してユーザーを作成する
ARG USER_ID
ARG GROUP_ID
# 既存のグループを確認して、なければ作成
RUN if ! getent group $GROUP_ID >/dev/null; then \
groupadd -g $GROUP_ID hostgroup; \
fi
# 既存のUIDに対応するユーザーがいない場合、新規ユーザーを作成して、PWなしでsudoを許可
RUN USER_NAME=$(getent passwd $USER_ID | cut -d: -f1) && \
if [ -z "$USER_NAME" ]; then \
USER_NAME="hostuser"; \
useradd -u $USER_ID -g $GROUP_ID -m $USER_NAME; \
fi && \
echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# google-chrome を $USER_ID で実行
USER $USER_ID
CMD ["/start.sh", "google-chrome", "--disable-dev-shm-usage", " --ozone-platform-hint=wayland", "--enable-wayland-ime"]
Dockerイメージを作成
ホストPCで利用しているUIDとGIDを指定してubuntu24_waychrome
という名前をつけてDockerイメージを作成する。
docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t ubuntu24_waychrome .
Dockerコンテナを起動
docker run -it --rm \
--name ubuntu24_waychrome \
-v /run/user/$(id -u)/wayland-0:/run/user/$(id -u)/wayland-0:rw \
-e WAYLAND_DISPLAY=wayland-0 \
-e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--env="PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native" \
--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 \
--cap-add=SYS_ADMIN --security-opt seccomp=unconfined \
ubuntu24_waychrome
Chromeの表示確認
YoutubeでBig Buck Bunnyが音声つきで再生できた。
chrome://version
でChromeのバージョンと起動オプションを確認する
chrome://gpu
でWaylandを利用が確認できる
chrome://gpu
でハードウェアアクセラレーションがEnable有効であることが(but at reduced performance:しかしパフォーマンスは落ちている)確認できる
ハードウェアアクセラーションの問題
DockerコンテナからChromeブラウザを起動すると下記のようにlibEGL
のwarning
が表示されている。/dev/dri/renderD128
へのアクセス権限がない問題の解決が必要そうだ。
* Starting system message bus dbus [ OK ]
libEGL warning: failed to open /dev/dri/renderD128: Permission denied
libEGL warning: failed to open /dev/dri/renderD128: Permission denied
ハードウェアアクセラレーションの解決
Dockerイメージを/bin/bash
付きで起動して/dev/dri/renderD128
を確認する。
docker run -it --rm \
--name ubuntu24_waychrome \
-v /run/user/$(id -u)/wayland-0:/run/user/$(id -u)/wayland-0:rw \
-e WAYLAND_DISPLAY=wayland-0 \
-e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--env="PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native" \
--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 \
--cap-add=SYS_ADMIN --security-opt seccomp=unconfined \
ubuntu24_waychrome /bin/bash
ls -la /dev/dri/renderD128
crw-rw---- 1 root systemd-resolve 226, 128 Aug 18 06:49 /dev/dri/renderD128
エラーはコンテナ内のChromeがWaylandディスプレイサーバーに接続しようとしたときに、/dev/dri/renderD128
デバイスファイルにアクセスする権限が不足している。Chromeを起動するユーザーがsystemd-resolve
に所属している必要がある。
Dockerfileの修正
usermod -aG systemd-resolve $USER_NAME
でsystemd-resolve
のグループにユーザを追加することで/dev/dri/renderD128
へのアクセス権を追加する
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# 必要なパッケージをインストール
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 && \
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 install -y weston mesa-utils sudo &&\
apt-get clean && rm -rf /var/lib/apt/lists/*
RUN echo "#!/bin/bash\n\
set -e\n\
sudo /etc/init.d/dbus start || { echo 'Failed to start dbus'; exit 1; }\n\
export XDG_RUNTIME_DIR=/run/user/\$(id -u)\n\
sudo mkdir -p \$XDG_RUNTIME_DIR || { echo 'Failed to create XDG_RUNTIME_DIR'; exit 1; }\n\
sudo chmod 700 \$XDG_RUNTIME_DIR || { echo 'Failed to chmod XDG_RUNTIME_DIR'; exit 1; }\n\
sudo chown \$(id -un):\$(id -gn) \$XDG_RUNTIME_DIR || { echo 'Failed to chown XDG_RUNTIME_DIR'; exit 1; }\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
# ホストのUIDとGIDを利用してユーザーを作成する
ARG USER_ID
ARG GROUP_ID
# 既存のグループを確認して、なければ作成
RUN if ! getent group $GROUP_ID >/dev/null; then \
groupadd -g $GROUP_ID hostgroup; \
fi
# 既存のUIDに対応するユーザーがいない場合、新規ユーザーを作成して、PWなしでsudoを許可
RUN USER_NAME=$(getent passwd $USER_ID | cut -d: -f1) && \
if [ -z "$USER_NAME" ]; then \
USER_NAME="hostuser"; \
useradd -u $USER_ID -g $GROUP_ID -m $USER_NAME; \
fi && \
echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \
# /dev/dri/renderD128にアクセス権を追加
usermod -aG systemd-resolve $USER_NAME
# google-chrome を $USER_ID で実行
USER $USER_ID
CMD ["/start.sh", "google-chrome", "--disable-dev-shm-usage", " --ozone-platform-hint=wayland", "--enable-wayland-ime"]
Chromeの表示確認
修正したDockerファイルで作成したDockerイメージからコンテナを起動する。chrome://gpu
の出力はGPUのハードウェアアクセラレーションに制限がないことを示している。
WebGLのベンチマークのSpace Rocksでテストすると、たまに60fpsを切る場合もあるが、ほぼ60fpsをキープして表示される
蛇足
Wayland環境でスクリーンショットを撮りたい場合
sudo apt-get install gnome-screenshot
メニューからGUIアプリを起動可能