Docker SSH Forwarding
Introduction
最近在老旧系统上经常会遇到软件兼容性问题,实习申请的开发机信息如下
- Remote Host:Ubuntu 18.04 LTS(glibc 2.27)
日常开发,存在以下package不兼容
- VSCode (Version >= 1.99)
- NodeJS:node.js - Getting GLIBC_2.28 not found - Stack Overflow
- fastfetch,如果是ubuntu18,需要自行编译得到可执行文件
Solutions(TL;DR)
针对老旧系统的兼容性问题,实践了两种方案
- 直接在远程主机上升级系统
- 在远程主机上运行 Docker 容器,使用 SSH 直接连接到 Ubuntu 主机上运行的 Docker 容器
>
- LocalHost$
- Remote Host(Ubuntu 18)#
- Docker Container
Option 2 的优势和使用docker作为开发环境的优势差不多
- 环境配置标准化,易于共享和复制
- …
Option 1
参考如下命令升级Ubuntu系统,过程中有较详细的提示
# 更新软件包$ sudo apt-get update$ sudo apt-get upgrade$ sudo apt-get dist-upgrade# 安装升级工具$ sudo apt install update-manager-core# 编辑升级配置文件,末行配置为lts,保存退出$ sudo vim /etc/update-manager/release-upgradesPrompt=lts# 执行升级,执行后会询问重启,或自行重启$ sudo do-release-upgrade$ lsb_release -aNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 20.04.6 LTSRelease: 20.04Codename: focal
Option 2
Before
View Mermaid diagram code
graph LR
A[Windows 主机] -->|SSH 直接连接| B[Ubuntu 服务器]
style A fill:#f5c2e7,stroke:#181825
style B fill:#b2bcfb,stroke:#181825
After
View Mermaid diagram code
graph LR
A[Windows 主机] -->|SSH 连接| B[Ubuntu 服务器]
B -->|启动容器,将容器22端口映射为Ubuntu 8033端口| C[Docker 容器]
A -->|SSH ubuntu:8033端口| C
style A fill:#f5c2e7,stroke:#181825
style B fill:#b2bcfb,stroke:#181825
style C fill:#a6e3a1,stroke:#181825
Docker SSH Forwarding
创建 Dockerfile
创建一个目录,用于构建 Docker 镜像,可以将.ssh
,.config
,.vscode-server
等目录拷贝在这,基本都可以复用

- 安装必要工具:vim、SSH 服务、fish shell 和 fzf 工具
- 配置 SSH,允许 root 登录,设置密码为 root(optional)
- 复制主机的 SSH 密钥到容器中,实现无密码登录
- 开放 22 端口
FROM artifactory.momenta.works/docker/python:3.11# 安装 vim 和其他必要软件包RUN apt-get update && \ apt update && \ apt-get install -y vim && \ apt-get install -y openssh-server -y && \ apt install fish -y && \ apt install fzf# 拷贝sshCOPY ./.ssh /root/.ssh/COPY ./.config /root/.config/# 免输入yesRUN echo "Host *\n\tHostKeyAlgorithms +ssh-rsa\n\tPubkeyAcceptedKeyTypes +ssh-rsa\n\tStrictHostKeyChecking no" > /root/.ssh/configRUN sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_configRUN echo 'root:root' | chpasswdRUN chmod 600 /root/.ssh/id_rsaRUN mkdir /var/run/sshdEXPOSE 22# 启动 SSH deamon serviceENTRYPOINT service ssh start && tail -f /dev/null
一次性在dockerfile中写完镜像的配置会比较麻烦,可以先在基于简单的dockerfile创建一个容器,进入container的shell交互环境,在容器内输入命令,安装好需要环境。
完成基础开发环境的配置后,再使用docker commit命令,将docker container打包成一个新的imagemage环境的配置一次在dockerfile中写完可能会比较麻烦,建议可以先在本地创建一个docker container,安装好需要的环境后,commit成一个新的image
# 创建容器$ docker run -it --name dev-image --hostname=dk --privileged=true --net=bridge -p 8033:22 debian:bookworm# 进入容器$ docker exec -it dev-image /bin/bash# 安装需要的环境$ apt-get update && \ apt update && \ apt install <xxx># 退出容器$ exit# 提交容器为新的镜像$ docker commit dev-image dev-image:latest
构建 Docker 镜像
# 创建容器$ docker build -t dev-image:latest .
运行 Docker 容器
# 运行容器$ docker run -it --name ssh --hostname=dk --privileged=true --net=bridge -p 8033:22 dev-image:latest
参数说明:
--name ssh
: 设置容器名称为 ssh--hostname=dk
: 设置容器主机名--privileged=true
: 赋予容器特权模式--net=bridge
: 使用桥接网络模式-p 8033:22
: 将容器 22 端口映射到主机的 8033 端口
如果需要持久化数据,可以使用 -v
参数挂载数据卷,例如:-v /path/on/host:/path/in/container
。
可以执行docker exec -it <container-name> /bin/bash
进入容器,或者使用docker exec -it <container-name> /bin/fish
进入fish shell。
LocalHost SSH Config
编辑 ~/.ssh/config
文件
> cat ~/.ssh/config# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost ubuntu HostName 10.21.163.77 User root IdentityFile C:/Users/gjx/.ssh/id_rsa StrictHostKeyChecking noHost docker HostName 10.21.163.77 User root Port 8033> ssh docker
5. 工作原理
这种连接方式涉及两层转发:
- Windows → Ubuntu 主机
- Ubuntu 主机端口 8033 → Docker 容器 22 端口
View Mermaid diagram code
sequenceDiagram
participant W as Windows
participant U as Ubuntu 主机
participant D as Docker 容器
W->>U: SSH 连接到端口 8033
U->>D: 端口映射 8033->22
D-->>W: SSH 会话建立
Note over W,D: 直接连接的效果
当需要连接多个 Docker 容器时,可以为每个容器映射不同的端口,并在 SSH 配置中添加相应条目:
> cat ~/.ssh/configHost docker1 HostName 10.21.163.77 User root Port 8033Host docker2 HostName 10.21.163.77 User root Port 8034
View Mermaid diagram code
graph TB
subgraph Windows
ssh[SSH 客户端]
end
subgraph Ubuntu主机["Ubuntu 主机 (10.21.163.77)"]
port1[端口 8033]
port2[端口 8034]
end
subgraph Docker容器
container1[容器1 - 端口22]
container2[容器2 - 端口22]
end
ssh -->|ssh docker1| port1
ssh -->|ssh docker2| port2
port1 --> container1
port2 --> container2
style Windows fill:#f5c2e7,stroke:#181825
style Ubuntu主机 fill:#b2bcfb,stroke:#181825
style Docker容器 fill:#a6e3a1,stroke:#181825
style ssh stroke:#181825,color:#11111e
style port1 stroke:#181825,color:#11111e
style port2 stroke:#181825,color:#11111e
style container1 stroke:#181825,color:#11111e
style container2 stroke:#181825,color:#11111e
Docker SSH Forwarding