X11クライアントを Docker コンテナの中で動かして、 リモートから使いたいと思ったので、 X11Forwarding の準備をした上で、 コマンドとして sshd を指定したコンテナを作りました。

検証環境

  • Docker Community Edition : 18.06.0-ce-mac70 (26399)
    • Engine: 18.06.0-ce
    • Compose 1.22.0

参考

Dockerize an SSH service の Dockerfile を参考にしました。

リンク先の内容が変わった時のために参考にした Dockerfile を引用しておくと、内容は以下の通り。

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

変更した Dockerfile

最終的には以下のようになりました。 FROM ubuntu:18.04 でも動作することを確認しています。

authorized_keys をコピーして公開鍵認証を使うようにすれば、 chpasswdPermitRootLogin の変更は不要です。

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/#\?PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

RUN apt-get install -y xauth
RUN echo AddressFamily inet >> /etc/ssh/sshd_config
#COPY authorized_keys /root/.ssh/authorized_keys

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

動作確認手順

参考にした先では docker port の出力で ssh -p の引数を決めていましたが、 テスト中に何度も build し直していると変わりまくって不便だったので、 シェルの履歴で再利用できるように変更しました。

$ docker build -t eg_sshd .
$ docker run -d -P --name test_sshd eg_sshd
$ docker port test_sshd 22
$ ssh -X -p $(docker port test_sshd 22|sed 's/.*://') root@localhost

パスワードは chpasswd で設定している screencast です。

後始末

これは参考にしたサイトそのままです。

$ docker container stop test_sshd
$ docker container rm test_sshd
$ docker image rm eg_sshd

変更点などの説明

以下は変更した点などの説明です。

ubuntu:18.04 対応

PermitRootLogin の行は 16.04 だとコメントアウトされていなくて、 18.04 だとコメントアウトされていたので両対応するために #\? にしています。

AddressFamily inet

xauth

デスクトップ環境の入っていないサーバーで X11Forwarding が失敗する原因でよくある xauth の問題に対処するために xauth を入れておきます。

手元側が macOS なら brew cask install xquartz などで XQuartz を入れておき、 ~/.ssh/configXAuthLocation /opt/X11/bin/xauth を設定しておきます。

ssh 設定

~/.ssh/configNoHostAuthenticationForLocalhost yes も設定しておくと手元の Docker で試すときにホスト鍵の確認がなくなって便利です。

デバッグ

xauth を入れても X11 forwarding request failed on channel 1 で繋がらなかったので、 CMD ["/usr/sbin/sshd", "-D", "-ddd"] にして docker logs test_sshd を確認したところ、

debug2: bind port 6503: Cannot assign requested address
debug3: sock_set_v6only: set socket 7 IPV6_V6ONLY
debug2: bind port 6504: Cannot assign requested address
debug3: sock_set_v6only: set socket 7 IPV6_V6ONLY
debug2: bind port 6505: Cannot assign requested address

のようなログが大量に出ていたので、 AddressFamily inet を設定して解決しました。

今回の件に限らず docker は IPv6 対応が弱いのが辛いところです。

確認用ソフト

x11-apps を入れて xeyes で試すのをよくやっています。 xterm を入れて試すのも良さそうです。

docker-compose.yml の例

以下のような docker-compose.yml を用意しておけば docker-compose build して docker-compose up -d して ssh -X -p 2222 root@localhost で入れるようになって、 image の入れ替えも docker-compose build して docker-compose up -d するだけなので、 用途によってはこちらの方が便利かもしれません。

version: '2.3'
services:
  x11-example:
    build: .
    ports:
    - "2222:22"

docker-compose を使った場合の clean up は docker-compose down -v --rmi local のようです。

まとめ

X クライアントを docker の中で動かす準備ができました。 docker コマンドそのままだと build し直て stop して rm して start し直したりするのが面倒なので、 docker-compose と組み合わせる方が良いかもしれません。

Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published