この記事で出来ること
dockerコンテナの中でGUIアプリを立ち上げて、mac(※1)に表示する
具体的には、VSCodeを立ち上げれるようになる
(※1 macに限らずともX Window Systemがインストールされている環境ならどこでも使えるはず)
背景
Dockerを使って開発するのがかなり一般的になってきました。かく言う私も、仕事や趣味でDockerばかり使っています。
Dockerfileさえ書いてしまえば、いつでも同じ環境を構築できるのでとても便利です。
ただDockerを使うことでやりづらくなる点もあります。それがデバッグ作業です。
私はIDEのデバッガーをよく使います。ブレークポイントを自由自在に置くことができ、現時点での変数やコールスタックが一覧で表示されるのでとても捗ります。ターミナルで行うデバッグも良いですが、使い勝手の良さでは圧倒的にIDEのデバッガーが優れていると思います。
私の知る限り、IDEのデバッガーはIDEがインストールされているホストマシンの環境をまず見に行きます。そのため、初期設定のままではDockerコンテナの中で立ち上げたプロセスを知る術がなく、デバッグのしようがありません。
もちろん、きちんと設定をすればDockeコンテナのプロセスのデバッグをすることができます。
が、設定、めんどくさいときないですか?
設定ができない言語やIDEだったらもう諦めるしかありません。
そんな時、Dockerコンテナの中でエディタを立ち上げちゃいましょう
方針
ssh
のX11 Forwarding
を使います。
Dockerコンテナ内で立ち上げたGUIアプリが、コンテナ内のX Window System
ではなく、ホストコンピューターのX Window System
に対して描画指示を送るようにします。
手順
今回は手始めにVSCodeをDockerコンテナの中で立ち上げたいと思います。
※以下、ローカル開発することを前提としたコードです。セキュリティの保証はできかねますので十分注意してください。
準備
macには標準でX Window Systemがインストールされていないみたいです。
なので、インストールします。
brew update
brew cask install xquartz
UbuntuなどのLinuxにはおそらくデフォルトでインストールされてるんじゃないかなと思います。
dockerのバージョンはこちら
$ docker -v
Docker version 19.03.5, build 633a0ea
1. SSHの公開鍵と秘密鍵を作成
Dockerコンテナとssh通信を行うのでそこで使う鍵を作ります。
今回は id_rsa_for_docker_ssh
と言う名前で作ります。
$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/machisuke/.ssh/id_rsa): /Users/machisuke/.ssh/id_rsa_for_docker_ssh
2. Dockerfileを作る
sshやX11 Forwarding、VSCodeの起動に必要なライブラリを入れます。
他のエディタやGUIツールを使う場合は、必要に応じて書き換えてください。
Dockerfileはこちらを参考にさせていただきました。
machisuke
と言う名前でユーザーを追加しており、パスワードはpassword
としておきました。ここも適宜変えてください。
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates\
sudo \
openssh-server \
wget \
libnotify4 \
gnupg \
libxkbfile1 \
libsecret-1-0 \
libgtk-3-0 \
libxss1 \
libnss3 \
libx11-xcb-dev \
libxtst6 \
libasound2 \
xauth \
iputils-ping \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
### User settings ###
ARG NB_USER=machisuke
ENV NB_USER ${NB_USER}
# HOST_ID should be same as host's user id.
ARG HOST_UID
ENV NB_UID ${HOST_UID}
# Add user and set password. (ここではユーザーのパスワードは"password"とします)
RUN useradd -m -G sudo -s /bin/bash -u $NB_UID $NB_USER && \
echo "${NB_USER}:password" | chpasswd
RUN echo "Defaults visiblepw" >> /etc/sudoers
RUN echo "${NB_USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
### End ###
### SSHでDockerにアクセスするための設定
ARG AUTHORIZED_KEYS
RUN ( echo "#!/bin/bash"; \
echo "echo ${AUTHORIZED_KEYS} > /home/${NB_USER}/.ssh/authorized_keys"; \
echo "chown -R ${NB_USER}:${NB_USER} /home/${NB_USER}"; \
echo "chmod 600 /home/${NB_USER}/.ssh/authorized_keys"; \
echo "service ssh start"; \
echo "tail -f /dev/null"; ) > /home/${NB_USER}/entrypoint.sh && \
chmod +x /home/${NB_USER}/entrypoint.sh && \
sed -i.bak 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config && \
echo "X11UseLocalhost no" >> /etc/ssh/sshd_config && \
mkdir /home/${NB_USER}/.ssh && chmod 700 /home/${NB_USER}/.ssh && \
( echo "Host *"; \
echo " StrictHostKeyChecking no"; \
echo " UserKnownHostsFile=/dev/null"; ) > /home/${NB_USER}/.ssh/config
# Disable annoying warning about sudo
RUN touch ~/.sudo_as_admin_successful
# ユーザーの切り替え
USER $NB_USER
ENV LANG=ja_JP.UTF-8
# VSCodeのダウンロードとインストール
RUN cd /home/${NB_USER} && \
wget --no-verbose https://go.microsoft.com/fwlink/?LinkID=760868 -O vscode.deb && \
sudo apt-get install -y --no-install-recommends ./vscode.deb
EXPOSE 22
# SSHサーバーを起動
CMD ["sudo","bash","-c", "bash ~/entrypoint.sh"]
3. 各種スクリプトの用意
作成したスクリプトは全て同じディレクトリにおいてください。
- Dockerイメージビルド用
公開鍵を変数として渡しています。
#!/usr/bin/env bash
PUB_KEY=$(cat ~/.ssh/id_rsa_for_docker_ssh.pub)
IMAGE_NAME="docker_ssh"
docker build \
--build-arg HOST_UID="$(id -u)" \
--build-arg AUTHORIZED_KEYS="${PUB_KEY}" \
-t ${IMAGE_NAME} \
.
- Dockerコンテナ起動用
このコマンドを実行すれば、buildも同時に走るようにします。
sshで使うコンテナの22
番ポートをホストマシンの8022
番にマッピングします。
#!/usr/bin/env bash
IMAGE_NAME="docker_ssh"
CONTAINER_NAME=${IMAGE_NAME}
bash ./docker_build.sh
docker run --name=${CONTAINER_NAME} --rm -it -p 8022:22 ${IMAGE_NAME}
- X11 forwarding用
ファイルにするまでもないですが、覚えるのも大変なので。
docker_run.sh
により、Dockerコンテナの22
番ポートはlocalhostの8022
番にマッピングされています。
#!/usr/bin/env bash
ssh -p 8022 -X -o StrictHostKeyChecking=no machisuke@localhost
4. Dockerコンテナの起動
$ bash ./docker_run.sh
Sending build context to Docker daemon 66.56kB
Step 1/17 : FROM ubuntu:18.04
---> 775349758637
Step 2/17 : RUN apt-get update && apt-get install -y --no-install-recommends sudo openssh-server wget libnotify4 gnupg libxkbfile1 libsecret-1-0 libgtk-3-0 libxss1 libnss3 libx11-xcb-dev libxtst6 libasound2 ca-certificates && apt-get clean && rm -rf /var/lib/apt/lists/*
---> Using cache
---> 9d3d8a65d0d7
(省略)
Step 16/17 : EXPOSE 22
---> Using cache
---> 3d096b9c1108
Step 17/17 : CMD ["sudo","bash","-c", "bash ~/entrypoint.sh"]
---> Using cache
---> c9e835fc358a
Successfully built c9e835fc358a
Successfully tagged docker_ssh:latest
* Starting OpenBSD Secure Shell server sshd [ OK ]
5. XQuartsのシェルからX11 forwardingとvscodeの起動
- XQuartsを起動して、メニューバーからターミナルを開きます。
- docker_connect.shを実行
パスワードはDockerfileに設定したpassword
です。
$ ./docker_connect.sh
machisuke@localhost's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.9.184-linuxkit x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
Last login: Wed Dec 4 07:14:55 2019 from 172.17.0.1
machisuke@1ff26b7a58a3:~$ code .
- 無事起動できました!お疲れ様です。
終わりに
この記事では、Dockerコンテナの中でGUIアプリを立ち上げるための最低限必要なことを共有させていただきました。みなさんのデバッグ作業の助けになっていれば、幸いです。
もちろん、エディタだけでなく、どんなGUIアプリもこの方法で表示することができると思いますので、興味のある方は挑戦してみてください。
この記事を参考に、Dockerコンテナ内でエディタを起動しようと思っている人は、下記の点に注意していただければと思います。
- コンテナを起動する度にエディタの設定がリセットされてしまう。
- プラグインなど、エディタの設定を恒久的に維持するためには改修が必要
- デバッガーによっては追加の設定が必要
- C++のデバッグ環境の構築は大変でした。(私はClionを使ってました)