Edited at

Dockerコンテナでsystemd無しのSSH

More than 1 year has passed since last update.


はじめに

DockerでSSHをやってみたら意外と難しかったのでメモ。systemdが起動していないコンテナ内ではsshdの起動に工夫がいるようですね。

調べたところやり方は何パターンかあるようですが、その中で筆者が個人的に気に入ったものを書きます。(筆者はCentOSのコンテナを用いました)


コンテナ内からSSHで外部にログイン (コンテナがSSHクライアントになる場合)

コンテナ内から別のホストにSSHでログインするのは別に難しくありません。

まず、SSHクライアントをインストールします。

$ sudo yum -y install openssh openssh-clients

あとは普通に鍵を生成してから相手ホストに公開鍵を渡して、各々でパーミッションの設定をするといういつものやつです。

# コンテナ(クライアント)側の操作

# パスフレーズなしのRSA鍵を/root/.ssh以下に生成
$ ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
# パーミッションの設定
$ chmod 700 /root/.ssh
# 公開鍵の転送
$ scp /root/.ssh/id_rsa.pub <ログインユーザ>@<相手ホストのIP>:~/.ssh


コンテナ内でsshdを起動 (コンテナがSSHサーバになる場合)

難しいのはこっちです。コンテナ内ではsystemdが起動していないので、いつものようにsystemctl start sshdとしてもエラーが出て上手くいきません。sshdを起動する際にちょっと工夫をいれます。

まずSSHサーバをインストールし、設定ファイルを書き換えておきます。

# SSHサーバのインストール

$ sudo yum -y install openssh openssh-server
# 設定ファイルの書き換え
$ sudo vi /etc/ssh/sshd_config

次にホスト鍵を生成します。systemdによってsshdが起動するわけではないので、自分でホスト鍵を生成する必要があるようです。設定ファイル内のホスト鍵の部分をコメントアウトしてしまう方法もアリです。

# ホスト鍵の生成 (必ずパスフレーズ無しにすること)

$ ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key
$ ssh-keygen -t dsa -N "" -f /etc/ssh/ssh_host_dsa_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

次に/var/run/sshd/root/.sshの2つのディレクトリを作ります。

$ mkdir /var/run/sshd

$ mkdir /root/.ssh

そして、このコンテナに公開鍵を渡して/root/.ssh以下に置き、パーミッションの設定をします。

# Dockerホストからコンテナに公開鍵を渡す

$ sudo docker cp id_rsa.pub <コンテナID>:/root/.ssh

# 以下はコンテナ内で実行
# 公開鍵の名前とパーミッションの設定
$ cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
$ chmod 600 /root/.ssh/authorized_keys
# .sshのパーミッションの設定
$ chmod 700 /root/.ssh

最後にsshdを起動するのですが、ここで一工夫。何の工夫もなしにsshdを起動しても一瞬デーモンが起動するだけですぐに停止してしまうため、sshdが常駐してくれません。

そこで、こんなコマンドでsshdを起動します。

# sshdの起動 (sshdはフルパスで起動しないとエラー)

$ /usr/sbin/sshd && tail -f /dev/null &

tail -f /dev/null&&で連結してあげることで、sshdが常駐してくれるようになります。

/dev/nullは「ヌルデバイス」という特殊なファイルで、ここに書き込まれたデータはすべて捨てられて消去されるようになっています。このファイルをtailコマンドでずっと監視させることで、無限ループを実現しているわけです。これで、Ctrl+Cを押さない限りはsshdが停止することはありません。

こうすることでsshdが常駐し、外部からコンテナにSSHでログインすることが可能になります。(ポートフォワーディングの設定を忘れずに!)


おわりに

Dockerコンテナだと、ちょっとSSHサーバ立てるだけでも面倒なことになるんですね…。完全に舐めてました。

紹介した方法以外にも、「/sbin/initを実行コマンドとした状態でコンテナを立ててdocker execコマンドでコンテナに入る方法」や、「supervisorを利用する方法」などいくつかあるようですが、今回紹介した方法が多分一番お手軽です。