何番煎じか分かりませんが、せっかく勉強したのでコンテナ間ssh通信ができるシンプルな環境を構築してみました。
方針
・docker compose up
するだけで簡単にssh通信を検証できる仕組みにしたい
・ホストマシンの~/.sshとかを汚さず検証したい
・sshなのでセキュアな感じで検証したい
こんなイメージを元に以下のような環境を構築してみようと思います。
実装
- ディレクトリ構成
% tree
.
├── compose.yml
├── local-volume
│ ├── local_config
│ ├── local_id_rsa
│ ├── local_id_rsa.pub
│ └── local_known_hosts
├── ssh-client
│ └── Dockerfile
└── ssh-server
└── Dockerfile
- Compose.yml
# networksについて
# bridgeならデフォルトで設定されるため省略でも問題ないが、subnet適用の挙動確認のため記載している
# version表記は現在は非推奨の模様
# version: "3"
services:
ssh_server:
build:
context: .
dockerfile: ./ssh-server/Dockerfile
container_name: ssh_server
hostname: master
privileged: true # /sbin/initを特権モード(Dockerデーモンへのアクセス)で実行するために必要
command: /sbin/init
volumes:
- ./local-volume/local_id_rsa.pub:/home/ssh-man01/.ssh/authorized_keys
expose:
- "2222" # コンテナ間通信のみ実現させたいのportsではなくexposeでOK
networks:
ssh_network:
ipv4_address: 192.168.10.2
ssh_client:
build:
context: .
dockerfile: ./ssh-client/Dockerfile
container_name: ssh_client
hostname: slave
tty: true # コンテナの起動状態を継続させる
volumes:
- ./local-volume/local_known_hosts:/root/.ssh/known_hosts
- ./local-volume/local_id_rsa:/root/.ssh/id_rsa
- ./local-volume/local_config:/root/.ssh/config
networks:
ssh_network:
ipv4_address: 192.168.10.3
networks:
ssh_network:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.10.0/24
- Dockerfile(ssh-client)
FROM ubuntu:20.04
RUN apt -y update && \
apt clean all && \
apt -y install openssh-client && \
mkdir -m 700 ~/.ssh
- Dockerfile(ssh-server)
FROM ubuntu:20.04
RUN apt -y update && \
apt clean all && \
apt -y install openssh-server && \
sed -ri 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
sed -ri 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config && \
useradd -m ssh-man01 && \
install -m 700 -o ssh-man01 -d /home/ssh-man01/.ssh
- local_config
Host master
HostName master
User ssh-man01
Port 2222
IdentityFile ~/.ssh/id_rsa
ServerAliveInterval 60
ServerAliveCountMax 5
検証
事前準備
ssh-keygen -t rsa
で鍵生成して公開鍵/秘密鍵をlocal-volumeディレクトリに配置し、それぞれ権限600に変更
% ls -l local-volume
total 32
-rw-r--r--@ 1 user staff 148 9 20 12:44 local_config
-rw-------@ 1 user staff 2602 9 19 20:30 local_id_rsa
-rw-------@ 1 user staff 564 9 19 20:15 local_id_rsa.pub
-rw-r--r--@ 1 user staff 444 9 20 14:40 local_known_hosts
コンテナ起動
% docker compose up -d
[+] Running 3/3
✔ Network ssh_network Created 0.0s
✔ Container ssh_client Started 0.3s
✔ Container ssh_server Started
network構成確認
・「指定したnetwork名・sbunetで構築できていること」を確認
・「指定したipv4アドレスが各コンテナに割り当てられ、指定のネットワークに属していること」を確認
% docker network inspect ssh_network
[
{
"Name": "ssh_network",
"Id": "e21a0a50a33a5c6b69f752f4f6114adaac471df40447b329ce80b9135cfefc4e",
"Created": "2023-09-20T05:58:58.725362953Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.10.0/24"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7be6980344c041e01f0b8fb64d77b86ff8e02836710e16cab91f4765f6f0340a": {
"Name": "ssh_server",
"EndpointID": "9fe9aaa47cd88b9dbd895a9da08f98af9b9bfdbcc0c6b2c3dbfc42ebea7847f4",
"MacAddress": "02:42:c0:a8:0a:02",
"IPv4Address": "192.168.10.2/24",
"IPv6Address": ""
},
"9b517b7fb1130382bc11b392a792a76294b49025c4cfd9e6e4a4e3850eed16b1": {
"Name": "ssh_client",
"EndpointID": "e93a15cf99024c764bc0e7104acb2a49d2507989f4652cab77aa5b5a6788e5d8",
"MacAddress": "02:42:c0:a8:0a:03",
"IPv4Address": "192.168.10.3/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "ssh_network",
"com.docker.compose.project": "docker-compose-test",
"com.docker.compose.version": "2.20.2"
}
}
]
slave側のコンテナへログイン
% docker exec -it ssh_client bash
root@slave:/#
master側へssh
「ssh-man01というユーザ名でmaster側へsshログインできること」を確認
# ~/.ssh/configを設定しているため下記コマンドで公開鍵認証が可能です
root@slave:/# ssh master
The authenticity of host '[master]:2222 ([192.168.10.2]:2222)' can\'t be established.
ECDSA key fingerprint is SHA256:DQSQdUdNphmtnOPpzKDEl/XMNCO+KN+Pz5sIEBzVGwo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
-- (中略) --
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
$ whoami
ssh-man01
$
ホストマシンからssh
「ホストマシンからはsshサーバのホストが解決できないこと」を確認
% ssh -i ./local-volume/local_id_rsa -oPort=2222 ssh-man01@192.168.10.2
ssh: connect to host 192.168.10.2 port 2222: Operation timed out
ということで、当初の構想通り環境を構築することができました!
まとめ
- DockerよりもLinuxサーバーやネットワークの勉強した方がよさそう...(Dockerはここらへんの基礎がしっかりあっての応用という感じがした)
- とはいえ、あまり複雑な構成でなければ割とハードル低く使っていけそう
- 今回はローカルマシン汚さずにssh検証することができたので、Dockerの良さを少し感じることができた
余談
さらっとできたように書きましたが、めちゃくちゃ時間かかってます...(._.)
そもそもSSHサーバー起動ってどうやるの?って感じでした。
sshd頑張って起動しようとしてみたり、Dockerhubのopenssh-serverなど使ってみようとしてみたり、、全然うまくいかず、試行錯誤の末以下の記事に助けられました。
privileged
は
・Dockerデーモン実行したい時
・ホストのハードウェアに直接アクセスしたい時
に使う特権モードのようです。(今回のケースは前者ですかね)
ホストコンピュータのルート権限を持つことと同義のようで、セキュリティ的な危険性が発生するようです。
今回はローカルで閉じた環境なので気にしなくていいですが、業務で使う際は十分気をつけないといけないですね。
参考
- https://zenn.dev/akhmgc/articles/52c90fe6100eaf
- https://docs.docker.jp/compose/toc.html
- https://www.udemy.com/share/109eIi3@V90_P314cpKcCxH5Tm1w78iWeugFigCOir2n73wrMli62ZMwkR4I9ylXZWRV6KVFCA==/
- https://josysnavi.jp/2020/tmsb_21jan20_docker-in-docker
- https://utouto97.hatenablog.com/entry/2022/03/15/092924
- https://qiita.com/mountcedar/items/43157ff1225c56500655