Docker SSH端口转发

Excerpt: 🤖本文介绍了一种基于Docker的SSH转发解决方案,通过在Ubuntu服务器上运行容器并配置端口映射,解决了老旧系统(如Ubuntu 18.04)上的软件兼容性问题,实现了标准化的开发环境配置和便捷的远程访问。

原文发表于: Docker SSH Forwarding - vluv's space

Introduction

最近在老旧系统上经常会遇到软件兼容性问题,实习申请的开发机信息如下

  • Remote Host:Ubuntu 18.04 LTS(glibc 2.27)

日常开发,存在以下package不兼容

Solutions(TL;DR)

针对老旧系统的兼容性问题,实践了两种方案

  1. 直接在远程主机上升级系统
  2. 在远程主机上运行 Docker 容器,使用 SSH 直接连接到 Ubuntu 主机上运行的 Docker 容器

命令提示符说明

> - LocalHost

$ - Remote Host(Ubuntu 18)

# - Docker Container

Option 2 的优势和使用docker作为开发环境的优势差不多

  • 环境配置标准化,易于共享和复制
  • ...

Option 1

参考如下命令升级Ubuntu系统,过程中有较详细的提示

shell 复制代码
# 更新软件包
$ 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-upgrades
Prompt=lts
# 执行升级,执行后会询问重启,或自行重启
$ sudo do-release-upgrade
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal

Option 2

Before

graph LR A[Windows 主机] -->|SSH 直接连接| B[Ubuntu 服务器] style A fill:#f5c2e7,stroke:#181825 style B fill:#b2bcfb,stroke:#181825

After

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 端口
dockerfile 复制代码
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

# 拷贝ssh
COPY ./.ssh /root/.ssh/
COPY ./.config /root/.config/

# 免输入yes
RUN echo "Host *\n\tHostKeyAlgorithms +ssh-rsa\n\tPubkeyAcceptedKeyTypes +ssh-rsa\n\tStrictHostKeyChecking no" > /root/.ssh/config

RUN sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

RUN echo 'root:root' | chpasswd
RUN chmod 600 /root/.ssh/id_rsa
RUN mkdir /var/run/sshd

EXPOSE 22

# 启动 SSH deamon service
ENTRYPOINT service ssh start && tail -f /dev/null

一次性在dockerfile中写完镜像的配置会比较麻烦,可以先在基于简单的dockerfile创建一个容器,进入container的shell交互环境,在容器内输入命令,安装好需要环境。

完成基础开发环境的配置后,再使用docker commit命令,将docker container打包成一个新的image

shell 复制代码
# 创建容器
$ 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 镜像

shell 复制代码
# 创建容器
$ docker build -t dev-image:latest .

运行 Docker 容器

shell 复制代码
# 运行容器
$ 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 文件

shell 复制代码
> cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_config
Host ubuntu
    HostName 10.21.163.77
    User root
    IdentityFile C:/Users/gjx/.ssh/id_rsa
    StrictHostKeyChecking no

Host docker
    HostName 10.21.163.77
    User root
    Port 8033

> ssh docker

5. 工作原理

这种连接方式涉及两层转发:

  1. Windows → Ubuntu 主机
  2. Ubuntu 主机端口 8033 → Docker 容器 22 端口
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 配置中添加相应条目:

shell 复制代码
> cat ~/.ssh/config
Host docker1
    HostName 10.21.163.77
    User root
    Port 8033

Host docker2
    HostName 10.21.163.77
    User root
    Port 8034
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
相关推荐
Clownseven1 小时前
SSH/RDP无法远程连接?腾讯云CVM及通用服务器连接失败原因与超全排查指南
服务器·ssh·腾讯云
ricky_fan1 小时前
window下配置ssh免密登录服务器
运维·服务器·ssh
Java陈序员2 小时前
再见 Navicat!一款开源的 Web 数据库管理工具!
java·react.js·docker
MickeyCV14 小时前
使用Docker部署MySQL&Redis容器与常见命令
redis·mysql·docker·容器·wsl·镜像
棠十一14 小时前
Rabbitmq
分布式·docker·rabbitmq
藥瓿亭15 小时前
K8S认证|CKS题库+答案| 6. 创建 Secret
运维·ubuntu·docker·云原生·容器·kubernetes·cks
2302_8097983216 小时前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器
嵌入式大圣16 小时前
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
运维·docker·容器
极简网络科技18 小时前
Docker、Wsl 打包迁移环境
运维·docker·容器
杨浦老苏18 小时前
轻量级Docker管理工具Docker Switchboard
运维·docker·群晖