【Mac】dockerコンテナ上でGUI有りのElectron開発環境を作成する

# はじめに
dockerコンテナ上でElectronの開発環境を構築した時の手順を残します。

環境
2020/4/28
MacOS Catalina v10.15.4

# 1. Docker上のGUIをホスト側で表示できるようにする
## 1-1. XQuartzをインストールする
docker上のGUIウィンドウを表示させるために、XQuartzをインストールします。

```
$ brew update
$ brew cask install xquartz
```

## 1-2. XQuartzの設定をする
インストールが終わったら XQuartz のアイコンをクリックし、 Macのメニューバーから
「xquartz」　→　「環境設定」　→　「セキュリティ」タブ　→　「ネットワーク・クライアントからの接続を許可」にチェックを入れて、xquartzとターミナルを再起動します。

## 1-3. XQuartzの設定を確認する
ここまでできたら、MacOS側で`echo $DISPLAY`コマンドを実行し、環境変数DISPLAYが設定されているか確認しましょう。設定されていなかった場合（何も表示されなかった場合）は一度Mac自体を再起動してもう一度確認してみましょう。

## 1-4. xhostコマンドで権限を付与する
次に、xhostコマンドでdockerにMacOS側でGUIを表示する権限を与えます。

```
$ xhost + 127.0.0.1
```
xhost設定はMacをシャットダウンすると毎回リセットされるので、`.zshrc`ファイルとかに書いてもいいかもしれません。

#2. dockerの設定
## 2-1. ディレクトリ構造
これは今回環境構築した時のディレクトリ構造です。今からの説明はこのディレクトリ構造に基づいています。自分で環境構築する際には、やりやすいように変更してください。

-app/
　├ Dockerfile
　├ docker-compose.yml
　└ src/


## 2-2. Dockerfile
**`DOCKER_UID` には、Mac側で`id`コマンドを実行して得られたuidを設定**しておきましょう。
ユーザ名、パスワードなどはお好みで設定してください。
`QT_X11_NO_MITSHM=1`を設定しておかないと、実行した時chromiumのバグによりウィンドウに何も表示されません。

```dockerfile:Dockerfile
FROM node

# install some packages to use electron
RUN apt-get update \
    && apt-get -y install libgtkextra-dev libgconf2-dev libnss3 libasound2 libxtst-dev libxss1 libgtk-3-0

RUN apt-get update \
    && apt-get install -y curl sudo

# 日本語が使えるようにする
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update \
    && apt-get install -y locales
RUN locale-gen ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LC_CTYPE ja_JP.UTF-8
RUN localedef -f UTF-8 -i ja_JP ja_JP.utf8

# install yarn
RUN curl -o- -L https://yarnpkg.com/install.sh | bash \
    && export PATH="$PATH:`yarn global bin`"

# add user
# DOCKER_UID には Mac側で id コマンドを実行して得られた uid を設定する
ARG DOCKER_UID=1000
ARG DOCKER_USER=docker
ARG DOCKER_PASSWORD=docker
RUN useradd -m -u ${DOCKER_UID} -G sudo ${DOCKER_USER} \
    && echo ${DOCKER_USER}:${DOCKER_PASSWORD} | chpasswd

# set workdir
WORKDIR /home/${DOCKER_USER}/app

# install electron
RUN yarn -D add electron

#set user
USER ${DOCKER_USER}

# not to use shared memory
ENV QT_X11_NO_MITSHM=1

```

## 2-3. docker-compose.yml
ttyをtrueにすることでdockerコンテナを起動させ続けます。
privilegedをtrueに設定しておかないとバグが発生するようです。
ホスト側でdockerのGUIが表示できるように、DISPLAY環境変数にhost.docker.internal:0を設定しましょう。
マウントするディレクトリは自分が設定したユーザ名、及び自分がやりやすいようなディレクトリ構造に合わせてください。

```docker-compose.yml
version: '3'
services: 
    app:
        build: .
        tty: true
        privileged: true
        environment:
            # use X11 forwarding
            - DISPLAY=host.docker.internal:0
        volumes:
            - ./src:/home/docker/app/src
```

以上で環境構築は終わりです。
# 3. 試す
ちゃんと設定できているか試してみましょう。
dockerコンテナを立ち上げて、コンテナ内に入ります。
ビルドにかなり長い時間がかかります。

```
$ docker-compose up -d --build
$ docker-compose exec app bash
```

electronのチュートリアルをやってみましょう。

```
$ cd ~

$ git clone https://github.com/electron/electron-quick-start

$ cd electron-quick-start

$ npm install && npm start
```

しばらく待って以下のようなウィンドウが表示されれば成功です。

<img width="821" alt="スクリーンショット 2020-04-28 6.44.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/ab7b93d4-e2d2-2544-6fc1-b75466ec4fb6.png">

自分が用意したアプリを実行する場合は、以下の手順で行ってください。

```
$ cd ~/app

$ ./node_modules/electron/dist/electron src
```

# 4. 終わりに
以上が私がdockerを利用してElectron開発環境を構築した方法です。
Electronについてはまだ環境構築しか行っていないため、もしかしたら間違っているところなどあるかも知れません。何か改善点等あれば是非ご教授ください。

# 5. 参考
* [How to show X11 windows with Docker on Mac](https://medium.com/@mreichelt/how-to-show-x11-windows-within-docker-on-mac-50759f4b65cb)
* [Docker コンテナ内でElectronの開発環境を構築する](https://zukucode.com/2019/07/docker-electron-dev.html)
* [Dockerコンテナ上で動かしたDebiannで日本語入力ができない](https://www.pgen.info/archives/1640)
* [Electron公式ページ](https://www.electronjs.org/)
* chromiumのバグについて :
https://github.com/electron/electron/issues/22775