ChromeブラウザをDockerで動作させる時のエラー対策 (ホストがMacの場合)

# はじめに

DockerのコンテナでChromeブラウザを実行させた場合に複数の不具合ログが出力される。特にD-BusとALSAに関連したエラーが一般的である。今回はこれらのエラーに対する対策方法をまとめた。Dockerコンテナ内でのChromeブラウザの安定した実行を目指し、必要な設定変更やオプションの調整方法について解説する。

# DockerのコンテナでChromeブラウザを実行する

できるだけ簡単に話を進めるため、VNC経由でウェブブラウザを起動が確認でき、かつ通常のDockerでは動作させられないD-Busが動作可能なdockerイメージ`akarita/docker-ubuntu-desktop`を用いる。[Utuntu22.04のデクトップ版のイメージ](https://qiita.com/takahashiakari/items/f096e5bcdfecf3d5ba90)である。
以下のコマンドは、Linux AMD64プラットフォーム上でUbuntuデスクトップ環境を含むDockerコンテナを起動し、PulseAudioサーバーへの接続設定を行う例である。この設定により、コンテナ内のアプリケーションはホストマシンのオーディオ出力を利用できるようになる。

```terminal:mac　terminal
$ docker run -it --platform=linux/amd64 -p 6080:6080 -e PULSE_SERVER="tcp:host.docker.internal:4713"　-v　~/.config/pulse:/root/.config/pulse --network-address akarita/docker-ubuntu-desktop
```

次に、コンテナ内にChromeブラウザをインストールする。以下の手順に従い、Chromeブラウザのデバイアンパッケージをダウンロードし、インストールを行う。

起動したコンテナでChromeブラウザをインストールする
```terminal:docker terminal
$ cd ~
$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
$ apt-get update
$ apt-get -y install ./google-chrome-stable_current_amd64.deb
```

インストール後、Chromeブラウザを特定のオプションを付けて起動する。--no-sandbox オプションはセキュリティのサンドボックス機能を無効にし、--disable-gpu はGPUによる加速をオフにする。これらのオプションは、コンテナ内でのChromeの安定稼働を目指し、実行時のエラーを最小限に抑える。

ホストのMacでsafariを起動してvnc経由でコンテナのGUI画面を表示する。

```terminal: mac
open -a safari.app http://localhost:6080/vnc.html
```

Terminalアイコンを選択しTerminalを立ち上げ、そこからChromeブラウザを実行する。

```terminal: VNC terminal
$ google-chrome --no-sandbox --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage
```

![スクリーンショット 2024-02-17 21.34.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/34870efc-ac79-8c6e-f445-d28c483c0d16.png)


# 実行時エラー対策

google-chromeをDockerで動作させた際には、多数のエラーログが表示される。これらの不具合はユーザーの体験を損なう可能性があり、適切な修正方法を知ることが重要である。本稿では、特にD-BusとALSAに関連したエラーに焦点を当て、それらの修正方法について検討する。

## D-Bus関連の不具合

Dockerのコンテナでgoogle-chromeを起動した場合に発生するD-Bus関連のエラーログは、アプリケーションがシステムバスに接続できないことに起因する。D-Busはアプリケーション間の通信を仲介するデーモンであり、これが正常に動作しないと、アプリケーションは期待通りに機能しない。

```terminal:ERRORの例
[685:710:0217/101309.067174:ERROR:bus.cc(407)] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[685:706:0217/101309.099874:ERROR:bus.cc(407)] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
```

これらのエラーは、D-Busが動作可能な形のdockerイメージを使用し、適切なコマンドを実行することで発生を抑えられる。具体的には、以下の手順でD-Busデーモンを起動し、その状態を確認する。
[wsl2の修正方法](https://github.com/microsoft/WSL/issues/7915)を参考とした。

:::note info
XDG_RUNTIME_DIRとDBUS_SESSION_BUS_ADDRESSの値を設定し、XDG_RUNTIME_DIRにディレクトリを作成してからdbus-daemonを起動する。
:::
```terminal: docker terminal
$ /etc/init.d/dbus start
$ /etc/init.d/dbus status
$ export XDG_RUNTIME_DIR=/run/user/$(id -u)
$ echo $XDG_RUNTIME_DIR
/run/user/0
$ export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
$ echo $DBUS_SESSION_BUS_ADDRESS
unix:path=/run/user/0/bus
$ mkdir $XDG_RUNTIME_DIR
$ chmod 700 $XDG_RUNTIME_DIR
$ chown $(id -un):$(id -gn) $XDG_RUNTIME_DIR
$ dbus-daemon --session --address=$DBUS_SESSION_BUS_ADDRESS --nofork --nopidfile --syslog-only &
```


## ALSA関連の不具合

オーディオ出力に関する不具合は、Dockerコンテナからホストマシンのオーディオシステムにアクセスする設定が不足していることが原因である。Dockerのホスト側でPulseaudioのサービスを動作させ、コンテナからそのサービスに接続することで、音を鳴らすことができるようになる。

### ホスト側でPulseaudioサービスを実行

まず、ホストマシンにPulseaudioをインストールする。

```terminal:mac terminal
$ brew install pulseaudio
```

次に、Pulseaudioの設定を修正し、DockerコンテナからTCP接続できるようにする。

```terminal:mac terminal
sudo vi /opt/homebrew/etc/pulse/default.pa
```
設定ファイルには、以下のように記述する。

```config:/opt/homebrew/etc/pulse/default.pa
### Network access (may be configured with paprefs, so leave this commented
### here if you plan to use paprefs)
#load-module module-esound-protocol-tcp
load-module module-esound-protocol-tcp
#load-module module-native-protocol-tcp auth=anonymous=1
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1
```

```terminal:mac terminal
$ brew services start pulseaudio
```

Pulseaudioの出力先リストを表示させ選択する
```terminal:出力先として#1を選択する例
$ pactl list sinks
シンク #0
	状態: SUSPENDED
	名前: Channel_1__Channel_2
	説明: VC34102UWQHD
	ドライバー: module-coreaudio-device.c
	サンプル仕様: float32le 2ch 48000Hz
	チャンネルマップ: front-left,front-right
	所有者モジュール: 21
	ミュート: いいえ
	ボリューム: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        バランス 0.00
	ベースボリューム: 65536 / 100% / 0.00 dB
	モニターソース: Channel_1__Channel_2.monitor
	待機時間: 0 usec, configured 0 usec
	フラグ: HARDWARE DECIBEL_VOLUME LATENCY
	プロパティー:
		device.string = "VC34102UWQHD"
		device.product.name = "VC34102UWQHD"
		device.description = "VC34102UWQHD"
		device.access_mode = "mmap"
		device.class = "sound"
		device.api = "CoreAudio"
		device.buffering.buffer_size = "4096"
		device.vendor.name = "JNX"
		device.icon_name = "audio-card"
	形式:
		pcm
シンク #1
	状態: SUSPENDED
	名前: 1__2
	説明: MacBook Proのスピーカー
	ドライバー: module-coreaudio-device.c
	サンプル仕様: float32le 2ch 48000Hz
	チャンネルマップ: front-left,front-right
	所有者モジュール: 8
	ミュート: いいえ
	ボリューム: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        バランス 0.00
	ベースボリューム: 65536 / 100% / 0.00 dB
	モニターソース: 1__2.monitor
	待機時間: 0 usec, configured 0 usec
	フラグ: HARDWARE DECIBEL_VOLUME LATENCY
	プロパティー:
		device.string = "MacBook Proのスピーカー"
		device.product.name = "MacBook Proのスピーカー"
		device.description = "MacBook Proのスピーカー"
		device.access_mode = "mmap"
		device.class = "sound"
		device.api = "CoreAudio"
		device.buffering.buffer_size = "4096"
		device.vendor.name = "Apple Inc."
		device.icon_name = "audio-card"
	形式:
		pcm
$ pactl set-default-sink 1
```

:::note info
Pulseaudioサービスを終了する場合
```terminal: mac terminal
$ brew services stop pulseaudio
```
:::

### コンテナ側からホスト側で動作しているPulseaudioサービスに接続する

Pulseaudioに必要なパッケージをインストールして必要な設定を行う

```terminal:docker terminal
$ apt install -y pulseaudio socat alsa-base
$ { echo "pcm.default pulse"; echo "ctl.default pulse"; } | tee ~/.asoundrc
$ export PULSE_SERVER=tcp:host.docker.internal:4713
```

サンプルファイルで音声再生の確認をする

```terminal:docker terminal
$ cd ~
$ wget https://freewavesamples.com/files/1980s-Casio-Piano-C5.wav
$ aplay 1980s-Casio-Piano-C5.wav
```

音が鳴れば成功だ。

最後にブラウザを起動する。ホスト側のウェブブラウザで`http://localhost:6080/vnc.html`にアクセスしてChromeブラウザを起動させる。対策によりエラーの数が減っていることがわかる。[YouTube](https://www.youtube.com)にアクセスして動画を再生すれば音声もホスト側から再生される。

```terminal: VNC terminal
$ export PULSE_SERVER=tcp:host.docker.internal:4713
$ google-chrome --no-sandbox --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage
```

![スクリーンショット 2024-02-17 21.34.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/c6cbe923-eaef-226a-db80-6ab0a3cd5096.png)