Docker Desktop for Windows で wine 使って Windows GUI を動かす

# これは何？

Windows10 1803 の [Docker Desktop for Windows](https://hub.docker.com/editions/community/docker-ce-desktop-windows) の docker container で Windows GUI アプリが動いた話です.

# 結論

次の組み合わせ

- [WineHQ](https://www.winehq.org/) をコンテナで動かす
- [VcXsrv](https://sourceforge.net/projects/vcxsrv/) をホストOS で動かす

# Dockerfile

使った Dockerfile です. たぶん ubuntu:latest でも動くと思います.
32bit アプリを動かすつもりなら, コメントアウトしている `ENV WINEARCH=win32` を有効にし, win32 環境を構築した方が良い

```Dockerfile:Dockerfile
FROM ubuntu:16.04

# @see https://qiita.com/fkshom/items/53de3a9b9278cd524099
RUN sed -i.bak -e "s%http://[^ ]\+%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g" /etc/apt/sources.list

RUN set -eux; \
	apt-get update \
	&& apt-get install -y --no-install-recommends \
		software-properties-common \
		apt-transport-https \
		wget \
		ca-certificates \
	&& dpkg --add-architecture i386 \
	&& wget -nc https://dl.winehq.org/wine-builds/winehq.key \
	&& apt-key add winehq.key \
	&& apt-add-repository 'https://dl.winehq.org/wine-builds/ubuntu/' \
	&& rm winehq.key \
	&& apt-get update \
	&& apt-get install -y --no-install-recommends \
		winehq-stable \
		winetricks \
	&& apt-get remove --purge -y \
		software-properties-common \
	&& apt-get autoremove -y \
	&& apt-get clean \
	&& rm -rf /var/lib/apt/lists/*

# for 32bit environment only
#ENV WINEARCH=win32

RUN set -eux; \
	apt-get update \
	&& apt-get install -y --no-install-recommends \
		xvfb \
	&& mkdir -p /root/.cache/wine \
	&& wget -P /root/.cache/wine \
		http://dl.winehq.org/wine/wine-gecko/2.47/wine_gecko-2.47-x86_64.msi \
		http://dl.winehq.org/wine/wine-gecko/2.47/wine_gecko-2.47-x86.msi \
		http://dl.winehq.org/wine/wine-mono/4.7.5/wine-mono-4.7.5.msi \
	&& xvfb-run wineboot -u \
	&& winetricks nocrashdialog win7 \
	&& xvfb-run wineboot -u \
	&& apt-get remove --purge -y \
		xvfb \
	&& apt-get autoremove -y \
	&& apt-get clean \
	&& rm -rf /var/lib/apt/lists/* /root/.cache/wine/wine*.msi
```

~~DISPLAY 環境変数を設定せずに wineboot を呼び出すと, CreateWindow のエラーが出ますが, 初期化は成功している模様です.~~
違いました。 wineboot は DISPLAY 環境変数が未設定だと途中で abort します. なので、 xvfb を使います.
また, 単に xvfb-run に GUI を捨てると wine-mono と wine_gecko の download を促す dialog が表示されてしまいます.
この問題を回避するため, あらかじめ wine-mono と wine_gecko の .msi を `.cache/wine` に配置しています. ここに .msi ファイルがあると, wineboot がキャッシュから mono と gecko を install してくれます. 

現状の Dockerfile だと, winehq-stable のバージョンが変わったら, wget の download 先を書き換える必要があり, 面倒...

# コンテナの起動

docker image を `wine:latest` で作成したとします.
下記のバッチファイルから起動すると, VcXsrv の `xhost +` と docker run の DISPLAY を設定しに行きます.
Windows10 の言語が日本語じゃなかったら, "vEthernet (既定のスイッチ)" を適宜書き換えてください.

```:launch.cmd
set ARGS=%*
set DISPLAY=127.0.0.1:0.0
"%PROGRAMFILES%\VcXsrv\xhost" +

for /f "tokens=3 usebackq" %%i in (`netsh interface ipv4 show address "vEthernet (既定のスイッチ)" ^| find "IP アドレス"`)  do @set IP=%%i
docker run -it --rm -e DISPLAY=%IP%:0.0 %ARGS% wine
```

このバッチを使用し, 次のようにコンテナを起動します.

```
launch.cmd -w /root/tmp -v "C:\hogehoge":/root/tmp
```

Dockerfile で ENTRYPOINT を wine にしていないので bash が走るのがイマイチなので適当に直してください。

# 参考にしたところ

[apt-getの利用リポジトリを日本サーバーに変更する](https://qiita.com/fkshom/items/53de3a9b9278cd524099)
[Ubuntu 18.04 / 16.04 に最新の wine をインストールする](https://sicklylife.hatenablog.com/entry/2018/09/01/004846)
[DockerからGUIアプリとWineアプリを使う方法](https://qiita.com/syui/items/b43ba220d9cd1e2fb74f)
[NETSHコマンドで取得したIPアドレスを変数に入れて判別するバッチファイルを作る方法](https://qwerty.work/blog/2018/08/netsh-get-ipaddress-batchfile.php)