dockerを仮想環境として利用する際に、コンテナの管理(コンテナ上のサービスの管理ではなく、コンテナ全体の管理)を他の人に丸投げしたくなった。ただし、同じ人に別のコンテナは触ってほしくないので、docker execできるrootやdockerグループ所属ユーザアカウントを渡すというやり方は、使いたくない。
やってみたこと
ホストのログインシェルを特殊なものにして、外部からsshでアクセスしたときに直接コンテナ内のシェルへ入り込むというのをやってみた。
仕組み
sshで外部からホストLinuxに特定コンテナ専用アカウントでアクセス。このアカウントのログインシェルを以下のシェルスクリプトにして、スクリプトからdocker execして特定コンテナにつなげる。
以下はLinux環境(ホストはCentOS、コンテナはUbuntu)での例。
mycontainerという名前のコンテナに外部からsshで入ることを想定する。
手順
- 参考文献[1]の方法で、sudoしなくてもdockerコマンドが使えるようにする。
- 以下のシェルスクリプトをログインシェルとするユーザをホストに作成
- ユーザ名は対象コンテナ名は同じにする
#!/bin/bash
if [ $# -eq 0 ]; then
exec docker exec -it `whoami` su - `whoami`
else
shift 1
exec docker exec -i `whoami` su - `whoami` -c "$*"
fi
/etc/passwdファイルはこんな感じ:
....
mycontainer:x:1010:1010::/home/mycontainer:/usr/local/bin/dockershell
- このユーザをdockerグループに加えてsudoしなくてもdockerコマンドが使えるようにする
....
docker:x:994:mycontainer
- コンテナ内にも同じユーザ名のユーザを作成する
- コンテナ内のユーザのユーザIDを他のユーザIDと同じにすることで権限を同等にする
- ホストのユーザとIDは一致しなくてよい
- コンテナ内はrootアクセスでよい場合は不要。この場合、上記スクリプトの "su - `whoami`" の部分を"/bin/bash"にしておく
- コンテナ内のユーザのユーザIDを他のユーザIDと同じにすることで権限を同等にする
- scpによるファイルコピーをするのであればコンテナにscp(openssh-clientsなど)を入れておく
- sftpによるファイルコピーをするのであればコンテナにsftp-server(openssh-serverなど)を入れておく
- sshでのアクセスは公開鍵認証とする
- ホストの /etc/ssh/sshd_config で
PubkeyAuthentication yes
のコメントを外す
- ホストの /etc/ssh/sshd_config で
- このアカウントについてはパスワード認証はできないようにしておくのが吉(検討事項参照)
- sshアクセスのための公開鍵を用意して、ホスト側のユーザアカウントホームの ~/.ssh/authorized_keys に入れておく
これで、sshでホストに作成したコンテナ名と同名のアカウントにアクセスすれば、コンテナ内に入れる。
検討事項
今回、公開鍵でのアクセスに限ったのは、ホストに新アカウントで入れないようにするため。このユーザはdockerコマンドが使えるため、直接ホストに入れてしまうと、他コンテナをいじることができてしまう。パスワード認証で入れると、ホスト側の別アカウントから su(switch user)することができるので、これを防ぐために公開鍵のみでのアクセスにしてみた。利用するユーザを完全に信頼できるならそこまでしなくてよいかもしれませんが。
他の解決策
○ コンテナにipアドレスをつけておいて、コンテナでsshdをあげてsshで直接入れるようにする。
→ ip必要とかめんどくさいよね。
○ コンテナでsshdをあげて、ホストからのポートフォワードでsshで入れるようにする。
→ ポート転送の設定めんどくさいよね。
dockershellスクリプトの説明
コンテナが1つしかないのであれば、ユーザ名とコンテナ名を一致させるとかしなくても、スクリプト内に直接コンテナ名を埋め込んでしまってもよいのだけど、ちょっと汎用性を持たせてみようと思ってこんな感じに。$*
で引数の有無を調べているんだけど、引数がないときは、ターミナルとしてのシェルが期待されているので、 docker exec
のオプションとして、-t
をつけています。tがあると、 scp
や sftp
がうまくいかないので、こうして切り分けています。また、もともと、 $*
の1番目には -c
が入っていてシェルに直接引っ付くようになっているのですが、これをそのまま su
コマンドに渡すと $*
の一部を su
コマンドの引数と解釈されることがあって困ったので、上記のように shift
で一度取り除いてから改めて -c
をつけています。
その他(不具合など)
- CentOS6.9+docker-io 1.7 だと、scp/sftpがうまく動かない…(完了しない)。
参考文献
[1] Dockerコマンドをsudoなしで実行する方法 https://qiita.com/DQNEO/items/da5df074c48b012152ee