dockerまわり：ウィンドウ描画できなくて困ったときのアレコレ

**2020/03/09 加筆修正**

# カッコよくウインドウ描画したいYO
機械学習するとき，学習の進み具合をmatplotlibとか使ってカッコよく書き出したりしたくないですか？
私はしたいです。
ということで，よくdoker周りでウィンドウ設定するのですが，これがまあよく引っかかる…ってことで記事にまとめようと思います。他の例，こんなんがあるよ！とかあったら遠慮なくお教えください。勉強したいです

# 今回のウィンドウ描画

- X window system　を使います
- xeyesできるところまで行けたら大体大丈夫なので，それぞれの環境でXeyesできることを目標とします

# X window systemって
使うようになるまでまっっっっったく知らなかったのですがとってもありがたい。
私は以下くらいの理解で使っています。

> - ウィンドウシステム（GUIで操作できるようにするためのソフトウェア）の一種
> - UNIX系システムで標準的に採用されている
> - クライアントサーバシステムを採用している


 **クライアントサーバシステムって何！！！！**

これ情報系の方とかだと普通に知ってるもんなんですか？
私は知らなかったです。というわけでいかに理解をまとめます。
操作してる側がXクライアント,実際に動く環境が入ってるのがXサーバです。
![x_hyoujun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594517/1e05eba0-3b71-d7d0-2151-10d673526f6a.png)
これをdockerコンテナとdockerを動かしているPCとで捉え直すと以下のようになります。
![x_docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594517/5c27bf35-00a5-fab0-5c83-6f9f1f76762f.png)
ローカル環境でいじっているように感じちゃうのですが，実はローカルとコンテナ間で通信してるんですね。
だから一筋縄では描画ができない，というわけみたいです。
これを踏まえて，それぞれの状況に応じて環境構築していきたいと思います。

# 場合0：そもそもローカルでxeyesできんかったら話にならない！
Macならターミナル,linuxをお使いならばとりあえず端末を開いて以下の通り打ち込んでみてください。

```
xeyes
```

以下のように出たなら大成功！手順１へと進んでください。
<img width="235" alt="スクリーンショット 2020-03-03 16.15.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594517/9ff0c85e-c5ab-fa02-ec63-9a27491b293e.png">

できなかった場合，以下の可能性が考えられます。
- Xeyesがインストールされていない（-bash: xeyes: コマンドが見つかりません）→　xeyes　インストール　とかで調べて実行してみてください。
- （linuxをお使いの場合）デフォルトが描画されない設定になっていることがあるので変更の必要あり。以下試してみてください

```
#vimをインストールした上で端末で以下を実行
sudo vi /etc/X11/xinit/xserverrc
---vimエディタ内---
#!/bin/sh
exec /usr/bin/X tcp -nolisten "$@" <-右のようになってるのでここから-nolistenを消して保存
----------------

sudo vi /etc/lightdm/lightdm.conf
---vimエディタ内---
[seatDefaults]
Xserver-allow-tcp=true <-デフォでは何も書いてないはずなのでこの行を追記
-----------------
```
上記手順の上でPC再起動
端末上で以下を実行

```
xhost +
export DISPLAY=(XクライアントのIPアドレス):0.0
```
ここまできたら再びxeyes試してみてください。きっとかわいいお目目が描画される…はず

# 場合１：dockerコンテナでxeyesしても描画されない
この場合，もうコンテナ作りかえるしかないです。
GUIでの描画が必要な時はdocker runするときに必ずこの設定しましょう。

```
docker run -it --net host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix/:/tmp/.X11-unix --name hogehoge hoge-image /bin/bash
```

以下各コマンドの働きです

```
--net host : ホストPCのネットワークスタックをコンテナ内で利用する
-e DISPLAY=$SIDPLAY : ホストのディスプレイ変数をコンテナのディスプレイ変数に入れる
-v /tmp/.X11-unix/:/tmp/.X11-unix : ソケットが入っているディレクトリを同名同構成のディレクトリとしてコンテナにバインド
```

最初わけわかんなかったんですけど，ローカルPCの環境をコンテナにコピーしているというイメージみたいです。
上コマンドでコンテナ作った上でコンテナにXeyesできる環境を作ります。

```
sudo apt install xorg
sudo apt install openbox
```

以上手順踏んだ上で

- コンテナ外で

```
xhost local:
export DISPLAY=:0.0
```

- コンテナ内で

```
xeyes   --->SUCCESS!!!(のはず)
```

長かったですね。

# 場合２：teratermなどでssh接続しているPC上でコンテナを動かしていて，描画できないとき

つまりこういうときです
![X_teratermpng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594517/16be092f-8585-608f-b366-357d27a2483d.png)

こうしたいときはまた，コンテナ作るとき別途設定が必要です。

```
docker run -it --net host -e DISPLAY=$SIDPLAY -v　＄HOME/.Xauthority:/root/.Xauthority --name hogehoge hoge-image /bin/bash
```

以下さっきと違うコマンドの働きです。バインドしてるものが違いますね。

```
-v ＄HOME/.Xauthority:/root/.Xauthority : ホスト側ユーザの.Xauthorityをコンテナのrootと共有する
```

これでコンテナ作った上で，コンテナにxeyesできる環境整えればきっと描画できるはずです。

# 場合３：Macがクライアント・サーバの場合ちょっと設定が必要
全てはこれに書いてあります。ありがとうございます
[https://gist.github.com/asufana/229cdac01fccee1a7d32ca8b5d7cfee6](https://gist.github.com/asufana/229cdac01fccee1a7d32ca8b5d7cfee6)
場合1,2にぶち当たった時はLinux・Windowsマシンでやっていたのでわからんかったのですが,Macでの設定はちょっと特殊でした。盲点

# 場合4：それでもできない！
これは場合2の派生なのですが,teratermの設定を見直すとうまくいく場合があります。

- teratermの設定（S）メニューから，SSH転送（O）．．．を選択
- 出てきた画面の「リモートの（X）アプリケーションをローカルのXサーバに表示する」のチェックボックスにチェック
- 設定（S）メニューから，設定の保存（S）を選択し,設定を保存
- 保存した上でteratermを立ち上げ直す

そうでない場合は，

- コンテナ外で

```
xhost +
```

- コンテナ内で

```
export DISPLAY=:0.0
```

さらにそうでない，何かがないと言われる場合には必要なものがコンテナ内外に揃っているか確かめてみてください(以下あたりのもの) 

```
sudo apt install xauth
sudo apt install xorg
sudo apt install openbox
```

これでもできない場合にはまだ遭遇したことがないです。
できない場合あれば教えてください。是非知りたいです。

# おわりに
長くなりましたが私が機械学習を始めてからの1年ちょっとでぶちあたったディスプレイ周りの問題です。これらのおかげで最近はだいぶスムーズに環境構築できるようになってきた感あります。誰かのお力になれれば幸いです。

参考URL
[Dockerコンテナの中でGUIアプリケーションを起動させる](https://unskilled.site/docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%B8%AD%E3%81%A7gui%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B/)
[SSH 接続先で走っている Docker コンテナ内で実行した X アプリの GUI を SSH クライアントで表示する](https://qiita.com/aoksh/items/1a386ee87594e67784c4)
[WindowsでリモートのLinuxのGUIアプリを表示させる－Xサーバ Xming](https://vogel.at.webry.info/201310/article_6.html)
[資料で使う技術/プロダクトロゴのリンク集](https://qiita.com/tkit/items/932316c5f5f7b162b61e)