【Docker for Windows】コンテナ上のChromiumのウインドウとサウンドをホストOSへ転送してみた

# やったこと
Docker for Windows上のコンテナでChromiumを起動させ、ChromiumのウインドウとサウンドをホストOSであるWindows 10へ転送しました。

コンテナ上のChromiumからウインドウ、サウンドをそれぞれ以下の手法で転送しました。

- ウインドウの転送
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/ea3ab906-9221-a48f-52dd-1c1c7d8648ed.png)　　　**X Window System(X11)**

- サウンドの転送
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/226e26af-7441-de21-20c8-7e019d8c8710.png)　　　**PulseAudio**

## 概念図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/be03ccfd-3279-5e63-fcb1-780b5f239a1e.png)

## 動作環境
- Windows 10 Pro version 1803, build 17134.706
- Docker Desktop version 2.0.0.3 (31259), build: 8858db3
- Docker Engine version 18.09.2, build 6247962

# やり方
## 1.　ホストOS（Windows 10）側での準備
### 1.1.　X11 Server の導入
#### 1.1.1.　X11 Server のインストール
　　コンテナ上のウインドウを受信するため、Windows 10にX11 Serverをインストールします。
　　ここでは、X11 ServerとしてVcXsrvを使用します。インストールに当たり、参考にさせて頂きましたサイトを掲載します。(丸投げのような形で申し訳ございません)

