TCPでDockerの標準入出力を提供したい - Qiita
↑は失敗。真面目にdocker kill
とかやらないとダメかなと考えていたけれど、そもそもやりたいことは接続ごとにコンテナをリセットすることで、nc
でなくても良かった。シェルを提供するならSSHを使うほうが良いよね。ということで、SSH接続があったら、コンテナを立ち上げ、そのコンテナを渡す方法。
SSHサーバーを立ち上げるDockerfile。
FROM centos
RUN \
dnf -y install openssh-server passwd && \
dnf -y clean all
RUN \
ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key && \
ssh-keygen -t ecdsa -N "" -f /etc/ssh/ssh_host_ecdsa_key && \
ssh-keygen -t ed25519 -N "" -f /etc/ssh/ssh_host_ed25519_key
RUN \
adduser user && \
echo p@ssw0rd | passwd --stdin user
# これを消さないと一般ユーザーはログインできない
RUN rm /run/nologin
CMD ["/usr/sbin/sshd", "-D"]
nologinを消さないとroot以外はログインできない。
このDockerfileだとssh-keygen
のところで生成しているサーバー鍵がキャッシュされるので注意。例えば、後半を書き換えて別のイメージを作り、そのイメージを他人に渡すと、自分の手元のコンテナのサーバー鍵と同じサーバー鍵を他人が持っていることになるので、中間者攻撃とかをされてしまう。これで作ったイメージ自体を公開するのもダメ。
ビルド。
$ docker build -t ssh_server .
シェルスクリプトを用意。
# コンテナを立ち上げ、
cid=$(docker run --rm -d ssh_server)
# IPアドレスを取得し、
ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${cid})
# 標準入出力を${ip}:22に繋ぐ
timeout 3m socat - TCP:${ip}:22
# タイムアウトするか標準入出力が切断されたら、コンテナを終了
docker stop ${cid}
このシェルスクリプトは、標準入出力を新しく立ち上げたコンテナのポート22に繋ぐ。
あとはホストの適当なポートで接続を待ち受けて、このシェルスクリプトの標準入出力に渡せば良い。この部分はxinetdでも良い。
$ socat TCP-LISTEN:2222,reuseaddr,fork 'SYSTEM:sh ssh_server.sh'
$ ssh user@ssh-server.example.com -p 2222
user@ssh-server.example.com's password:
[user@a73d4676f399 ~]$ echo "hoge" > hoge
[user@a73d4676f399 ~]$ ls -al
total 28
drwx------ 1 user user 4096 Feb 25 15:13 .
drwxr-xr-x 1 root root 4096 Feb 25 15:05 ..
-rw-r--r-- 1 user user 18 Jul 21 2020 .bash_logout
-rw-r--r-- 1 user user 141 Jul 21 2020 .bash_profile
-rw-r--r-- 1 user user 376 Jul 21 2020 .bashrc
-rw-rw-r-- 1 user user 5 Feb 25 15:13 hoge
[user@a73d4676f399 ~]$ exit
logout
Connection to ssh-server.example.com closed.
$ ssh user@ssh-server.example.com -p 2222
user@ssh-server.example.com's password:
[user@0e2465485f42 ~]$ ls -al
total 20
drwx------ 2 user user 4096 Feb 25 15:05 .
drwxr-xr-x 1 root root 4096 Feb 25 15:05 ..
-rw-r--r-- 1 user user 18 Jul 21 2020 .bash_logout
-rw-r--r-- 1 user user 141 Jul 21 2020 .bash_profile
-rw-r--r-- 1 user user 376 Jul 21 2020 .bashrc
[user@0e2465485f42 ~]$ exit
logout
Connection to ssh-server.example.com closed.
$ ssh user@ssh-server.example.com -p 2222
user@ssh-server.example.com's password:
[user@62bc4f4c36ed ~]$ Bad packet length 1237871916.
ssh_dispatch_run_fatal: Connection to xxx.xxx.xxx.xxx port 2222: Connection corrupted
新しいファイルを追加しても繋ぎ直したらリセットされているし、接続して放置していると(上記のシェルスクリプト中のtimeout
で)3分で強制切断されるし、どうなってもサーバー側にDockerのコンテナが残ることはない