WindowsのDocker環境でRust GUIアプリを動かす

## やりたいこと

- RustでGUIアプリ開発をしたい
- 手元にはWindowsマシンしかない

[Windows10のWSL（WSLg）でGUIアプリが動くようになった](https://qiita.com/y-tsutsu/items/6bc65c0ce4d20a82a417)（投稿日 2022年11月26日）

とのことなので、**WindowsのDocker Desktop環境でRustのGUIアプリを動かす**

### この記事の内容

1. まずはWSL2のdockerでGUIが動かせるか確認する（Rustは関係ない）
2. Rust GUIのライブラリ [gtk-rs](https://gtk-rs.org/) を使って、Rust製GUIアプリを動かす

:::note info
GTKは画像編集で有名なGIMPの実装のために作られたツールキットらしい
※GTK = The GIMP Toolkit
:::

## 前提条件

- OSは Windows 11 Home 22H2
- Ubuntu on WIndows がインストールされている
- Docker Desktop がインストールされている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/3ca9bc17-d6cc-a414-e99d-f712cb71d451.png)

## Ubuntu on Windows でGUIアプリを起動する

まずはRustとは関係なしに、そもそもWLS2からLinux GUIアプリを起動することができるか確認する

Microsoftのドキュメントが参考になる
[Linux 用 Windows サブシステムで Linux GUI アプリを実行する](https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/gui-apps)

1. コマンドプロンプトを開いて`ubuntu`と入力する
1. 入力待ちの部分が `root@{pcname}`になったら、以下のコマンドを実行する

```bash
sudo apt install gedit -y
gedit
```
以下のようなテキストエディタが表示されれば成功です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/db512393-af5b-b165-5da0-e6b5d3d97c01.png)

## WSL2のDockerでGUIアプリを起動する

次に、WLS2からdockerコンテナを起動してGUIアプリが起動するか確認する

1. 先ほどと同様に、コマンドプロンプトを開いて`ubuntu`と入力する
1. 任意のフォルダに`Dockerfile`を作成する
1. そのフォルダで`gedit Dockerfile`
1. 「[DockerGuiTest/notCompose/ 内で、コマンドを実行](https://github.com/rayfiyo/dockerGuiTest#%E6%96%B9%E6%B3%95b-build--run)」を参考にDockerfileを編集し、dockerコマンドを実行する

Dockerfileの内容

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/f29081f4-6b1a-1a13-e5ed-494a7ffc8642.png)

Ubuntu on Windows で実行するコマンド2つ

```bash
# イメージをビルドする
docker build --build-arg DISPLAY=$DISPLAY --build-arg PULSE_SERVER=$PULSE_SERVER --build-arg WAYLAND_DISPLAY=$WAYLAND_DISPLAY --build-arg XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR . -t image-name 

# コンテナを起動する
docker run -v /mnt/wslg:/mnt/wslg -v /tmp/.X11-unix:/tmp/.X11-unix -it --rm image-name
```

成功すれば、以下のような画面が起動する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/65a9f2a8-801f-f960-6d55-ecc29936766b.png)

これでdocker環境からもGUIを使えることがわかった

### WSL2でdockerが使えない場合の対処

自分の場合は、Docker Desktopの設定を変更することで、使えるようになりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/56f13fef-d42a-0633-7db1-5d22e43e86d9.png)

