vscodeのdevcontainer内でelectronのGUIアプリを作りたかった

vscoderemote-containerelectronのGUIアプリを作る環境を整える。

remote-containerdevcontainerとも呼ぶ。(勝手に呼んでいる)

結論から言うと次の2点で実用には遠いと感じた。

  • 日本語が文字化けする。
  • Electronアプリから他のアプリを起動できない。

1つ目は解決できるかもしれないが、2つ目は許容できない問題だ。 Electronアプリからブラウザを起動するのはよくあることなので、これができないと、かなり使いづらくなってしまう。もしかしたら解決できるのかもしれないが、再び問題にぶち当たりそうで探したくない。

環境構築については、一応まとめておこうと思ってここに残すことにした。

まずはコンテナの作成

すでに、Electronアプリがある前提で進める。なくても、構築後にチュートリアルアプリでもpullしてくれば問題ないと思う。

remote-containerは準備が必要だったと思うので、準備する。ms-vscode-remote.remote-containersのエクステンションをローカルのvscodeに入れておけば、vscodeを起動した時に、ウィンドウの左下に新しいアイコンが表示されているのが確認できると思う。

アプリがあるディレクトリでcode .してvscodeを起動して、左下のアイコンを押して、Open folder in containerをクリックすれば、指定したフォルダをDockerコンテナで開ける。 今回はElectronアプリなので、Node.js 12のイメージをコンテナに利用した。

またこの時、自動的に.devcontainerフォルダが作成され、中に2つのファイルが作成される。devcontainer.jsonDockerfileの2つ。

remote-containerの設定はこの2つのファイルをいじればいい。

コンテナの設定

まずは、Dockerfileから。以下のような設定をする。

#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------

# To fully customize the contents of this image, use the following Dockerfile instead:
# https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/javascript-node-12/.devcontainer/Dockerfile
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-12

# ** [Optional] Uncomment this section to install additional packages. **
#
ENV DEBIAN_FRONTEND=noninteractive
# Electronが使うパッケージなどをセットアップ
RUN apt-get update \
   && apt-get -y install --no-install-recommends libgtkextra-dev libgconf2-dev libnss3 libasound2 libxtst-dev libxss1 libgtk-3-0 \
   #
   # Clean up
   && apt-get autoremove -y \
   && apt-get clean -y \
   && rm -rf /var/lib/apt/lists/*
# ENV DEBIAN_FRONTEND=dialog

# not to use shared memory
ENV QT_X11_NO_MITSHM=1

# settings to use Japanese
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

# DISPLAYの設定を忘れずに
ENV DISPLAY=host.docker.internal:0

ほぼこちらを参考にした: 【Mac】dockerコンテナ上でGUI有りのElectron開発環境を作成する - Qiita

日本語の設定をしてもElectronアプリ中の日本語は文字化けしてしまっていた。

次に、devcontainer.jsonの方。

// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/javascript-node-12
{
    "name": "Node.js 12",
    "dockerFile": "Dockerfile",
    // Set *default* container specific settings.json values on container create.
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash"
    },
    // Add the IDs of extensions you want installed when the container is created.
    "extensions": [
        "dbaeumer.vscode-eslint",
        "spadin.remote-x11"  // 役に立つのかわよくわからない
    ],
    // Xサーバ(ホスト側)のソケットをDockerコンテナ側にマウントする。
    "mounts": [
        "source=/tmp/.X11-unix/,target=/tmp/.X11-unix/,type=bind,consistency=cached"
    ],
    // --privilegedがないとエラーが出る。
    "runArgs": [
        "--privileged"
    ],
    // Use 'forwardPorts' to make a list of ports inside the container available locally.
    // "forwardPorts": [],
    // Use 'postCreateCommand' to run commands after the container is created.
    // "postCreateCommand": "yarn install",
    // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
    "remoteUser": "node"  // rootだと`--no-sandbox`オプションが必要と言われる。
}

注意すべきは、mountsrunArgsremote-userだろう。基本的にはdocker runなどで指定するものと同じ。行頭のformat detailsを見ればよくわかる。

mountsはホスト側のXサーバのドメインソケットを確認して、それをコンテナにマウントすればいい。

runArgsはまさにdocker runで指定するオプションと同じ。--privilegedは特権を持たせる。これを付与しないと、

The setuid sandbox is not running as root. Common causes:
  * An unprivileged process using ptrace on it, like a debugger.
  * A parent process set prctl(PR_SET_NO_NEW_PRIVS, ...)
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted

このようなエラーが表示される。

remoteUserは上のコメントにもあるように、rootでElectronアプリを実行すると、--no-sandboxオプション無しのルート実行はサポートしていない。のようなメッセージが表示されてしまうため。

次にすることは、コンテナ側のproj_root/node_modules/electron/dist/chrome-sandboxに権限の設定を行うこと、(もしかすると、不要かもしれない) このファイルは、root所有で4755権限じゃないといけないよ、的なエラーが出た気がする。なので、

chown root node_modules/electron/dist/chrome-sandbox
chmod 4755 node_modules/electron/dist/chrome-sandbox

をリモートコンテナのシェルで行う。

上のようなコンテナ設定が済んだら、ホスト側、つまりXサーバ側での設定を行う。(別に逆順でもいい)

Xサーバ(ホスト側)の設定

自環境はmacosなので、XサーバとしてはXQuartzを使用した。imgをダウンロードしたり、homebrew caskでインストールできたりする。

インストールして、ログインアウトすれば、DISPLAY環境変数が勝手に設定される。

次にxhostコマンドでクライアント(コンテナ)のアクセスコントロールを設定する。

ソケットを渡しているので、実質自分(ホスト)となる。なので、

$ xhost +127.0.0.1
$ xhost # これで確認可能

を行なっておけばいい。

起動確認

Xウィンドウシステムの確認だけなら、vscodeのターミナル(リモートコンテナのシェル)で。

$ apt update && apt install -y x11-apps
...
$ xcalc

などで、確認できる。

Electronアプリの確認は、普通に、yarn startなどで起動すればいい。

エラーが発生する場合は、エラーメッセージをそのまま(ある程度短くして)検索エンジンに投げればいい。(丸投げ)

あとがき

ローカル環境を汚さないというメリットがあるが、GUIアプリのためにここまでするのはちょっと面倒。外部ブラウザとの連携も面倒というか起動しないので、この点は全く頼りにできない。

日本語問題はなんとかできるのかもしれないが、上の問題のせいで解決する気も無くしてしまった。

また気が向いたときにでも解決に取り組んでみようかと思う。

以上です。

タイトルとURLをコピーしました