容器化远程开发环境:code-server + SSH + Python 自启动配置

核心目标

构建一个包含 Python + code-server(网页版 VS Code) + SSH 的 Docker 镜像,通过 docker-compose 实现:

  • 外部可访问 code-server(浏览器)和 SSH(终端);
  • 容器内多服务(SSH/code-server)自启动;
  • 容器开机自启 + 数据持久化;
  • 环境可配置、可扩展。
技术选型底层逻辑
组件 选型理由
基础镜像 ubuntu:22.04 相比 CentOS,Ubuntu 对 code-server/python 生态兼容性更好,包源更新更及时;22.04 为 LTS 版本,稳定。
进程管理 supervisord Docker 容器默认仅支持单进程前台运行,supervisord 可管理多进程(SSH+code-server),并实现进程异常重启。
端口规划 SSH 用容器内 22 端口(映射宿主机 2222,避免和宿主机 SSH 冲突);code-server 用容器内 8080 端口(映射宿主机 8080)。
数据持久化 挂载宿主机目录到容器 /workspace,确保代码 / 配置不会随容器删除丢失。

二、文件结构与逐行解析(核心文件)

1. 完整文件目录结构
复制代码
dev-env/  # 项目根目录
├── Dockerfile          # 镜像构建脚本
├── supervisord.conf    # 多进程自启动配置
├── docker-compose.yml  # 容器编排配置
└── workspace/          # 代码持久化目录(自动创建)
2. Dockerfile 逐行深度解析
复制代码
# 基础镜像:选择Ubuntu 22.04 LTS(长期支持版,稳定)
FROM ubuntu:22.04

# 维护者信息(可选,便于镜像管理)
MAINTAINER dev <dev@example.com>

# 环境变量配置:
# 1. DEBIAN_FRONTEND=noninteractive:禁用Ubuntu安装时的交互提示(如时区选择)
# 2. CODE_SERVER_PASSWORD:code-server访问密码(默认值,可被docker-compose覆盖)
# 3. SSH_PASSWORD:SSH登录root密码(默认值,可被docker-compose覆盖)
ENV DEBIAN_FRONTEND=noninteractive
ENV CODE_SERVER_PASSWORD=123456
ENV SSH_PASSWORD=123456