参考：[wsl上のubuntuでdockerが使用できない](https://zenn.dev/kathmandu/articles/4a86c3d75b93c3)

## RustのGUIアプリをDockerで起動する

[RustのGUIライブラリ「gtk-rs」](https://gihyo.jp/article/2023/07/rust-monthly-topics-04-01)

上記記事を参考に、Ubuntu on Windowsターミナルでdockerコンテナを起動し、Rust製GUIアプリを動かす

### docker-compose.yml

1. Ubuntu on Windowsを起動し、任意のフォルダを作成する
1. 作成したフォルダの中に `docker-compose.yml`を作成する
1. ファイルの中に以下の内容を記述する

```yml:docker-compose.yml
version: "3.9"
services:
  mylinux:
    build: ./linux-container
    container_name: mylinux
    hostname: mylinux
    working_dir: /work
    tty: true
    stdin_open: true
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
      - /mnt/wslg:/mnt/wslg
    environment:
      - DISPLAY=$DISPLAY
      - PULSE_SERVER=$PULSE_SERVER
      - WAYLAND_DISPLAY=$WAYLAND_DISPLAY
      - XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR
```

次に、`./linux-container`フォルダの中にDockerfileをつくる

### Dockerfile

docker-compose.ymlファイルがある階層に、`linux-container`フォルダをつくる
そのフォルダの中に`main.rs`と`Dockerfile`つくる

- ベースイメージはUbuntu:22.04
- Rustをインストールし、パスを通す
- `/work`フォルダにRustプロジェクトを作成する

```docker:Dockerfile
FROM ubuntu:22.04
RUN apt update && apt install -y libgtk-4-dev build-essential

# Rust install
ENV RUST_HOME /usr/local/lib/rust
ENV RUSTUP_HOME ${RUST_HOME}/rustup
ENV CARGO_HOME ${RUST_HOME}/cargo
RUN mkdir /usr/local/lib/rust && chmod 0755 $RUST_HOME
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > ${RUST_HOME}/rustup.sh \
    && chmod +x ${RUST_HOME}/rustup.sh \
    && ${RUST_HOME}/rustup.sh -y --default-toolchain nightly --no-modify-path
ENV PATH $PATH:$CARGO_HOME/bin

# Rust build
RUN mkdir /work
WORKDIR /work
RUN cargo new hello-gtk
WORKDIR /work/hello-gtk
RUN cargo add gtk4@0.6.6 --rename gtk
COPY main.rs /work/hello-gtk/src/
RUN cargo build
```

hello-gtkプロジェクト（ビルド済み）が入ったDockerイメージが完成した
`main.rs`の内容は、[先述の記事にあるmain.rs](https://gihyo.jp/article/2023/07/rust-monthly-topics-04-01)と同じにする

### hello-gtkを実行する

docker-compose.ymlの階層で`docker comose up`をして、コンテナを起動する
さらに`exec`でコンテナの中に入る

```powershell
docker compose up -d
docker compose exec mylinux bash
```

最初のフォルダは`/work`になっている

```bash:pwd
/work
```

`hello-gtk`フォルダに移動して、`cargo run`する
すでに`cargo build`を終えているので、すぐにGUIが起動する

```
cd hello-gtk

cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 1.07s
     Running `target/debug/hello-gtk`
Clicked!
Clicked!
Clicked!
```

以下のような画面が立ち上がる
Click me!を押した分だけ、コンソールにClicked!とメッセージが表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/75c91a93-895b-7ee4-d52c-0ede007fbe7e.png)

以上でWindowのDocker環境でRustのGUIアプリが起動した

## おわりに

Windows、Docker、gtk-rsを組み合わせて
WindowsマシンでRustのGUIアプリを起動して動作することを確認した

VSCodeのターミナル（PowerShell）ではなく、Ubuntu on　Windowsのターミナルから
コンテナを起動する必要させなければならないのが手間なので
ここを解消したい

### 追記_VSCodeのターミナルをWSLにする

VSCodeのターミナルの種類をWSLにするのは簡単だった
ターミナルを開いて ＋ を押すと、ターミナルの種類を選択できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/d5b2622e-fbb7-2637-62db-b438df8f7e16.png)

`cargo run`すると、画面が表示される
クリックすると、ログがVSCodeのターミナルに表示される

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/d232cdc2-4998-6497-fa20-e25cec3503c8.gif)

自分の環境ではデフォルトで`pwsh`（PowerShell 7系）だったが
ほかにも Git や コマンドプロンプトも選べるらしい

## 参考

[【Docker】Rustをインストール](
https://c-a-p-engineer.github.io/tech/2022/09/29/docker-rust-install/)

[wslのDockerでGUI操作](https://qiita.com/rayfiyo/items/17842dcf258b4d585531)

## 糸冬了！！