- [VcXsrvのダウンロードサイト](https://sourceforge.net/projects/vcxsrv/)
- [VcXsrvのインストール時に参考にしたサイト「WSL上にXサーバをインストールしてGUIを実現する（VcXsrv編）」](https://www.atmarkit.co.jp/ait/articles/1812/06/news040.html)

#### 1.1.2.　X11 Server の起動
　　デスクトップ上の「XLaunch」から、VcXsrvを起動します。（全て[次へ]を選択し、[完了]を押せばOKです）
　　タスクトレイにVcXsrvのアイコンが表示されていれば、起動しています。
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/215549f6-623d-65d2-3d60-cd2d2b44ae06.png)

### 1.2.　PulseAudio for Windowsの導入
#### 1.2.1.　PulseAudio for Windows のインストール
　　[PulseAudio on Windowsのダウンロードサイト](https://www.freedesktop.org/wiki/Software/PulseAudio/Ports/Windows/Support/)から「zipfile containing preview binaries」を選択して、zipファイルをダウンロードし、任意に場所へ解凍します。

#### 1.2.2.　PulseAudio for Windows の設定
- 「etc\pulse\default.pa」の編集

| 42行目       |       設定 |    
|:-----------------|------------------:|
| 変更前            |              load-module module-waveout sink_name=output source_name=input |
| 変更後           |            load-module module-waveout sink_name=output source_name=input **record=0** |

| 61行目       |       設定 |    
|:-----------------|------------------:|
| 変更前            |              **#**load-module module-native-protocol-tcp |
| 変更後           |            load-module module-native-protocol-tcp **auth-ip-acl=127.0.0.1** |

- 「etc\pulse\daemon.conf」の編集

| 39行目       |       設定 |    
|:-----------------|------------------:|
| 変更前            |              **;** exit-idle-time = 20 |
| 変更後           |            exit-idle-time = **-1** |

#### 1.2.3.　PulseAudio for Windows の起動

　　解凍した「pulseaudio-1.1」フォルダと同階層に以下のバッチファイルを配置して、実行します。

```bat:pulseaudio.bat
@echo off

cd /d %~dp0

powershell -NoProfile -Command Start-Process -WindowStyle Minimized '.\pulseaudio-1.1\bin\pulseaudio.exe'
```
　　以下のようなコマンドプロンプトが表示されていれば、起動しています。（「Ctrl+C」で停止できます）
　　**※Windows Firewallから許可を求められた場合は、許可をしてください。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/137bfbac-76c5-5e8f-33bd-f16a5d9c71e3.png)


## 2. Dockerイメージの作成
## 2.1.　X11 の環境設定
　Dockerfile内で環境変数 DISPLAYを以下のように設定します。

```Dockerfile
ENV DISPLAY=host.docker.internal:0.0
```

## 2.2.　Pulseaudio の環境設定
　Dockerfile内で環境変数 PULSE_SERVERを以下のように設定します。

```Dockerfile
ENV PULSE_SERVER=tcp:host.docker.internal:4713
```
　また、ALSAのdefaultサウンドカードとして、PulseAudio（仮想サウンドカード）を登録します。

```shell
{ \
echo "pcm.default pulse"; \
echo "ctl.default pulse"; \
} | tee ~chrome/.asoundrc \
&& chown -R chrome:chrome /home/chrome
```

## 2.3　Dockerfileサンプル
 [zenika/alpine-chrome](https://hub.docker.com/r/zenika/alpine-chrome/)をベースに以下のDockerfileを作成しました。

```Dockerfile:Dockerfile
# Credit goes to Zenika (https://github.com/Zenika/alpine-chrome/blob/master/Dockerfile) 
FROM alpine:latest

# Installs latest Chromium package.
RUN echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
    && apk add --no-cache \
    chromium@edge \
    harfbuzz@edge \
    nss@edge \
    freetype@edge \
    ttf-freefont@edge \
    mesa-gl \
    pulseaudio \
    pulseaudio-libs \
    alsa-plugins-pulse@edge \
    bash \
    && wget https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip \
    && mkdir -p /usr/share/fonts/NotoSansCJKjp \
    && unzip NotoSansCJKjp-hinted.zip -d /usr/share/fonts/NotoSansCJKjp/ \
    && chmod 644 /usr/share/fonts/NotoSansCJKjp/*.otf \
    && rm NotoSansCJKjp-hinted.zip \
    && fc-cache -fv

# Add user so we don't need --no-sandbox. 
RUN addgroup -S chrome \
    && adduser -S -G chrome chrome \
    && mkdir -p /home/chrome/Downloads \
    && { \
    echo "pcm.default pulse"; \
    echo "ctl.default pulse"; \
    } | tee /home/chrome/.asoundrc \
    && chown -R chrome:chrome /home/chrome

# Run Chrome as non-privileged
USER chrome
WORKDIR /home/chrome

ENV CHROME_BIN=/usr/bin/chromium-browser
ENV CHROME_PATH=/usr/lib/chromium/
ENV DISPLAY=host.docker.internal:0.0
ENV PULSE_SERVER=tcp:host.docker.internal:4713

# Autorun chrome
ENTRYPOINT ["chromium-browser", "--disable-gpu", "--disable-software-rasterizer", "--disable-dev-shm-usage"]
``` 

## 2.4　ビルド

```shell
docker build -t speaktech/secure-browser:1.0 .
```

## 3. コンテナの実行
　[zenika/alpine-chrome](https://hub.docker.com/r/zenika/alpine-chrome/)の手引きに従い、限られた権限でChromiumのsandobox機能を利用するためにseccompプロファイル（[chrome.json](https://raw.githubusercontent.com/jfrazelle/dotfiles/master/etc/docker/seccomp/chrome.json)）を利用します。


```shell
Invoke-WebRequest -Uri https://raw.githubusercontent.com/jfrazelle/dotfiles/master/etc/docker/seccomp/chrome.json -OutFile chrome.json

docker run -it --rm --security-opt seccomp=$(pwd)/chrome.json speaktech/secure-browser:1.0
```

コンテナを実行すると、Windows 10上でChromiumが起動します。Youtubeなどで音声がWindows 10へ転送されることを確認できれば、完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/59ebefa5-ce7d-05fc-f9ba-6435e13aa239.png)



# 4.　最後に、なぜやろうと思ったのか？
　インターネットへのアクセスをコンテナに実行させることで、セキュアなブラウザ環境ができるのでは？と思い、やってみました。
　ブラウザを閉じる度にコンテナごと削除するので、ウイルス感染後の情報漏洩等のリスクが低くなります。
　また、Windows Firewallを利用して、コンテナからの通信をウインドウ/サウンドの転送のみに絞ることで、ホストOSのウイルス感染リスクを軽減できると考えます。

　難点としては、ウインドウとサウンドを非同期に転送している関係上若干音ズレします。(**私個人としては、**許容範囲内です)
　
　「これで、より安心に、いろいろなサイトを閲覧できる気がします」という意味深な感想で締めさせていただきます。
　最後までご拝読いただきまして、ありがとうございました。