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
相关推荐
THMAIL1 小时前
mac M芯片运行docker-desktop异常问题
macos·docker·容器
两点王爷2 小时前
IDEA中springboot项目中连接docker
spring boot·docker·intellij-idea
家庭云计算专家2 小时前
还没用过智能文档编辑器吗?带有AI插件的ONLYOFFICE介绍
服务器·人工智能·docker·容器·编辑器
孤的心了不冷5 小时前
【Docker】CentOS 8.2 安装Docker教程
linux·运维·docker·容器·eureka·centos
头疼的程序员6 小时前
docker学习与使用(概念、镜像、容器、数据卷、dockerfile等)
学习·docker·容器
IT小郭.6 小时前
使用 Docker Desktop 安装 Neo4j 知识图谱
windows·python·sql·docker·知识图谱·database·neo4j
淡水猫.6 小时前
hbit资产收集工具Docker(笔记版)
运维·docker·容器
旧故新长15 小时前
访问 Docker 官方镜像源(包括代理)全部被“重置连接”或超时
运维·docker·容器
white.tie15 小时前
Docker部署单节点Elasticsearch
elasticsearch·docker·jenkins
程序猫A建仔17 小时前
【物联网】基于树莓派的物联网开发【4】——WIFI+SSH远程登录树莓派
运维·物联网·ssh