返回

用 Docker 容器取代虚拟机实现远程开发

探讨如何使用 Docker 容器替代虚拟机进行高效远程开发
2025-07-16
5542 字 · 约 14 分钟阅读

在 Windows 下使用远程开发是当下非常流行的开发方式,相较于本地开发,优势在于:

  • 原生Linux开发环境
  • 无缝跨平台开发
  • 统一的开发体验

在远程开发中,虚拟机是最常用的方式之一,但它也有一些缺点:

  1. 隔离性:虚拟系统与宿主系统是完全隔离的,在部分开发场景需要反复下载上传文件(如配置文件),涉及调试web时也要更改网络地址
  2. 硬件资源切割:虚拟机需要规划好性能,提前划出硬盘、CPU、网络、显卡等资源作为独立的虚拟资源,只能给一个虚拟机使用 CUDA 套件

Docker 的轻量级虚拟弥补这 2 个缺点,进程级别的隔离,资源共享,且支持 CUDA 套件等硬件资源的共享

下面实践基于 Debian12.7 容器作为开发容器的过程和涉及到一些问题

1. Debian 容器

容器实现目标如下:

  1. Host网络:采用 host 网络,无需映射端口方便web应用调试
  2. 持久化存储:对代码目录做持久化存储,和宿主机双向绑定,方便更改文件

为了方便迁移容器,此次采用 Docker Compose 来构建

1.1. 镜像构建

Docker 设计理念与虚拟机不同,一个容器是生命进程等于一个应用的生命进程,而不是虚拟机这种完全独立的操作系统

所以要给容器一个永久运行的应用,这里选用 SSH 服务,构建一个 Dockerfile 文件如下:

FROM debian:12.7

ENV TZ=Asia/Shanghai

# 设置代理(可选)
ENV http_proxy=http://localhost:8080
ENV https_proxy=http://localhost:8080


# 更改apt源为清华源(可选)
# RUN sed -i.bak 's|http://deb.debian.org|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources && \
#     sed -i.bak 's|http://security.debian.org|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources

# 安装常用工具和软件包
RUN apt-get update && \
    apt-get install -y openssh-server && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# 配置 SSH 服务
RUN mkdir -p /run/sshd && \
    ssh-keygen -A && \
    echo 'root:root' | chpasswd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    sed -i 's/#Port 22/Port 57623/' /etc/ssh/sshd_config

EXPOSE 57623

CMD ["/usr/sbin/sshd", "-D"]

说明:

  1. 基于 Debian 12.7 镜像
  2. 安装常用工具,包括 SSH 服务、编辑器、网络工具等
  3. 配置 SSH 服务,允许 root 用户登录,并修改 SSH 端口为 57623,避免冲突

构建镜像确保没有问题:

sudo docker build -t debian:12.7-dev . --no-cache

1.2. 映射目录

除了要将代码目录映射给容器外,为了重启后不丢失开发环境,推荐将一些常规的目录也映射到容器内,如:

  • /etc 系统配置目录
  • /root 用户目录

可以添加其他你认为需要的目录,但这些系统目录初始化不可为空,所以需要先运行容器,再将目录作为模板复制到宿主机上

先运行一个一次性容器:

docker run --name debian12.7 --rm -it --entrypoint /bin/bash debian:12.7-dev

另开终端,将刚才运行的容器内目录作为模板复制到宿主机上:

docker cp debian12.7:/root ./
docker cp debian12.7:/etc ./

最后创建一个目录用于存放代码文件,并将容器的代码目录与宿主机进行绑定

mkdir -p codes

再将上面的 Dockerfile 也放入到目录中,再创建一个 compose.yaml 文件,最终目录如下:

$ tree -L 1      
.
├── compose.yaml
├── Dockerfile
├── etc
└── root

3 directories, 2 files

compose.yaml 文件的内容如下:

services:
  debian12.7-dev:
    build: ./
    image: debian:12.7-dev
    container_name: debian12.7-dev
    restart: unless-stopped
    environment:
      - TZ=Asia/Shanghai
    network_mode: host
    hostname: debian12.7-dev
    stdin_open: true
    tty: true
    volumes:
      - ./codes:/codes
      - ./root:/root
      - ./etc:/etc

文件说明:

  • build:指定 Dockerfile 路径
  • image:指定镜像名称为 debian-develop:12.7
  • environment:设置环境变量,如时区、NVIDIA 显卡等

1.3. 运行

compose 的目录下,执行:

sudo docker-compose up -d

运行成功后,在宿主机使用ssh容器连接

