创建基于 Amazon Linux 2023 的允许 SSH 登陆的 Docker 镜像

前年记录过一篇 创建可直接用 root 用户 ssh 登陆的 Docker 镜像, 采用了基础镜像是 Ubuntu:20.04. 因为在 AWS 使用 AmazonLinux 2023 更为频繁,为贴近生产环境,本地开发也使用基本 AmazonLinux 2023 为基础镜像的容器,与 IDE 连接以 SSH 协议, 容器的操作由自己的控制,而非直接使用 devcontainer 的方式。比如可以在 Windows 或 macOS 进行 Linux 相关的开发。

当今 Linux 主要还是两个发行版,一个是 RedHat 的家族,一个是 Debian 的家族,之前验证过 Debian 族的 Ubuntu, 这次要验证 RedHat 族的 AmazonLinux 2023, 也作为将来不时之需。

创建允许 root + 密码登陆的镜像

Dockerfile 内容为

 1FROM public.ecr.aws/amazonlinux/amazonlinux:2023
 2
 3RUN dnf -y update \
 4    && dnf -y install openssh-server passwd \
 5    && dnf clean all \
 6    && rm -rf /var/cache/dnf
 7
 8RUN mkdir /var/run/sshd
 9
10RUN ssh-keygen -A
11
12RUN echo 'root:changeme' | chpasswd
13
14RUN sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config \
15 && sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config \
16 && sed -i 's/^#\?UsePAM.*/UsePAM no/' /etc/ssh/sshd_config
17
18
19CMD ["/usr/sbin/sshd", "-D"]

这里不对上面的命令作具体的解释了,因为是 RedHat 系列,所以 dnf 命令也可以换成 yum 命令, 好像如今天列建议用 dnf 命令来管理软件包。

构建镜像

1docker build -t demo-ssh .

创建了一个 tag 为 demo-ssh:latest 的镜像。

运行容器

1docker run -d -p 2222:22 --name dev-container demo-ssh

映射了宿主机的 2222 端口到容器的 22 端口,这样就可以通过 SSH 连接到容器了。

ssh 登陆

 1~ ssh root@localhost -p 2222
 2The authenticity of host '[localhost]:2222 ([::1]:2222)' can't be established.
 3ED25519 key fingerprint is SHA256:m6vcc3uV+ZsEho1Ljf74IHA+EVUL+KmTmMWo/uhnIx4.
 4This key is not known by any other names.
 5Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
 6Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.
 7root@localhost's password:
 8   ,     #_
 9   ~\_  ####_        Amazon Linux 2023
10  ~~  \_#####\
11  ~~     \###|
12  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
13   ~~       V~' '->
14    ~~~         /
15      ~~._.   _/
16         _/ _/
17       _/m/'
18[root@c56f3ed9d155 ~]#

输入密码 changeme, 这样用 ssh 就登陆了 Docker 容器,再就是根据自己的开发需求安装相应的软件。

本文的内容也就差不多了,由于只在本地作为开发测试使用,安全性不用太过于考虑,顶多把密码设置稍为复杂一些。在 IDE 连接本地的 localhost:2222 SSH 服务设置时也只需要填入一次密码。

其他相关话题

想要免密码登陆的话,那就直接参考 创建可直接用 root 用户 ssh 登陆的 Docker 镜像创建免密登陆的镜像 一节,主动就是在构建时把本地的用 keygen 命令产生的 ~/.ssh/id_rsa.pub 内容拷入到 Docker 镜像的 /root/.ssh/authorized_keys 文件中。

像用 JetBrains 之类的 IDE 连接 Docker 容器后要能远程调试,它们会在容器中安装必要的代理软件,我们可以在容器不使用时 docker stop, 需要用的时候再 docker startdocker kill 也没多大关系,还是可用 docker start 启动的。如果用了 docker rm <容器id>, 那么下次启动时就是一个全新的容器了, 之前由 IDE 安装的代理软件又要重新安装了。

由 IDE 自动安装的软件可能难以配置到 Dockerfile 中,所以最好的办法是对容器当前状态进行备份,如 docker commit 保存当前状态。例如

1docker commit dev-container demo-ssh:backup
2
3# 下次启动就用
4docker run -d -p 2222:22 --name dev-container demo-ssh:backup

commit 了之后,电脑重启也不怕。如果镜像要与别人共享,可用 docker save, docker load 命令导出和导入镜像文件。

当 IDE 用 ssh 连接容器后会进行文件同步,项目文件不大的话,每次同步到容器中也行,或者在启动容器时用 -v <本地目录>:/work 映射到容器的一个卷, 这样下次启动容器时不须再将时行完整文件的同步。

本文碰到的两个问题

  1. 如果在 Dockerfile 中没有加 RUN ssh-keygen -A, 则在启动容器时报错 sshd: no hostkeys available -- exiting.
  2. 如果在 Dockerfile 中缺少 sed -i 's/^#\?UsePAM.*/UsePAM no/' /etc/ssh/sshd_config 的话容器可以启动,但用 ssh 登陆时客户端报错 root@localhost: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
永久链接 https://yanbin.blog/amazonlinux-2023-root-ssh-enabled-image/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。