
#trae #ubuntu #remote-ssh 

```table-of-contents
```

### 1. 整体架构图示

- **Ubuntu 2 (Dev Server):** 存放源码，运行 `tiktok_pm` 容器（代码挂载），Trae 通过 SSH 远程连接此处。
    
- **Ubuntu 1 (Prod Server):** 运行 `tiktok_pm` 容器（镜像打包），通过 Docker 卷持久化数据，不挂载源码。
    
- **ThinkBook (Local):** 仅作为 UI 端，通过 Trae 连接 Ubuntu 2 进行开发。

### 2. Ubuntu 2：开发环境配置 (Dev)

这是您主要的工作区。路径：`/home/shenwei/docker/tiktok_pm`

#### A. 目录结构

``` bash
/home/shenwei/docker/tiktok_pm/
├── src/                # Django 源代码仓库
├── docker-compose.yml   # 开发环境 Compose
├── .env.dev            # 开发环境变量
└── Dockerfile          # 开发/生产共用基础镜像定义
```

#### B. 开发环境 `docker-compose.yml`

开发环境的核心在于 **Bind Mount**（绑定挂载），实现代码修改实时生效。

### 3. 具体配置 (ThinkBook)
#### 第一阶段：基础设施层配置 (Connectivity & Permissions)

在配置 IDE 之前，必须确保 SSH 连接是免密的，并且你的 Ubuntu 用户有权直接操作 Docker，否则 Trae 的远程插件会因为权限弹窗而连接失败或功能受限。

##### 1. 配置 SSH 免密登录 (本地机器 -> Ubuntu2 Server)

Trae 的远程连接依赖于非交互式登录。

- **本地机器（客户端）生成密钥对**（如果已有可跳过）：
    
    Bash
    
    ```
    ssh-keygen -t rsa -b 4096
    ```
    
- **将公钥上传至 Ubuntu2 Server**：
    ```
    # 替换 user 和 ip
    ssh-copy-id -i ~/.ssh/id_rsa.pub shenwei@192.168.3.45
    ```
    
- **配置 SSH Config 文件**（推荐）： 在本地 `~/.ssh/config` (Mac/Linux) 或 `%USERPROFILE%\.ssh\config` (Windows) 中添加别名，方便 Trae 读取。
    
```
Host ubuntu2
    HostName 192.168.3.45
    User shenwei
    Port 22
    IdentityFile "C:\Users\ishenwei\.ssh\id_rsa"  # 你的私钥路径
Host ubuntu2-ext # 公网访问
    HostName ubuntu2.ishenwei.online:60024
    User shenwei
    Port 22
    IdentityFile "C:\Users\ishenwei\.ssh\id_rsa"  # 你的私钥路径
Host ubuntu1
    HostName 192.168.3.47
    User shenwei
    Port 22
    IdentityFile "C:\Users\ishenwei\.ssh\id_rsa"  # 你的私钥路径
Host ubuntu1-ext # 公网访问
    HostName ubuntu1.ishenwei.online:60022
    User shenwei
    Port 22
    IdentityFile "C:\Users\ishenwei\.ssh\id_rsa"  # 你的私钥路径
```

在 Ubuntu Server 上，你的用户必须在 `docker` 用户组中，否则 Trae 无法列出容器。

- **SSH 登录服务器执行：**
    
    Bash
    
    ```
    sudo usermod -aG docker $USER
    # 必须注销并重新登录，或执行以下命令使组变更立即生效
    newgrp docker
    ```
    
- **验证：** 执行 `docker ps`，如果不需要 sudo 且能列出容器，则配置成功。
    

---

#### 第二阶段：Trae 客户端配置 (IDE Setup)

Trae 原生支持 VS Code 的插件生态，我们需要利用 Remote Development 能力。

##### 1. 安装 Trae 及必要插件

打开 Trae，在左侧扩展市场（Extensions）中搜索并安装（如果尚未预装）：

- **Remote - SSH** (必装)
    
- **Docker** (Microsoft 出品，必装)
    
- **Dev Containers** (如果你计划使用 `.devcontainer` 模式开发，强烈推荐)
    

##### 2. 建立远程连接

1. 使用快捷键 `Ctrl/Cmd + Shift + P` 调出命令面板。
    
2. 输入并选择：`Remote-SSH: Connect to Host...`。
    
3. 选择你在 SSH Config 中配置的 `ubuntu2`。
    
4. Trae 会在远程服务器上安装 **VS Code Server (Trae Server)** 代理组件。首次连接需要几十秒。
    

---

#### 第三阶段：开发模式选择 (Workflow Configuration)

针对 Docker 项目，你有两种主要的开发模式，根据你的需求选择：

##### 模式 A：Attach 到正在运行的容器 (推荐用于调试)

这种模式下，你直接“进入”已经在 Ubuntu 上跑起来的 Docker 容器进行代码修改。

1. **连接成功后**，在 Trae 左侧侧边栏找到 **Docker** 图标。
    
2. 在 **Containers** 列表中，找到你的目标项目容器。
    
3. 右键点击该容器，选择 **"Attach Visual Studio Code"** (或 Trae 对应选项)。
    
4. Trae 会打开一个新的窗口，此时你的 IDE **实际上是运行在 Docker 容器内部**。
    
5. **优点**：环境完全隔离，直接使用容器内的 Python/Node/Go 环境，无需在 Ubuntu 宿主机安装语言环境。
    

##### 模式 B：远程编辑宿主机文件 + Docker CLI (推荐用于编排)

这种模式下，你编辑的是 Ubuntu 文件系统上的代码 (`/home/user/project`)，但在终端调用 Docker 命令。

1. **连接成功后**，点击 "Open Folder"。
    
2. 选择 Ubuntu 上 `docker-compose.yml` 或项目代码所在的路径。
    
3. 打开终端 (`Ctrl + ~`)，直接执行 `docker compose up -d` 等命令。
    
4. **优点**：适合管理 `docker-compose.yml` 文件本身，或者同时管理多个微服务容器的配置。
    

---

#### 第四阶段：解决常见“坑” (Troubleshooting)

根据经验，在内网开发 Docker 项目常遇到以下问题，请提前规避：

1. **Git 凭证问题**：
    
    - 如果在容器内开发（模式 A），容器内可能没有你的 SSH Key 或 Git 配置。
        
    - **解决**：Trae/VS Code 通常会自动转发本地的 SSH Agent。确保本地运行了 SSH Agent (`eval "$(ssh-agent -s)" && ssh-add`)，这样容器内拉取代码使用的是你本地的 Key。
        
2. **文件权限 (UID/GID) 问题**：
    
    - 如果使用 Volume 挂载（将 Ubuntu 目录挂载进容器），容器内生成的 Build 文件可能归属于 `root`，导致你在宿主机无法删除或修改。
        
    - **解决**：在 Dockerfile 中创建与宿主机相同 UID 的用户，或在 `docker-compose.yml` 中指定 `user: "${UID}:${GID}"`。
        
3. **内网穿透 (如果不只是局域网)**：
    
    - 如果你离开办公地点，需要从公网访问这个内网 Server。
        
    - **建议**：不要直接暴露 SSH 端口。在 Ubuntu 上安装 **Tailscale** 或 **Cloudflare Tunnel**。
        
    - 如果使用 Tailscale，Trae 的 SSH Config HostName 可以直接填 Tailscale 的 IP (如 `100.x.x.x`)，实现无缝切换。