ssh root@127.0.0.1 -p 57623

连接后可以根据需要自行进行系统设置了

2. 使用

2.1. 备份

在使用过程中,可能会对容器进行一些系统设置或安装一些软件,这时可以将当前容器保存为一个新的镜像,以便后续使用或迁移

以上面的容器为例,创建一个新的备份镜像:

sudo docker commit my-develop my-develop_backup_image

如果需要迁移,或者考虑冷备的话还可以将这个新的备份镜像保存为 tar 文件

sudo docker save -o my-develop_backup_image.tar my-develop_backup_image

迁移到其他具备 docker 环境的服务器上,使用load就可以将这个镜像重新导入

docker load -i my-develop_backup_image.tar

2.2. CUDA 应用开发

如果需要用到 CUDA 显卡等,可以在 Dockerfile 中更换为 CUDA 的官方镜像,CUDA 的安装可以参考 NVIDIA Docker,只需将镜像更换为 nvcr.io/nvidia/pytorch:25.04-py3 或其他 CUDA 镜像即可

例如修改 Dockerfile 如下:

FROM nvcr.io/nvidia/pytorch:23.12-py3

ENV TZ=Asia/Shanghai \
    http_proxy=http://localhost:8080 \
    https_proxy=http://localhost:8080 \
    SSH_PORT=57623

# 安装常用工具和软件包
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        openssh-server vim wget git zsh curl gcc make openssl ffmpeg tree \
        p7zip-full unzip screen net-tools build-essential && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# 配置 SSH 服务
RUN mkdir -p /run/sshd /root/.ssh && \
    ssh-keygen -A && \
    echo 'root:root' | chpasswd && \
    sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/;s/#Port 22/Port ${SSH_PORT}/" /etc/ssh/sshd_config
    
CMD ["/usr/sbin/sshd", "-D"]

compose.yaml 文件参考如下:

services:
  pytorch23.12-dev:
    build: ./
    image: my-pytorch:latest
    container_name: pytorch23.12-dev
    restart: unless-stopped
    environment:
      - TZ=Asia/Shanghai
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=all
      - SAGEATTN_FORCE_SM90=1
      - CUDA_VISIBLE_DEVICES=0
      - no_proxy=localhost,192.168.10.3
      - NO_PROXY=localhost,192.168.10.3
    runtime: nvidia
    network_mode: host
    hostname: pytorch23.12-dev
    stdin_open: true
    tty: true
    volumes:
      - ./codes:/codes
      - ./root:/root
      - ./etc:/etc

2.3. GUI开发

在开发时,会有一些程序需要显示 GUI 图形界面,这就需要借助 VcXsrvXming 等 X Server 程序

X Server 实现了远程服务器上运行GUI程序,并在本地计算机中显示其内容的功能

其工作原理如下:

借助这个技术,可以在远程开发时使用开发一些GUI程序,非常方便

实现步骤如下

  1. 安装运行 VcXsrv 程序,并依次检查 Multiple Windows-Start no client-Disable access control 三个选项都勾选了
  2. 使用任意SSH客户端连接远程服务器,要设置 启用X11转发 选项(如:ssh -x username@hostname
  3. 运行任意GUI程序即可在本地看到GUI内容

首先在本地Windows中安装 VcXsrv 程序

  • 下载地址:https://github.com/ArcticaProject/vcxsrv/releases

安装后打开,记得勾选下面这个选项免去访问控制,之后根据需要自行启用

接着使用任何ssh客户端,我用的是 tabby,打开具体ssh服务器设置,并勾选 X11转发 ,如下

登录服务器后,运行用于测试的 X11-apps GUI程序,如下:

sudo apt install x11-apps

# 执行 xclock 程序
xclock

接着运行xclock,效果如下

3. 一些实际问题

由于 Docker 镜像并非完整操作系统,在日常使用会出现不少小问题,以下是一些记录与修复

3.1. 光标输入错位

这是缺失中文编码的问题,输入 locale 可以检查,如下:

$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=zh_CN.UTF-8
LC_TIME=zh_CN.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=zh_CN.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=zh_CN.UTF-8
LC_NAME=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
LC_TELEPHONE=zh_CN.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION=zh_CN.UTF-8
LC_ALL=

修复需要安装locales,如下:”

apt install -y locales

运行选择默认的语言编码

dpkg-reconfigure locales

在弹出的所有语言编码中选择你需要的默认语言编码,我这里选择的是120. en_US.UTF-8 UTF-8

留言

发表留言