有时候我们在 Mac OS X 或 Windows 平台下需要开发以 Linux 为运行时的应用,IDE 或可直接使用 Docker 容器,或 SSH 远程连接。本地命令行下操作虽然可以用 docker exec
连接正在运行的容器,但 IDE 远程连接的话 SSH 总是一种较为通用的连接方式,所以我们希望做一个能进行 SSH 连接的 Docker 容器。因为是本地运行的 Docker,我们想直接用 root 连接,以获得在容器中最大的运行权限。下面以 ubuntu:2004 基础镜像为例,看如何安装启用 ssh 服务以及允许 root 连接。
创建允许 root + 密码登陆的镜像
我们创建一个基本的 Dockerfile 文件,内容为
1 2 3 4 5 6 7 8 |
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y openssh-server && \ mkdir /var/run/sshd && \ echo 'root:your_password' | chpasswd && \ sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config CMD ["/usr/sbin/sshd", "-D"] |
注:
- mkdir /var/run/sshd: 在启动 /usr/sbin/sshd 需用到,否则无法启动
- sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config: 允许 root 用户登陆,安装 openssh-server 后,PermitRootLogin 行默认被注释掉了
- 如果登陆验证有问题,在构建镜像时加上
sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
试试
构建镜像
$ docker build -t demo-ssh .
创建了一个 tag 为 demo-ssh:latest 的镜像
启动容器
$ docker run -d -p 2022:22 demo-ssh
895e8c689c44b806da82d87980a292f55fd316bbfcce2ac3a174d7710511f272
映射主机上的端口号 2022 容器的 22
SSH 登陆
$ ssh root@localhost -p 2022
由于使用了非默认的 22 端口号,所以需加上 -p 2022
指定连接端口号。
第一次登陆会提示 Are you sure you want to continue connecting (yes/no/[fingerprint])?
回答 yes 后,再输入前面构建镜像时的密码(your_password)就登陆成功了。
就是下面的过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
The authenticity of host '[localhost]:2022 ([::1]:2022)' can't be established. ED25519 key fingerprint is SHA256:PPAA8h/AKQS9n0myXjWn32i2Sr6d9bX+fZ9IynavXNg. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[localhost]:2022' (ED25519) to the list of known hosts. root@localhost's password: Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 6.6.26-linuxkit x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command. The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@895e8c689c44:~# |
fingerprint 记录在了本地的 ~/.ssh/known_hosts 文件中。如修改了镜像(重新构建了镜像),还是在相同的映射端口上启动容器后,比如重新构建了 demo-ssh 镜像,停掉了原来的容器,再次用
$ docker run -d p 2022:22 demo-ssh
在相同的 2022 端口上映射容器内的 22 端口号
$ ssh root@localhost -p 2022
将会看到如下的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ssh root@localhost -p 2022 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ED25519 key sent by the remote host is SHA256:hKgsTk2QbpGoA3SS3qPGfbWKLZe3F5yTaYTBI4zBCck. Please contact your system administrator. Add correct host key in /Users/yanbin/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /Users/yanbin/.ssh/known_hosts:38 Host key for [localhost]:2022 has changed and you have requested strict checking. Host key verification failed. |
我们需要在 ~/.ssh/known_hosts 中把 [localhost]:2022 行删除掉才能重新回答 yes
来用密码登陆。
相同的镜像多次启动,或是用不同的映射端口启动容器都用不着从 ~/.ssh/known_hosts 中删除相应的条目。
创建免密登陆的镜像
如果镜像不欲分享,那么参考 如何无需密码进行 SSH 连接[翻译],我们可以创建一个不用输入密码就能 SSH 登陆的 Docker 镜像。
首先在本地用 ssh-keygen -t rsa
在目录 ~/.ssh 下生成 id_rsa 和 id_rds.pub 密钥文件,记住在询问 Enter passphrase
是直接回车过掉。
然后在构建 Docker 镜像是把本地的 ~/.ssh/id_rsa.pub
的内容放到镜像的 /root/.ssh/authorized_keys
文件中。
相应的 Dockerfile 是
1 2 3 4 5 6 7 8 9 10 |
FROM ubuntu:20.04 ARG ssh_pub_key RUN apt-get update && apt-get install -y openssh-server && \ mkdir /var/run/sshd && \ mkdir /root/.ssh && \ echo "$ssh_pub_key" > /root/.ssh/authorized_keys CMD ["/usr/sbin/sshd", "-D"] |
由于无需用户/密码登陆,所以关于启于 root 用户登陆相关的内容也用不着了。
构建命令
$ docker build -t demo-ssh --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" .
这样本地的 ~/.ssh/id_rsa.pub 文件内容就会跑到镜像的 /root/.ssh/authorized_keys 中去
同样的方式启动容器,但 SSH 连接容器时不用输入密码了
$ ssh root@localhost -p 2022
~/.ssh/known_hosts 的处理方式会是一样的,现在不需要输入密码就能登陆了。
另外还能配置默认的用户和端口号,在 ~/.ssh/config 文件中
1 2 3 |
Host localhost User root Port 2022 |
这样的话,输入
$ ssh localhost
就相当于下面的全命令
$ ssh root@localhost -p 2022
而且配置了 ssh key 的话,ssh localhost 就直接登陆了。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ ssh localhost Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 6.6.26-linuxkit x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command. Last login: Wed Jun 5 20:32:05 2024 from 192.168.65.1 root@0474baf1a1ff:~# |
只有第一次必须回答 yes 接受 fingerprint, 以后只需像上面那样输入 ssh localhost
就非常顺滑进入到容器的终端。
用 scp 命令在本地和 SSH 主机上搬运文件和 ssh 的验证方式是一样的,比如拷贝一个文件进到容器可以用命令
$ scp test.txt localhost:/
因为是 Docker 容器,大可不必用 scp, 用 docker cp 就行,不依赖于 ssh, 只要写上可定位唯一容器的 ID 前缀
$ docker cp test.txt 89:/
本文链接 https://yanbin.blog/create-root-ssh-docker-image/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。