在 Windows 下使用远程开发是当下非常流行的开发方式,相较于本地开发,优势在于:
- 原生Linux开发环境
- 无缝跨平台开发
- 统一的开发体验
在远程开发中,虚拟机是最常用的方式之一,但它也有一些缺点:
- 隔离性:虚拟系统与宿主系统是完全隔离的,在部分开发场景需要反复下载上传文件(如配置文件),涉及调试web时也要更改网络地址
- 硬件资源切割:虚拟机需要规划好性能,提前划出硬盘、CPU、网络、显卡等资源作为独立的虚拟资源,只能给一个虚拟机使用 CUDA 套件
Docker 的轻量级虚拟弥补这 2 个缺点,进程级别的隔离,资源共享,且支持 CUDA 套件等硬件资源的共享
下面实践基于 Debian12.7 容器作为开发容器的过程和涉及到一些问题
1. Debian 容器
容器实现目标如下:
- Host网络:采用
host
网络,无需映射端口方便web应用调试 - 持久化存储:对代码目录做持久化存储,和宿主机双向绑定,方便更改文件
为了方便迁移容器,此次采用 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"]
说明:
- 基于
Debian 12.7
镜像 - 安装常用工具,包括 SSH 服务、编辑器、网络工具等
- 配置 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 图形界面,这就需要借助 VcXsrv 或 Xming 等 X Server 程序
X Server 实现了远程服务器上运行GUI程序,并在本地计算机中显示其内容的功能
其工作原理如下:
借助这个技术,可以在远程开发时使用开发一些GUI程序,非常方便
实现步骤如下
- 安装运行 VcXsrv 程序,并依次检查
Multiple Windows
-Start no client
-Disable access control
三个选项都勾选了 - 使用任意SSH客户端连接远程服务器,要设置 启用X11转发 选项(如:
ssh -x username@hostname
) - 运行任意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