Mac 上用 OrbStack + Docker + Pi Web 搭一套长期可用的 AI Coding Agent 环境
从 Docker 隔离、Pi Web 自动启动到 Context 管理,一篇完整记录实际搭建过程与踩坑的实战教程。
1. 为什么要这样搭
Pi 本身是一个自由度很高的 Coding Agent。
它可以:
- 读取文件
- 写文件
- 修改代码
- 执行 Shell
- 安装依赖
- 运行测试
- 调用 Git
- 持续循环完成开发任务
这种能力很好用,但也意味着:
如果直接把 Pi 放在 macOS 本机并给它很大的 Shell 权限,它理论上也能访问当前用户能访问的大量目录。
所以我的思路是:
给 Pi 一个完整 Linux 开发环境,让它在里面尽可能自由地工作,只把真正需要操作的项目目录共享进去。
最后得到的结构是:
┌────────────────────────┐
│ macOS │
│ │
│ Chrome / Edge / Safari │
│ http://127.0.0.1:30141 │
└───────────┬────────────┘
│
↓
┌────────────────────────┐
│ OrbStack │
│ Docker Runtime │
└───────────┬────────────┘
│
↓
┌────────────────────────┐
│ Debian 13 Container │
│ │
│ Git │
│ SSH │
│ Python │
│ Go │
│ Node.js │
│ Pi │
│ Pi Web │
│ │
│ /workspace │
└───────────┬────────────┘
│
↓
┌────────────────────────┐
│ macOS 本地项目目录 │
│ ~/work/pi-devbox/ │
│ workspace/ │
└────────────────────────┘
最终日常体验其实很简单:
打开 Mac
↓
OrbStack 自动启动
↓
Docker 容器自动恢复
↓
Pi Web 自动启动
↓
浏览器打开 http://127.0.0.1:30141
↓
开始 Coding
2. OrbStack 到底是什么
这是我一开始最疑惑的地方。
真正用下来以后,我会把 OrbStack 理解成:
Mac 上负责运行 Linux / Docker 的底层运行环境。
macOS 本身没有 Linux Kernel,而常见 Docker 镜像绝大多数运行的是 Linux。
所以在 Mac 上运行:
docker run alpine
背后一定需要某种 Linux 虚拟化环境。
常见选择包括:
Docker Desktop
Colima
OrbStack
这里使用 OrbStack。
它真正做的事情大致是:
Docker CLI
↓
OrbStack 提供 Docker Engine
↓
Linux 环境
↓
Container
所以实际使用以后,OrbStack 的存在感会非常低。
这反而是好事。
平时真正操作的是:
浏览器
↓
Pi Web
OrbStack 只负责安静地在后台托住 Docker / Linux 环境。
3. 安装并验证 OrbStack
如果已经安装 Homebrew:
brew install orbstack
然后启动:
open -a OrbStack
也可以:
orb start
查看当前 Docker context:
docker context show
正常应该输出:
orbstack
验证 Docker
执行:
docker run --rm alpine uname -m
Apple Silicon Mac 正常会输出:
aarch64
第一次执行时出现:
Unable to find image 'alpine:latest' locally
Pulling from library/alpine
...
是正常现象。
Docker 实际做了:
发现本地没有 Alpine
↓
从 Registry 下载
↓
创建临时 Container
↓
执行 uname -m
↓
输出 aarch64
↓
删除 Container
看到:
aarch64
说明:
OrbStack ✅
Docker Engine ✅
Linux Container ✅
ARM64 ✅
4. 创建项目目录
建议统一把这一套环境放在:
~/work/pi-devbox
为方便阅读,下文中的用户名、邮箱、密码都使用脱敏占位符。
创建目录:
mkdir -p ~/work/pi-devbox/workspace
cd ~/work/pi-devbox
最终目录结构:
pi-devbox/
├── Dockerfile
├── docker-compose.yml
├── mac.entrypoint.sh
├── .env
└── workspace/
以后真正的项目都放:
workspace/
例如:
workspace/
├── project-a/
├── project-b/
├── agent-demo/
└── rag-demo/
5. 先理解四个核心文件
这一部分非常重要。
刚开始接触 Docker 时,很容易把 Dockerfile、Compose 和 Shell 脚本混在一起。
其实它们负责的事情完全不同。
5.1 Dockerfile
可以理解为:
Linux 开发环境的装机清单。
例如:
RUN apt-get install ...
RUN npm install ...
最后得到:
Dockerfile
↓
docker build
↓
Docker Image
Image 可以理解成:
已经装好 Node、Go、Python、Pi、Pi Web 的系统模板。
5.2 docker-compose.yml
可以理解为:
这台 Container 启动时要怎么运行。
它定义:
- 容器叫什么
- 开放哪些端口
- 挂载哪些目录
- 使用哪些 Volume
- 传哪些环境变量
- 是否自动重启
5.3 .env
可以理解为:
会变化的参数配置文件。
例如:
ROOT_PASSWORD=<your-password>
GIT_USER_NAME=<your-git-name>
GIT_USER_EMAIL=<your-git-email>
这样用户名、密码、邮箱就不需要写死在 Dockerfile 中。
5.4 mac.entrypoint.sh
它才是真正的 Shell 脚本。
作用:
Container 每次启动以后,要执行哪些初始化操作。
例如:
恢复 /root 默认文件
↓
设置 Git 用户
↓
启动 SSH
↓
启动 Pi Web
6. 完整 Dockerfile
创建:
nano Dockerfile
内容:
FROM debian:13-slim
ENV LANG=C.UTF-8 \
LANGUAGE=C.UTF-8
# 基础工具
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
nano \
openssh-client \
openssh-server \
passwd \
unzip \
zip \
vim \
wget \
&& apt-get autoremove -y \
&& apt-get clean
# Git / SSH
RUN git config --system tag.gpgSign false \
&& git config --system commit.gpgsign false \
&& mkdir -p /run/sshd \
&& sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config \
&& sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
ENV PATH=$PATH:/usr/local/go/bin:/root/go/bin:/root/.local/bin
# 各种开发缓存统一放在容器内部 /cache
ENV GOMODCACHE=/cache/go-mod \
GOCACHE=/cache/go-build \
npm_config_cache=/cache/npm \
PIP_CACHE_DIR=/cache/pip
# Python
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN apt-get install -y --no-install-recommends \
python3 \
python3-pip \
&& pip3 config set --global global.index-url \
https://pypi.tuna.tsinghua.edu.cn/simple
# Go
ARG GOLANG_VERSION=1.27.1
RUN arch="$(dpkg --print-architecture)" \
&& wget -q https://go.dev/dl/go${GOLANG_VERSION}.linux-${arch}.tar.gz \
&& tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-${arch}.tar.gz \
&& rm -f go${GOLANG_VERSION}.linux-${arch}.tar.gz \
&& go env -w GOPROXY=https://goproxy.cn,direct \
&& go install -v golang.org/x/tools/gopls@latest \
&& go install -v github.com/go-delve/delve/cmd/dlv@latest \
&& go install -v honnef.co/go/tools/cmd/staticcheck@latest \
&& go clean -modcache \
&& go clean -cache
ENV GOPATH=/root/go
# Node.js 24 + TypeScript
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& apt-get autoremove -y \
&& apt-get clean \
&& npm config set registry https://registry.npmmirror.com --location=global \
&& npm install -g typescript ts-node \
&& npm cache clean --force
# Bash 自动补全
RUN apt-get update \
&& apt-get install -y --no-install-recommends bash-completion \
&& apt-get autoremove -y \
&& apt-get clean \
&& printf '%s\n' \
'' \
'if ! shopt -oq posix; then' \
' if [ -f /usr/share/bash-completion/bash_completion ]; then' \
' . /usr/share/bash-completion/bash_completion' \
' elif [ -f /etc/bash_completion ]; then' \
' . /etc/bash_completion' \
' fi' \
'fi' \
>> /etc/bash.bashrc
# Pi Agent
RUN npm install -g --ignore-scripts \
@earendil-works/pi-coding-agent \
&& npm cache clean --force
# Pi Web
RUN npm install -g @agegr/pi-web@latest \
--registry=https://registry.npmjs.org \
--fetch-retries=5 \
--fetch-retry-mintimeout=20000 \
--fetch-retry-maxtimeout=120000 \
&& npm cache clean --force
# 备份 /root 默认内容
RUN set -eux; \
mkdir -p /root-defaults; \
cp -a /root/. /root-defaults/
COPY mac.entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
WORKDIR /workspace
EXPOSE 22222
EXPOSE 30141
CMD ["/usr/local/bin/entrypoint.sh"]
保存:
Ctrl + O
Enter
Ctrl + X
7. 为什么要设置 cache
这里:
ENV GOMODCACHE=/cache/go-mod \
GOCACHE=/cache/go-build \
npm_config_cache=/cache/npm \
PIP_CACHE_DIR=/cache/pip
很实用。
它把:
Go Module Cache
Go Build Cache
npm Cache
pip Cache
统一放到:
/cache
而 /cache 不映射到 Mac。
所以这些临时文件:
留在 Container
Container 真删除时:
缓存一起回收
不会持续污染 Mac 本地目录。
8. 为什么要有 root-defaults
稍后会给 /root 挂持久化 Volume:
pi-root:/root
问题是:
Docker Volume 一旦挂到 /root,镜像中原本 /root 的内容会被遮住。
所以构建镜像时先:
/root
↓
/root-defaults
备份一份。
Container 启动后再:
/root-defaults
↓
/root
恢复默认内容。
9. 完整 mac.entrypoint.sh
创建:
nano mac.entrypoint.sh
内容:
#!/bin/bash
set -e
# 恢复镜像构建阶段备份的 /root 默认内容
cp -an /root-defaults/. /root/ 2>/dev/null || true
# Git 用户名
if [ -n "$GIT_USER_NAME" ]; then
git config --global user.name "$GIT_USER_NAME"
fi
# Git 邮箱
if [ -n "$GIT_USER_EMAIL" ]; then
git config --global user.email "$GIT_USER_EMAIL"
fi
# SSH root 密码
echo "root:${ROOT_PASSWORD:-root123}" | chpasswd
# 创建 SSH Host Keys
ssh-keygen -A
mkdir -p /run/sshd
echo "======================================"
echo " Pi Development Container"
echo "======================================"
echo ""
echo "Workspace:"
pwd
echo ""
echo "Architecture:"
uname -m
echo ""
echo "Node:"
node --version
echo ""
echo "npm:"
npm --version
echo ""
echo "Python:"
python3 --version
echo ""
echo "Go:"
go version
echo ""
echo "Pi:"
pi --version
echo ""
echo "======================================"
# SSH 后台运行
echo "Starting SSH..."
/usr/sbin/sshd -p 22222
# Pi Web 成为 Container 主进程
echo "Starting Pi Web..."
echo "Pi Web: http://127.0.0.1:30141"
exec pi-web \
-H 0.0.0.0 \
--no-open
保存:
Ctrl + O
Enter
Ctrl + X
然后:
chmod +x mac.entrypoint.sh
10. 逐行理解 entrypoint 脚本
10.1 Shebang
#!/bin/bash
表示:
使用 Bash 执行这个文件。
10.2 set -e
set -e
表示:
关键命令失败时停止整个脚本。
有些允许失败的命令会显式写:
xxx || true
表示:
这条失败我知道,继续执行。
10.3 恢复 root 默认内容
cp -an /root-defaults/. /root/ 2>/dev/null || true
其中:
cp
= copy
-a
= 保留目录、权限、时间等属性
-n
= 已经存在的文件不覆盖
10.4 判断环境变量是否为空
if [ -n "$GIT_USER_NAME" ]; then
git config --global user.name "$GIT_USER_NAME"
fi
其中:
[ -n "$GIT_USER_NAME" ]
表示:
如果这个字符串不为空。
10.5 默认值语法
${ROOT_PASSWORD:-root123}
意思是:
ROOT_PASSWORD 有值
→ 用 ROOT_PASSWORD
没有值
→ 用 root123
10.6 ssh-keygen -A
ssh-keygen -A
生成 SSH Server 所需的 Host Keys。
10.7 启动 SSH
/usr/sbin/sshd -p 22222
这里没有 -D。
所以 sshd 会自己进入后台。
10.8 exec pi-web
exec pi-web \
-H 0.0.0.0 \
--no-open
这里的:
\
表示下一行仍然属于同一条命令。
等价于:
exec pi-web -H 0.0.0.0 --no-open
普通:
pi-web
类似:
bash
↓
pi-web 子进程
而:
exec pi-web
表示:
用 Pi Web 直接替换当前 Bash 进程。
于是:
entrypoint.sh
↓ exec
Pi Web
Pi Web 会成为 Container 的主进程。
这意味着:
Pi Web 活着
↓
Container 活着
如果 Pi Web 意外退出:
Pi Web 退出
↓
Container 退出
↓
Docker restart policy 生效
↓
Container 自动恢复
这是整个自动启动链路里非常关键的一点。
11. 完整 docker-compose.yml
创建:
nano docker-compose.yml
内容:
services:
pi-dev:
build:
context: .
container_name: pi-dev
restart: unless-stopped
ports:
- "127.0.0.1:22222:22222"
- "127.0.0.1:30141:30141"
volumes:
- ./workspace:/workspace
- pi-root:/root
environment:
ROOT_PASSWORD: ${ROOT_PASSWORD}
GIT_USER_NAME: ${GIT_USER_NAME}
GIT_USER_EMAIL: ${GIT_USER_EMAIL}
volumes:
pi-root:
12. 为什么端口要绑定 127.0.0.1
例如:
- "127.0.0.1:30141:30141"
表示:
Mac
127.0.0.1:30141
↓
Docker
↓
Container
30141
这样 Pi Web 只提供给本机。
局域网其他机器无法直接通过:
Mac-IP:30141
访问。
考虑到 Pi Web 背后的 Agent 可以:
- 执行 Shell
- 修改代码
- 访问 workspace
默认只开放 localhost 更合理。
为什么 Container 内部又监听 0.0.0.0
entrypoint:
pi-web -H 0.0.0.0
这里是 Container 内部。
如果 Pi Web 只监听:
127.0.0.1
这个 localhost 指的是:
Container 自己
Docker 端口转发无法正常访问。
因此内部:
0.0.0.0:30141
外部:
127.0.0.1:30141
最终安全边界仍然在 Mac 侧。
13. 创建 .env
执行:
nano .env
例如:
ROOT_PASSWORD=<your-password>
GIT_USER_NAME=<your-git-name>
GIT_USER_EMAIL=<your-git-email>
保存以后:
chmod 600 .env
14. 构建并启动容器
执行:
docker compose up -d --build
其中:
--build
表示先重新构建 Image。
-d
表示 Container 后台运行。
查看 Container
docker ps
应该看到:
pi-dev
状态:
Up
查看日志
docker logs pi-dev
大致应该看到:
======================================
Pi Development Container
======================================
Workspace:
/workspace
Architecture:
aarch64
Node:
...
npm:
...
Python:
...
Go:
...
Pi:
...
======================================
Starting SSH...
Starting Pi Web...
Pi Web: http://127.0.0.1:30141
15. 实际踩坑一:docker.sock 不存在
第一次运行 Docker 时遇到过:
failed to connect to the docker API at
~/.orbstack/run/docker.sock
connect: no such file or directory
原因:
Docker CLI
已经指向 OrbStack
但
OrbStack Docker Engine
还没有真正启动
解决:
open -a OrbStack
orb start
然后:
docker info
最后重新验证:
docker run --rm alpine uname -m
16. 实际踩坑二:Pi Web npm 下载失败
构建阶段真实遇到过:
npm error network
In most cases you are behind a proxy
or have bad network settings.
最后:
failed to solve
RUN npm install -g @agegr/pi-web@latest
exit code: 1
因为前面全局配置过:
registry.npmmirror.com
而 Pi Web 这一步下载不稳定。
最终给 Pi Web 单独强制使用 npm 官方 Registry:
RUN npm install -g @agegr/pi-web@latest \
--registry=https://registry.npmjs.org \
--fetch-retries=5 \
--fetch-retry-mintimeout=20000 \
--fetch-retry-maxtimeout=120000 \
&& npm cache clean --force
然后重新:
docker compose up -d --build
成功。
17. 实际踩坑三:重启后 Pi Web is offline
有一次 Mac 重启以后,浏览器页面仍然存在,但显示:
Pi Web is offline
这个现象一开始很容易误判。
其实:
浏览器
缓存了 Pi Web 的前端页面。
所以 UI 还能显示。
但:
Pi Web Server
并没有真正启动。
于是前端只能显示:
offline
最后做了两个改动:
- Pi Web 全局安装进 Docker Image
- Pi Web 通过
exec成为 Container 主进程
也就是:
Container 启动
↓
entrypoint.sh
↓
启动 SSH
↓
exec pi-web
这样 Container 重启时,Pi Web 会自动恢复。
18. 项目目录如何映射
Compose:
- ./workspace:/workspace
例如 Mac:
/Users/<username>/work/pi-devbox/workspace/project-a
Container:
/workspace/project-a
Pi 修改:
/workspace/project-a/src/main.ts
Mac 上对应文件也会立刻变化。
这是 Docker bind mount。
注意安全边界
Docker 隔离了:
macOS 系统
其他未挂载目录
大量本地配置
但:
/workspace
是主动共享进去的。
所以:
rm -rf /workspace/*
真会删除 Mac 上 workspace 中的文件。
因此真实项目最好:
Git 管理
+
Container 隔离
例如执行大任务前:
git add .
git commit -m "checkpoint before agent task"
19. Pi 配置和会话如何持久化
Pi 的主要数据在:
/root/.pi
Compose:
- pi-root:/root
因此:
Pi Sessions
插件
模型配置
Provider 配置
其他 Pi 数据
都会进入:
pi-root
这个 Docker Volume。
所以:
关闭浏览器
✅ 数据还在
停止 Container
✅ 数据还在
重启 Container
✅ 数据还在
docker compose down
✅ 数据还在
重新 Build
✅ 数据还在
真正需要小心的是:
docker compose down -v
这里的:
-v
会删除 Volume。
没特殊需求不要执行。
20. Container 要不要一直挂后台
我的选择是:
日常一直挂着。
因为使用频率较高。
结构:
Mac 登录
↓
OrbStack
↓
Docker Engine
↓
pi-dev
↓
Pi Web
空闲时主要就是:
Linux Runtime
Node Web Server
Container
模型推理在远端 API。
所以不是 Mac 本地一直跑大模型。
如果几天不用,也可以直接在 OrbStack 中:
Containers
↓
pi-dev
↓
Stop
下一次:
Start
即可。
项目、Pi 配置、会话不会丢。
21. Pi Web 插件配置
环境跑通以后,在 Pi Web 中进入:
Settings
↓
Plugins
建议第一轮安装下面这些插件:
npm:@juicesharp/rpiv-ask-user-question
npm:@narumitw/pi-btw
npm:pi-context-view
npm:pi-open-tui
npm:@xyzensun/pi-mctx
建议使用:
Global
全局安装。
因为 /root 已经做了持久化,所以这些插件不会因为 Container 重建而消失。
22. 插件说明
22.1 ask-user-question
npm:@juicesharp/rpiv-ask-user-question
作用是给 Agent 增加结构化提问能力。
例如:
你准备采用哪一种认证方案?
○ JWT
○ Session
○ OAuth
遇到关键分叉时,Agent 可以先问你,而不是直接猜。
22.2 pi-btw
npm:@narumitw/pi-btw
这是很实用的一个插件。
例如当前 Agent 正在:
修改代码
↓
跑测试
↓
分析 Bug
突然想问:
这里为什么不用 Redis?
直接问会把这个问题塞进主 Context。
可以用:
/btw 为什么这里不用 Redis?
它相当于:
主 Agent Context
────────────────────→
↓
临时问题
↓
回答
────────────────────→
继续主任务
很适合开发过程中临时冒出来的小问题。
22.3 pi-context-view
npm:pi-context-view
主要用于观察:
System Prompt
Tools
Messages
Context
Pi Web 已经能显示不少 Context 信息,所以这个插件的重要性相对下降。
但第一轮体验可以保留。
22.4 pi-open-tui
npm:pi-open-tui
主要改善 Pi 终端 TUI。
如果主要入口是:
Pi Web
这个插件实际使用频率会比较低。
但保留也没问题。
22.5 pi-mctx
npm:@xyzensun/pi-mctx
这个非常值得理解。
它主要解决:
Coding Agent 长 Session 的 Context 管理。
/mctx sink
长时间 Coding 时,Agent 会产生大量:
read 文件结果
bash 输出
测试日志
Git diff
构建日志
这些 Tool Result 很容易把 Context 撑大。
执行:
/mctx sink
可以把已经不需要继续常驻 Context 的 Tool Result 移出去。
恢复:
/mctx sink --undo
/mctx new
这个更有意思。
可以理解成:
当前长 Session
↓
总结当前工作状态
↓
新建 Session
↓
注入总结
↓
继续工作
也就是把:
“总结一下当前工作”
↓
清理 Context
↓
重新开始
自动化。
对长时间 Coding 很实用。
23. 为什么暂时不继续堆插件
目前已经有:
Pi Web
├── Session
├── Models
├── Plugins
├── Skills
├── Files
├── Git
├── Context
└── Agent Tools
再继续堆:
MCP Adapter
Subagent
各种 Web 插件
各种 UI 插件
很容易出现:
Agent 还没真正用起来,环境已经越来越复杂。
更合理的思路是:
真实使用
↓
发现痛点
↓
再安装对应能力
24. 下一阶段:Skills
Plugins 更多是在修改:
Agent 的能力和运行行为
Skills 更像是:
告诉 Agent:
遇到某一类任务
应该怎么做
遵守什么流程
使用什么工具
例如以后可以沉淀:
Java / Spring Skill
RAG Skill
代码 Review Skill
数据库变更 Skill
Git 提交 Skill
测试 Skill
甚至项目自己带:
项目规范 Skill
这一块比盲目继续堆插件更值得投入。
25. 最终日常使用方式
搭好以后,日常基本不需要一直敲 Docker 命令。
使用方式:
打开 Mac
↓
OrbStack 自动工作
↓
pi-dev 自动启动
↓
Pi Web 自动启动
↓
浏览器打开收藏夹
地址:
http://127.0.0.1:30141
然后在 Pi Web 中选择:
/workspace/project-a
创建 Session,开始 Coding。
26. 最终架构
┌─────────────────────┐
│ Browser │
│ │
│ Pi Web │
│ localhost:30141 │
└──────────┬──────────┘
│
↓
┌────────────────────────────────────────────────────────┐
│ macOS │
│ │
│ ┌──────────────── OrbStack ────────────────────────┐ │
│ │ │ │
│ │ Docker Engine │ │
│ │ │ │ │
│ │ ↓ │ │
│ │ ┌────────────────────┐ │ │
│ │ │ pi-dev Container │ │ │
│ │ │ │ │ │
│ │ │ Debian 13 │ │ │
│ │ │ Git │ │ │
│ │ │ SSH │ │ │
│ │ │ Python │ │ │
│ │ │ Go │ │ │
│ │ │ Node │ │ │
│ │ │ Pi │ │ │
│ │ │ Pi Web │ │ │
│ │ │ │ │ │
│ │ │ /workspace ───────────────┐ │ │
│ │ │ /root ───────────┐ │ │ │
│ │ └────────────────────┘ │ │ │ │
│ │ │ │ │ │
│ │ Docker Volume │ │ │ │
│ │ pi-root ◀───────────────┘ │ │ │
│ └──────────────────────────────────────┼────────────┘ │
│ │ │
│ bind mount │
│ │ │
│ ↓ │
│ ~/work/pi-devbox/workspace │
│ │
└────────────────────────────────────────────────────────┘
27. 总结
这套东西搭完以后,最大的感受是:
一开始看起来是在折腾:
OrbStack
Docker
Shell
Volume
Port
真正获得的是一套:
可以长期使用、可以重建、可以持久化、隔离边界清晰的 AI Coding Agent 开发环境。
Pi 可以在 Linux Container 内拥有足够大的操作空间去:
安装依赖
运行命令
修改代码
跑测试
管理 Git
Mac 负责:
浏览器
IDE
项目文件
Docker 负责:
Agent 工作环境
两边职责非常清楚。
最终结构可以记成:
【可随时重建】
Docker Image
├── Debian
├── Node
├── Go
├── Python
├── Pi
└── Pi Web
【运行实例】
Container
└── pi-dev
【永久代码】
Mac
└── workspace
【永久 Agent 数据】
Docker Volume
└── pi-root
这里最值得记住的一句话是:
运行环境尽量做到可重建,真正的数据独立保存。
接下来真正值得投入时间的已经不是继续折腾 Docker,而是:
用真实项目跑 Pi
↓
熟悉 Context 管理
↓
沉淀 Skills
↓
优化自己的 Agent Harness
↓
观察哪些流程值得自动化
到这一步,Pi 才开始从“一个 Coding Agent”变成“自己可以逐渐塑造的开发环境”。