# 安装系统依赖:
# - openssh-server:SSH服务核心包
# - python3/python3-pip:Python环境(Ubuntu22.04默认python3.10)
# - wget:下载code-server安装脚本
# - supervisor:多进程管理工具
# && rm -rf /var/lib/apt/lists/*:清理apt缓存,减小镜像体积
RUN apt update && apt install -y \
    openssh-server \
    python3 \
    python3-pip \
    wget \
    supervisor \
    && rm -rf /var/lib/apt/lists/*

# 安装code-server:
# 1. 下载官方安装脚本到/tmp目录
# 2. 赋予执行权限
# 3. --method=standalone:独立安装(不依赖系统包管理器);--prefix=/usr/local:安装到系统目录,方便全局调用
RUN wget https://code-server.dev/install.sh -O /tmp/install.sh \
    && chmod +x /tmp/install.sh \
    && /tmp/install.sh --method=standalone --prefix=/usr/local

# 配置SSH服务:
# 1. mkdir -p /var/run/sshd:创建SSH运行时目录(SSHD启动必需)
# 2. echo "root:${SSH_PASSWORD}" | chpasswd:设置root用户密码(读取环境变量)
# 3. sed修改sshd_config:允许root通过SSH登录(默认禁止),关闭DNS解析(加速SSH连接)
RUN mkdir -p /var/run/sshd \
    && echo "root:${SSH_PASSWORD}" | chpasswd \
    && sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config \
    && sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config

# 配置supervisord:
# 1. 创建supervisord配置目录
# 2. 拷贝宿主机的supervisord.conf到容器指定目录(后续编写该文件)
RUN mkdir -p /etc/supervisor/conf.d
COPY supervisord.conf /etc/supervisor/supervisord.conf

# 暴露端口:
# - 22:容器内SSH端口
# - 8080:容器内code-server端口
# 注:仅声明端口,实际映射需在docker-compose中配置
EXPOSE 22 8080

# 容器启动命令:
# 启动supervisord,加载指定配置文件,前台运行(适配Docker容器运行规则)
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
3. supervisord.conf (多进程管理核心)
复制代码
# [supervisord]:主进程配置
[supervisord]
nodaemon=true  # 关键:禁止supervisord后台运行(Docker容器要求前台进程,否则容器会退出)
logfile=/var/log/supervisord.log  # 主日志文件路径
pidfile=/var/run/supervisord.pid  # 进程PID文件路径

# [program:sshd]:SSH服务子进程配置
[program:sshd]
command=/usr/sbin/sshd -D  # 启动SSH(-D:前台运行,适配supervisord)
autostart=true  # 容器启动时自动启动SSH
autorestart=true  # SSH进程异常退出时自动重启
stdout_logfile=/var/log/sshd.log  # SSH标准输出日志
stderr_logfile=/var/log/sshd.err  # SSH错误输出日志

# [program:code-server]:code-server服务子进程配置
[program:code-server]
# 启动命令:
# --bind-addr 0.0.0.0:8080:绑定到容器所有IP的8080端口(允许外部访问)
# --auth password:密码认证模式
# --password ${CODE_SERVER_PASSWORD}:认证密码(读取环境变量)
# /workspace:code-server默认工作目录(后续挂载到宿主机)
command=code-server --bind-addr 0.0.0.0:8080 --auth password --password ${CODE_SERVER_PASSWORD} /workspace
autostart=true  # 容器启动时自动启动code-server
autorestart=true  # code-server异常退出时自动重启
stdout_logfile=/var/log/code-server.log  # code-server标准输出日志
stderr_logfile=/var/log/code-server.err  # code-server错误输出日志
user=root  # 以root用户运行(避免权限问题)
directory=/workspace  # 工作目录
priority=10  # 启动优先级(数字越小越先启动,这里SSH优先)
4. docker-compose.yml 逐行解析(容器编排核心)
复制代码
# docker-compose版本(3.8适配Docker 19.03+,兼容性好)
version: '3.8'

# 服务定义
services:
  # 服务名:dev-env(自定义)
  dev-env:
    # 构建配置:基于当前目录的Dockerfile构建镜像
    build: .
    # 镜像标签:构建后镜像名为dev-env:python-code-ssh(便于识别)
    image: dev-env:python-code-ssh
    # 容器名:dev-env(自定义,便于管理)
    container_name: dev-env
    # 端口映射:
    # - 宿主机2222端口 → 容器22端口(SSH)
    # - 宿主机8080端口 → 容器8080端口(code-server)
    ports:
      - "2222:22"
      - "8080:8080"
    # 数据卷挂载:
    # 宿主机./workspace目录 → 容器/workspace目录(代码持久化)
    # 注:./workspace相对路径,对应docker-compose.yml所在目录
    volumes:
      - ./workspace:/workspace
    # 重启策略:
    # always:无论容器正常退出/异常退出,都自动重启;宿主机开机时也会自动启动容器
    restart: always
    # 特权模式:解决SSH/端口绑定等权限问题(生产环境可按需关闭,仅开发环境推荐)
    privileged: true
    # 环境变量覆盖:
    # 替换Dockerfile中的默认密码(更安全,避免硬编码)
    environment:
      - CODE_SERVER_PASSWORD=mycode123  # 自定义code-server密码
      - SSH_PASSWORD=myssh123           # 自定义SSH密码

三、完整操作步骤

步骤 1:准备工作(宿主机环境)

确保宿主机已安装 Docker 和 docker-compose:

复制代码
# 安装Docker(Ubuntu/CentOS通用脚本)
curl -fsSL https://get.docker.com | bash -s docker

# 安装docker-compose
curl -L "https://github.com/docker/compose/releases/download/v2.24.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# 验证安装
docker --version
docker-compose --version
步骤 2:创建项目目录与文件
复制代码
# 创建项目根目录
mkdir -p ~/dev-env && cd ~/dev-env

# 创建空文件(后续粘贴内容)
touch Dockerfile supervisord.conf docker-compose.yml

# 创建代码持久化目录
mkdir -p workspace
步骤 3:编写文件内容

将上述 Dockerfile、supervisord.conf、docker-compose.yml 的内容分别粘贴到对应文件中(可通过 vim/vi 编辑)。

步骤 4:构建并启动容器
复制代码
# 进入项目目录
cd ~/dev-env

# 构建镜像 + 启动容器(-d:后台运行;--build:强制重新构建镜像)
docker-compose up -d --build

# 查看容器状态(确认Up状态)
docker-compose ps
# 或
docker ps | grep dev-env

✅ 成功标志:输出中dev-env容器状态为Up

步骤 5:多维度验证服务可用性
验证 1:访问 code-server(浏览器)
  1. 打开浏览器,输入:http://宿主机IP:8080(如http://192.168.1.100:8080);
  2. 输入 docker-compose.yml 中配置的CODE_SERVER_PASSWORD(示例:mycode123);
  3. ✅ 成功标志:进入 VS Code 网页版,左侧文件管理器显示/workspace目录(和宿主机~/dev-env/workspace同步)。
验证 2:SSH 连接容器
复制代码
# 宿主机/其他机器执行(替换为你的宿主机IP)
ssh root@192.168.1.100 -p 2222
  1. 输入 docker-compose.yml 中配置的SSH_PASSWORD(示例:myssh123);

  2. ✅ 成功标志:登录到容器终端,执行以下命令验证环境:

    复制代码
    # 验证Python
    python3 --version  # 输出Python 3.10.x
    pip3 --version     # 输出pip版本
    
    # 验证code-server
    code-server --version  # 输出code-server版本
    
    # 验证SSH进程
    ps aux | grep sshd    # 输出sshd进程
验证 3:自启动功能
复制代码
# 手动重启容器
docker restart dev-env

# 查看容器内进程(确认SSH/code-server都在运行)
docker exec dev-env ps aux
# ✅ 成功标志:输出包含sshd、code-server、supervisord进程

# 验证开机自启(可选)
reboot  # 重启宿主机
# 重启后执行
docker ps | grep dev-env
# ✅ 成功标志:容器状态为Up
验证 4:数据持久化
  1. 在 code-server 中创建文件/workspace/test.py,写入:print("Hello Docker!")
  2. 宿主机查看~/dev-env/workspace/test.py,✅ 成功标志:文件存在且内容一致;
  3. 停止并删除容器:docker stop dev-env && docker rm dev-env
  4. 重新启动容器:docker-compose up -d
  5. ✅ 成功标志:~/dev-env/workspace/test.py文件仍存在,code-server 中可正常查看 / 编辑。

四、进阶配置与优化

1. SSH 密钥登录(替代密码,更安全)
复制代码
# 宿主机生成SSH密钥(无密码回车)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/dev-env-key

# 将公钥拷贝到容器(先启动容器)
docker cp ~/.ssh/dev-env-key.pub dev-env:/root/.ssh/authorized_keys

# 进入容器配置权限(关键:SSH对权限要求严格)
docker exec -it dev-env /bin/bash
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
service ssh restart

# 宿主机用密钥登录
ssh root@宿主机IP -p 2222 -i ~/.ssh/dev-env-key
2. 扩展 Python 依赖(预装常用包)

修改 Dockerfile,在安装 python3-pip 后添加:

复制代码
# 预装常用Python包(如numpy/pandas/flask)
RUN pip3 install numpy pandas flask -i https://pypi.tuna.tsinghua.edu.cn/simple

-i指定清华源,加速安装)

3. 自定义 code-server 配置(如插件自动安装)

在 docker-compose.yml 的 volumes 中添加:

复制代码
volumes:
  - ./workspace:/workspace
  - ./code-server-config:/root/.config/code-server  # 挂载code-server配置目录

宿主机./code-server-config/extensions目录放入插件包,容器启动后自动加载;./code-server-config/config.yaml可自定义 code-server 配置。

4. 端口冲突解决

若宿主机 8080/2222 端口被占用,修改 docker-compose.yml 的 ports:

复制代码
ports:
  - "2223:22"  # 宿主机2223→容器22
  - "8081:8080" # 宿主机8081→容器8080

五、常见问题排查

问题现象 排查方案
code-server 无法访问 1. 检查容器状态:docker ps;2. 检查端口映射:`netstat -tulpn grep 8080;3. 查看日志:docker logs dev-env --tail 100`
SSH 登录失败 1. 检查密码是否正确;2. 检查容器 22 端口是否映射:docker port dev-env;3. 进入容器查看 SSHD 日志:cat /var/log/sshd.err
容器启动后立即退出 1. 查看 supervisord 日志:docker exec dev-env cat /var/log/supervisord.log;2. 确认 supervisord.conf 中nodaemon=true
数据持久化失效 检查 volumes 配置:`docker inspect dev-env grep Mounts`,确认宿主机目录正确挂载

总结

  1. 核心逻辑 :通过supervisord解决 Docker 单进程限制,实现 SSH+code-server 自启动;通过 docker-compose 的restart: always实现容器开机自启;通过 volume 挂载实现数据持久化。
  2. 访问方式
    • code-server:浏览器http://宿主机IP:8080(密码认证);
    • SSH:ssh root@宿主机IP -p 2222(密码 / 密钥认证)。
  3. 扩展性:可通过修改 Dockerfile 预装 Python 依赖,通过 volume 挂载自定义 code-server 配置,适配不同开发场景。
  4. 安全性:生产环境建议禁用 root 密码登录,改用 SSH 密钥;修改默认端口和密码,避免弱口令。

完整覆盖了「镜像构建→容器编排→服务验证→进阶优化→问题排查」全流程,可直接落地为生产 / 开发用的 Docker 虚拟环境。

相关推荐
Benszen6 小时前
Docker容器化解决方案全解析
运维·docker·容器
badhope6 小时前
Docker从零开始安装配置全攻略
运维·人工智能·vscode·python·docker·容器·github
用户075494284547 小时前
🚀 OpenClaw Docker+Minimax部署完全指南:踩坑记录与解决方案
docker
无盐海7 小时前
Linux vi 命令 Docker命令
linux·docker
杨浦老苏9 小时前
零人类公司编排框架Paperclip的安装
人工智能·docker·ai·群晖
L-影9 小时前
部署本地Dify过程,使用Dify的前期准备
人工智能·docker·ai·dify
Hi2024021711 小时前
AI编程助手Claude Code、Codex、OpenCode一站式Docker环境
docker·容器·ai编程
minstbe12 小时前
IC设计私有化AI助手实战:基于Docker+OpenCode+Ollama的数字前端综合增强方案(基础版)
前端·人工智能·docker
Keanu-12 小时前
【无标题】
docker·云原生