Skip to content

Docker 远程直连部署 (Windows -> Linux)

文档目标: 记录从本地 Windows (Docker Desktop) 环境,通过 Docker Context 机制直接操控远程 Ubuntu 服务器 (PVE) 的完整工作流。彻底告别传统 docker save 导出镜像、SCP 传输、再 docker load 导入的繁琐流程。


不使用远程直连部署(借助1Panel\宝塔) :

本地打包生成镜像:

bash
docker buildx build --platform linux/amd64 -t app_name .

将镜像保存在项目根目录

bash
docker save -o app_name.tar app_name

将镜像文件app_name.tar上传到服务器项目目录,另外同时上传docker-compose.yml.env。 使用1Pannel容器编排,实例化容器并启动。

一、 核心原理解析

使用 Docker Context 远程直连的核心在于:代码在本地,算力在云端。 本地 Docker 客户端不再负责执行容器,而是将本地的构建上下文(代码、Dockerfile等)通过 SSH 通道流式传输给远程服务器,由服务器端的 Docker 引擎完成拉取、编译和运行。

二、 标准配置流程(最佳实践)

1. 配置 SSH 免密登录(⚠️ 极其关键)

Docker 的远程构建通道无法良好处理需要手动输入密码的交互提示。如果未配置免密,构建过程极易在 Transferring context 阶段卡死。

在 Windows 本地终端执行:

DOS

# 1. 生成密钥(一路回车即可)
ssh-keygen -t ed25519

# 2. 将公钥推送到远程服务器(替换为实际的用户名和 IP)
type C:\Users\Administrator\.ssh\id_ed25519.pub | ssh root@192.168.1.100 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 3. 测试免密登录(应该直接进入 Ubuntu,无需输入密码)
ssh root@192.168.1.100

2. 创建并切换 Docker 远程上下文

告诉本地 Docker Desktop 接管远程服务器。

DOS

# 1. 创建远程 Context
docker context create root-remote --docker "host=ssh://root@192.168.1.100"

# 2. 切换当前使用的 Context
docker context use root-remote

# 3. 验证是否接管成功(查看 Operating System 是否变为 Ubuntu)或者 docker ps
docker info

# 切换回本地环境
docker context use default

随着你管理的服务器变多,你可能会创建多个远程 Context。你可以随时使用下面这行命令来查看当前所有的环境列表:

docker context ls

输出示例:

Plaintex

NAME            TYPE    DESCRIPTION                               DOCKER ENDPOINT         
default * moby    Current DOCKER_HOST based configuration   npipe:////./pipe/docker_engine
root-remote     moby                                              ssh://root@192.168.1.100

注意看:列表里带星号 * 的那个,就是你当前正在使用的环境。

3. 配置 .dockerignore 排除庞大文件

为了保证 SSH 传输极速,必须在项目根目录创建 .dockerignore,排除无关环境和打包文件,防止 SSH 通道因传输大文件而拥堵甚至崩溃。

Plaintext

.git
.env
*.tar
*.tar.gz
__pycache__/
.venv/
.uv/
data/
logs/

4. 一键构建与部署

如果只有Dockerfile文件

现在你只需要像往常一样在本地执行命令,一切都会在远程服务器上发生:

Bash

# 在本地代码目录下执行,会将本地代码上下文发送到远程进行构建
docker build -t my-app:latest .

# 在远程服务器上启动容器
docker run -d -p 8080:8080 --name my-app-container my-app:latest

推荐写好 ocker-compose.yml

在项目根目录下执行以下命令,Docker 会自动将代码同步至远端并启动服务:

DOS

docker-compose up -d --build

(如果需要强制无缓存更新代码,可先执行 docker-compose build --no-cache)

  • docker build + docker run(命令驱动): 你需要把所有的配置(端口映射 -p、数据卷挂载 -v、环境变量 -e、网络 --network 等)全部写在命令行里。如果配置很多,这行命令会变得又长又难记。一旦终端关了或者历史记录清了,下次启动你可能就忘了参数是什么。
  • docker-compose(文件驱动/基础设施即代码): 所有的启动参数、环境配置都被固定写在了一个 docker-compose.yml 文件中。团队里的任何一个人拿到代码,只需要敲一行 docker-compose up -d --build,就能保证跑出来的环境和你一模一样。

三、 常见踩坑与解决方案记录

坑 1:路径解析报错 invalid volume specification

  • 现象docker-compose up 时提示找不到 D:\03_Code\Projects\...

  • 原因:在 docker-compose.yml 中使用了相对路径的“绑定挂载”(./data:/app/data)。在远程模式下,Windows 会将相对路径解析为 D 盘绝对路径传给 Ubuntu,导致 Linux 报错。

  • 解决方案:改用 Docker 命名卷(Named Volume),将数据存储的选址权交由远端 Docker 引擎接管。 YAML

    services:
      app:
        volumes:
          - aqi_data:/app/data  # 使用命名卷
    
    volumes:
      aqi_data:  # 底部声明命名卷

坑 2:构建卡死在 load metadata 阶段

  • 现象:终端一直卡在 #3 [internal] load metadata for docker.io/library/python:3.13.0-slim

  • 原因:服务器端的 Docker 镜像源失效或被墙,导致无法获取基础镜像信息。

  • 解决方案:进入远程服务器,清理失效的镜像源,配置国内稳定源。 Bash

    sudo bash -c 'cat > /etc/docker/daemon.json <<EOF
    {
      "registry-mirrors": [
        "https://docker.m.daocloud.io",
        "https://docker.nju.edu.cn",
        "https://dockerproxy.com"
      ]
    }
    EOF'
    sudo systemctl restart docker

坑 3:特定镜像库(如 ghcr.io)下载龟速

  • 现象docker.io 的镜像拉取正常,但遇到 ghcr.io(GitHub 容器库)时,每秒仅几十 KB。

  • 原因:常规国内 Docker 镜像源仅加速 Docker Hub,对 GitHub Packages 无效。

  • 解决方案:修改 Dockerfile,将 ghcr.io 替换为国内的高校/代理镜像源(如南京大学源)。 Dockerfile

    # 修改前
    # COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
    
    # 修改后
    COPY --from=ghcr.nju.edu.cn/astral-sh/uv:latest /uv /uvx /bin/

坑 4:Git 提交失败 does not have a commit checked out

  • 现象:本地执行 git add . 报错,拒绝添加子目录。

  • 原因:不小心在项目中创建了嵌套的 .git 文件夹(套娃仓库),被识别为未初始化的 Submodule。

  • 解决方案:删除嵌套的 .git 文件夹,清理缓存后重新提交。 Bash

    rm -rf service/.git
    git rm --cached service
    git add .