课程大纲
课程大纲系列主页
学习进度已完成 0/19

W1 · 开营、工具地基(沙箱 · SSH · Git)

入门进行中Docker2 天前更新

Phase 1 · 基础与安全前置 · 第 1 周。本周不写正经代码,目标是看清终点、摆正预期,再把往后 15 周天天要用的工具地基打好——会用终端、搭一个出问题也不影响主力电脑的隔离沙箱、配好 SSH 密钥、建起一个逐周累积到结课的 Git 仓库。内容偏多,分两半:上半场到「沙箱跑通」,下半场 SSH + Git。沙箱一旦跑通、仓库一旦建好,后面 15 周都在这套环境里操作、逐周往仓库里累积。

本周一句话

用几分钟交代这门课要做成什么、Agent 和普通脚本差在哪,剩下全周把往后天天要用的工具地基打好:会用终端、亲手搭一个出问题也不影响主力电脑的隔离沙箱、配好 SSH 密钥、建起一个逐周累积到结课的 Git 仓库。

学完能做到

  • 说得清这门课最后要交出什么,心里有一张课程地图。
  • 说得清 Agent(看屏幕自己决策)和普通脚本(每步写死)差在哪、各自什么时候用。
  • 会用终端:用 pwd / ls / cd / mkdir 在目录间走动,分得清绝对路径和相对路径,知道命令要在对的目录里敲。
  • 用人话讲清 Docker 的镜像、容器、仓库分别是什么,看懂一个 docker-compose.yml 在配什么,会用 up / ps / logs / down 管自己的沙箱。
  • 在自己机器(或云环境)跑通一个隔离沙箱,浏览器里看到它的桌面,并在里面跑通一个最简自动化。
  • 讲得清 SSH 的密钥对原理,会生成密钥、把公钥加到 GitHub、用 ssh 连上一台远程机器或容器。
  • 会建 Git 仓库并写好 .gitignore,完成 add / commit / push 推上 GitHub;改坏了能用 restore / revert 退回,知道分支是干什么的。

前置要求

  • 一台能装 Docker 的电脑(macOS / Windows / Linux);陪跑版直接用配好的云环境。
  • 不需要任何编程基础。
  • Windows 用户提前确认能开 WSL2(Docker Desktop 依赖)。
  • 内存建议 ≥ 8GB(桌面容器吃内存)。
  • 注册一个 GitHub 账号(下半场连远程要用,免费)。

开营:这门课要做成什么

先放一段期末成品给个锚点:给 Agent 一句话——比如「把这个文件夹里几十份 PDF 的关键信息读出来整理成 Excel」——它自己看屏幕、点鼠标,把活干完。16 周后,你能亲手做出这个。

把丑话说在前面:这门课要动手、要交作业,每周 8–10 小时。Computer Use 今天还不便宜、不算快、也不是每次都稳。课程教的是技术和判断力,不承诺学完就能接单赚钱,也不承诺产出能直接商用。第一周就把预期摆正,比中途才发现不匹配好。

Agent 和普通脚本差在哪

这门课会先教你写普通脚本打底(W2–W8),再教你让 AI 看屏幕自己决策、做成 Agent(W9 起)。今天先把这一个区别记住就够:

  • 普通脚本(确定性脚本):每一步都写死——点这个坐标、输这串字、等 2 秒。它不看屏幕,照着跑;界面一变就点错。适合步骤固定、不变的活。你 W2、W3 先学写的就是这种。
  • Agent:看截图 → 看懂当前画面 → 自己决定下一步 → 动手 → 再看结果对不对。界面变了能随机应变。代价是慢(每步调一次大模型)、按次花钱、偶尔出错。这种 W9 起自己做。

一句话记住:普通脚本是「照剧本演」,Agent 是「看着情况临场发挥」。固定的活写脚本更快、更稳、更便宜;要「盯着屏幕随机应变」的活,才值得上 Agent。别一上来就想全用 Agent——能写死的部分写死,真要判断的才交给模型,这个取舍后面会反复遇到。

命令行入门:先会用终端

下一步就要你敲 docker compose up -d,可没写过代码的人多半连终端都没打开过。这一段把「终端是什么、命令往哪敲」讲清楚,后面 Docker、SSH、Git 全靠它。原则跟学 Python 一样——只讲这周用得上的。

终端是什么:一个靠打字下命令、而不是点图标来操作电脑的窗口。你敲一行命令、回车,它执行完把结果打回来。Docker、Git、SSH 这些工具都没有图标可点,只能在终端里用,所以先过这一关。

怎么打开

  • macOS:「终端.app」(Terminal),默认是 zsh。
  • Windows:用 PowerShell(或装 Windows Terminal),别用老的 cmd。
  • 沙箱里:搭好的那个 Linux 桌面自带终端,默认 bash。

三处长得像、用法九成相同,少数命令有差别,遇到会点出来。

四条命令,先记住这几条

  • pwd —— 我现在在哪个目录(print working directory)。
  • ls —— 这个目录里有什么(PowerShell 里 ls 也能用)。
  • cd 目录名 —— 进到某个目录;cd .. 退回上一级;cd ~ 回家目录。
  • mkdir 名字 —— 新建一个目录。

就这几个动词,配上下面的「路径」,覆盖你这周九成操作。复制文件、看文件内容用到再查。

路径:命令在「哪」执行很关键

  • 绝对路径:从根写全,如 /Users/你/cua-camp(Windows 形如 C:\Users\你\cua-camp)。
  • 相对路径:相对你「现在所在的目录」,如 cd cua-camp. 是当前目录、.. 是上一级。
  • ~ 是你的家目录(macOS / Linux)。

命令要在对的目录里敲。 后面 docker compose upgit commit 都得在放着对应文件的那个目录里执行,敲错地方就找不到文件——先 pwd 看清自己在哪。

两个省力技巧:打几个字按 Tab 自动补全目录名 / 文件名,少打也少打错;按 方向键调出上一条命令,改一点再回车,不用重打。

现在就动手:建一个 cua-camp 目录当本课主目录。

bash
mkdir cua-camp
cd cua-camp
pwd

pwd 会打印你现在所在的目录,看到这条路径就对了:

text
/Users/你/cua-camp          # Windows 形如 C:\Users\你\cua-camp

这个目录下一段拿来放 compose 文件,下半场在里面建 Git 仓库,往后每周代码也放它——这是你整门课的家。目录名用英文、别带空格和中文;Windows 路径用反斜杠 \、macOS / Linux 用正斜杠 /;命令和参数之间要留空格。

实战视频 · W1-1
加载视频中

为什么第一周就搭沙箱

先说一句风险:Agent 是会看错、点错的程序——社区里出现过它误删整个用户目录、执行危险命令的真实案例。本周的沙箱只是练习场,搞砸了重建就好;但要先建立敬畏:等 W9 起真做能自己决策的 Agent,碰到删文件、改配置、花钱这类不可逆操作,必须留一道人类确认。

安全观先行。Agent 要替你点鼠标、敲键盘,等于把电脑钥匙交给一段还会看错点错的程序。先把它关进隔离环境,搞砸了也碰不到真系统、真文件、真账号。

市面课大多把沙箱当成最后才讲的生产化话题,前 8 到 10 周让你裸机操作;这门课反过来,第一周就给你一个怎么操作都不影响主力机的练习环境。本周只求跑通最简沙箱,生产级深度定制(持久化、双平台、宿主调度)留到 W13。

本周要搭的东西怎么配合,先看一张全景图——代码在宿主机改、沙箱里跑,SSH 配好密钥,Git 推上 GitHub:

W1 开发环境地基全景:宿主机上的代码目录挂进 Docker 沙箱(webtop 桌面),配好 SSH 密钥,用 Git 推到 GitHubW1 开发环境地基全景:宿主机上的代码目录挂进 Docker 沙箱(webtop 桌面),配好 SSH 密钥,用 Git 推到 GitHub

搞懂 Docker:你在操作什么

市面课常常一句「装个 Docker、跑这条命令」就过去,敲错了也不知道错在哪。这里花点功夫把「在操作什么」讲明白,后面出问题才知道往哪儿查。原则照旧——只讲这周用得上的。

一句话讲清 Docker:它让你在自己电脑里,快速起一个「装好了系统和软件、跟主系统隔开」的隔离环境。里面怎么操作都行,关闭后就清空,外面的真系统毫发无损。

三个词先认准,记住就够用

  • 镜像(image):一个只读的模板,打包好了系统和软件。可以想成一张「装好系统和软件的光盘」。我们用的 webtop 镜像,就打包好了「Linux 桌面 + 浏览器」。
  • 容器(container):用镜像跑起来、正在运行的那个隔离环境。同一个镜像能起好几个容器,互不影响。我们的沙箱就是一个容器。
  • 仓库(registry):存放镜像的服务,可以想成「应用商店」。本地没有这个镜像,docker 就去仓库下载(拉,pull)。默认仓库(Docker Hub)在海外,国内连着慢,所以下面动手时要给它配个代理加速。

串起来一句话——镜像是模板,容器是用模板跑起来的隔离环境,仓库是下载镜像的地方。

跟虚拟机有什么区别:两者都能隔离。虚拟机相当于「在你电脑里再开一整台电脑」,重、慢、占地方;容器跟你的系统共用底层,只打包应用和它要的依赖,秒级启动、占用小。当练习环境,容器又轻又够隔离。更深的(内核、命名空间)留到 W13 讲生产级,这周不碰。

这周你只会用到这几条命令

  • docker run hello-world —— 装好后的自检,拉个最小镜像跑一下。
  • docker compose up -d —— 照 compose 文件把沙箱启动起来;-d 是后台运行,不占用你的终端。
  • docker compose ps —— 看容器起没起来、状态对不对。
  • docker compose logs —— 起不来时第一件事:看它到底报什么错。
  • docker compose down —— 停掉并删掉这个沙箱容器(挂载文件夹里的数据不受影响)。

就这五条,覆盖你这周绝大部分操作。其余的(docker ps 看所有容器、docker stop 停某个)用到再查。

读懂 docker-compose.yml:对着「配套代码」里的 compose 文件,只盯四样——

  • image: 用哪个镜像(这里是 webtop)。
  • ports: 把容器里的端口接到你电脑的端口。这里接出两个:3001(https,浏览器开 https://localhost:3001 看桌面)和 3000(http 备用)。冒号左边是你电脑的端口、右边是容器的端口,左边被占用就改左边(如 3002:3001)。
  • volumes: ./sandbox-data:/config 把容器里的 /config 接到当前文件夹下的 sandbox-data./ 就是 compose 所在的那个文件夹,比如 sandbox/);桌面数据落在你硬盘上、跟着容器自己的文件夹走,容器删了重建数据还在。
  • environment: 时区、用户 ID 这类设置。其中 PIXELFLUX_WAYLAND=false 这一行要留着——它强制沙箱用 X11,后面 W3 / W4 的自动化才打得动(原因下面动手部分会说)。剩下 shm_sizesecurity_opt 是桌面应用要用的,照抄即可。

compose 文件就是一张配置单——用哪个镜像、开哪个端口、把哪个文件夹接进来、配哪些环境变量。这四样看懂,市面上多数 compose 文件你都读得动。

易错点:镜像 ≠ 容器(模板 ≠ 跑起来的环境);up 是起、down 是删、stop 只停不删;命令要在放着 compose 文件的那个目录里敲。

动手:搭沙箱 + 跑通 hello world

装 Docker

  • macOS / Windows:装 Docker Desktop(Windows 安装时启用 WSL2 后端)。macOS 注意选对芯片——Apple Silicon(M 系列)选 Apple chip 版,Intel Mac 选 Intel 版,装错起不来。
  • Linux:装 Docker Engine + docker compose 插件。
  • 验证:终端跑 docker run hello-world,打印出 Hello from Docker! 开头的一段欢迎信息就算装好(它顺手演示了「拉镜像 → 起容器 → 跑完退出」整条链路)。这条也要从 Docker Hub 拉镜像,国内若卡着不动,先做下面的「配代理加速」再回来跑。

配代理加速(国内必做,否则卡在拉镜像):webtop 镜像有几百 MB 到 1GB+,默认从海外仓库拉,国内经常卡着不动。让 Docker 走你的 Clash 代理去拉,别用国内镜像源 / 镜像加速器——镜像站只同步了一部分镜像,碰到它没收录或被过滤掉的就直接拉不到(webtop、官方 demo 这类不保证都在),而且公共镜像源这两年时常关停失效。代理直连 Docker Hub、只换条路出去,拉什么都不挑。前提:你有一个能用的 Clash(ClashX / Clash for Windows / Clash Verge 这类),全程在图形界面里点:

  1. 在 Clash 里拿两样东西:HTTP 代理端口(在客户端「General / 设置」页能看到,ClashX、Clash for Windows 默认 7890,Clash Verge 默认 7897,以你客户端里显示的为准);打开「Allow LAN / 允许局域网连接」开关(不打开,Docker 那个虚拟机连不到你的代理,Windows 尤其必须开)。
  2. 在 Docker Desktop 里填代理:Settings → Resources → Proxies(部分版本在 Settings → Proxies)→ 打开「Manual proxy configuration」,HTTP 和 HTTPS 两栏填同一个地址(端口换成你上一步看到的实际端口)——macOShttp://127.0.0.1:7890Windowshttp://host.docker.internal:7890(WSL2 里的 127.0.0.1 指向虚拟机自己、连不到宿主机的 Clash,要用 host.docker.internal 指回你的电脑);「No Proxy」一栏填 localhost,127.0.0.1;点「Apply & Restart」。
  3. 验证docker info 往下翻,看到 HTTP Proxy / HTTPS Proxy 是你填的地址,再跑 docker run hello-world 能秒拉下来、打印 Hello from Docker!,就通了。

连不上就按这个顺序排查:① 先确认 Clash 的 Allow LAN 开着——这步让 Clash 从只监听本机改成监听 0.0.0.0,Docker 的虚拟机才连得到;② Mac 和 Windows 把 127.0.0.1host.docker.internal 互换试一下;③ Windows 仍然不通,十有八九是防火墙挡了端口、或 WSL2 网络绕路——最稳的兜底是直接填你电脑的局域网 IP(PowerShell 跑 ipconfig 看 IPv4 地址,填成 http://192.168.1.x:7890 这种),必要时再给这个端口加一条 Windows 防火墙入站规则。

不是你网络坏了,是默认仓库在海外,配好代理就快了。

一键起沙箱:先立个好习惯——一个容器一个独立文件夹,compose 放进去、数据卷也挂在这个文件夹里,互不混、删起来干净。在 cua-camp 里给沙箱单开一个 sandbox 文件夹,把「配套代码」的 docker-compose.yml 放进去,进到该文件夹再起:

bash
mkdir sandbox                 # 在 cua-camp 里给沙箱容器单开一个文件夹
# 把配套代码的 docker-compose.yml 放进这个 sandbox 文件夹
cd sandbox
docker compose up -d          # compose 和数据(sandbox-data)都待在 sandbox 文件夹里

起好后大概是这样(两个 表示网络和容器都拉起来了):

text
[+] Running 2/2
 ✔ Network sandbox_default   Created
 ✔ Container cua-sandbox     Started

第一次会先拉镜像(配了代理会快很多),起好后浏览器打开 https://localhost:3001。第一次会弹「您的连接不是私密连接 / 不安全」——这是容器的自签证书,点「高级 → 继续前往 localhost」就进去了(这是你本机的容器,放心点)。进去就能看到容器里的 Linux 桌面,这块桌面跟你的真系统完全隔开。顺手 docker compose ps 看状态,STATUS 那列是 Up 就对了,起不来就 docker compose logs 看报错:

text
NAME          IMAGE                                    STATUS         PORTS
cua-sandbox   lscr.io/linuxserver/webtop:ubuntu-xfce   Up 12 seconds  0.0.0.0:3001->3001/tcp, 0.0.0.0:3000->3000/tcp
实战视频 · W1-2
加载视频中

跑通 hello world:在沙箱桌面里打开终端,装好 Python + pyautogui,跑一个最简脚本(见「配套代码」),看着鼠标自己在桌面上画出方块轨迹、最后弹一个窗——这是你第一次亲眼看到「程序自己在操作电脑」,也是后面 W3、W4 那些自动化脚本的最小原型。把这个 hello_world.py 也在 cua-camp 里存一份,下半场建 Git 仓库时一起提交。

实战视频 · W1-3待录制

不练了就在 sandbox 文件夹里 docker compose down 把容器停掉删掉;桌面数据存在 sandbox/sandbox-data 文件夹里不会丢,下次 up 回来还在。


以下是下半场(第 2 次录播):SSH + Git。 上半场到这里告一段落——沙箱跑通、hello world 动起来,已经是个完整的阶段成果。下半场把开发环境配齐:SSH 密钥 + 一个推上 GitHub 的结课作品仓库。

SSH:用密钥安全连上另一台机器

SSH 是下一段 Git 的前置——往 GitHub 推代码靠 SSH 密钥免密认证;陪跑版连云环境、远程操作沙箱也都用它。

SSH 是什么:一种加密的远程登录方式,让你在自己电脑的终端里,安全地操作「另一台机器」——可能是云服务器,也可能是一个容器。传输全程加密,中途被截走也看不懂。

为什么用密钥、不用密码:密码登录每次都要输,弱密码会被暴力猜,密码本身也可能在传输或服务器端被记录。密钥登录是你在本机生成一对密钥——

  • 公钥.pub 结尾):交给对方(GitHub、服务器),可以公开。可以想成一把交给别人保管的锁。
  • 私钥:只留在你自己机器,永远不外传、永远不提交进 Git。可以想成唯一能开那把锁的钥匙。

对方拿公钥验、你拿私钥应答,对得上才放行。一次配好,往后免密码。

实战视频 · W1-4待录制

生成密钥对

bash
ssh-keygen -t ed25519 -C "你的邮箱"

一路回车用默认(方括号处直接回车),过程大概是这样:

text
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/你/.ssh/id_ed25519): [回车]
Enter passphrase (empty for no passphrase): [回车]
Enter same passphrase again: [回车]
Your identification has been saved in /Users/你/.ssh/id_ed25519
Your public key has been saved in /Users/你/.ssh/id_ed25519.pub

密钥存在 ~/.ssh/id_ed25519(私钥)、id_ed25519.pub(公钥)。.pub 那个是公钥,能贴出去;没后缀的是私钥,谁都不给。

连 GitHub:先用 cat ~/.ssh/id_ed25519.pub 打印公钥,它是 ssh-ed25519 AAAA... 你的邮箱 这样一整行,整行复制 → GitHub Settings → SSH and GPG keys → New SSH key → 贴上保存。验证:

第一次问 yes / no 输 yes(写入 known_hosts),看到这句就通了:

text
Hi 你的用户名! You've successfully authenticated, but GitHub does not provide shell access.

提示「does not provide shell access」是正常的,GitHub 本来就不给终端访问。这一步配好,下一段往 GitHub 推代码就不用反复输密码。

连云主机(陪跑版真实用到)

bash
ssh 用户名@主机地址        # 例 ssh [email protected]

把公钥放到服务器上(陪跑版已配好),就能直接进,操作那台远程机器像操作本机终端一样。自学版没有云主机也没关系,理解「ssh 用户@地址 就能连上去」这个形状即可。

连沙箱容器:本地拿到沙箱的 shell,标准做法是 Docker 自带的——这不是 SSH:

bash
docker exec -it cua-sandbox bash
# 提示符变成 root@<容器ID> 就进来了,敲 exit 退出

想真正用 ssh 连容器、把上面学的命令用起来,全本地就能把 SSH 从生成密钥到连上容器完整走一遍。有两种练法、二选一即可:给 webtop 装个 sshd 直接连它本体,或另起一个最小的 SSH 服务容器去连(配套代码给了 compose)。具体步骤见文末「可选:用 ssh 连一个本地容器」。

安全要点:私钥绝不外发、绝不提交进 Git(下一段 .gitignore 会再强调);私钥权限要严,chmod 600 ~/.ssh/id_ed25519,权限太开放 ssh 会拒绝用;第一次连会问指纹 yes / no,是正常的 known_hosts 确认,不是报错。万一私钥已经误提交进 Git,别只删文件就完事——立刻去 GitHub 删掉对应公钥、本地重新生成一对新密钥,旧的视同泄露。

Git + GitHub:建起结课作品仓库

Git 是往后 15 周天天用的工具。这一段一次讲全套:建仓库、提交、连 GitHub、回滚、分支。关键设计——你这周已经产出了文件(沙箱的 docker-compose.ymlhello_world.py),正好拿它们当结课作品仓库的第一个提交。从今天起,每周代码都进这一个仓库,结课时它就是你的完整作品。

Git 是什么:版本管理工具,给项目存一个个「存档点」(提交,commit)。改崩了能退回到任一存档点。可以想成项目的后悔药 + 一条时间线。

实战视频 · W1-5待录制

装 + 配(第一次用先配身份)

bash
git --version                              # 打印 git version 2.x.x 即已装好(沙箱 / 多数环境自带)
git config --global user.name  "你的名字"
git config --global user.email "你的邮箱"

建仓库 + 先写 .gitignore(最容易栽的地方):

bash
cd cua-camp                  # 进上半场建的主目录
git init                     # 建仓库,一次即可
# 立刻写 .gitignore,别把垃圾和密钥提交进去
printf "sandbox-data/\n.venv/\n__pycache__/\n*.png\n.DS_Store\n*.log\n.env\n.ssh/\n" > .gitignore

printf 这条 Windows PowerShell 里没有——Windows 用户改用编辑器(VS Code / 记事本)在仓库根目录新建 .gitignore,把文末「配套代码」区那份内容原样贴进去;或在 PowerShell 里跑 "sandbox-data/",".venv/","__pycache__/","*.png",".DS_Store","*.log",".env",".ssh/" | Set-Content .gitignore

git init 会回一句(路径是你自己的):

text
Initialized empty Git repository in /Users/你/cua-camp/.git/

先立规矩再提交——.gitignore 写明哪些不进仓库:挂载的数据、虚拟环境、截图、密钥。私钥、.env 绝不能进。

第一次提交(你的作品仓库从这里诞生)

bash
git add .                                   # 改动放进暂存区
git commit -m "chore: 初始化课程仓库与沙箱配置"
git log --oneline                           # 看提交历史

commitlog 会回类似这样(开头那串短哈希是提交号,每次都不同):

text
[main (root-commit) a1b2c3d] chore: 初始化课程仓库与沙箱配置
 2 files changed, 30 insertions(+)
a1b2c3d chore: 初始化课程仓库与沙箱配置

这是你结课作品仓库的第 1 个提交,里面是沙箱配置和 hello world,往后每周往里加。

连 GitHub,推上去:先确认 SSH 密钥已配好——这是能推送的前提,没配下面 git push 会被拒、报 Permission denied (publickey)。复用上一段「SSH」那对就行:① ssh-keygen 生成密钥;② cat ~/.ssh/id_ed25519.pub 把公钥整行加到 GitHub → Settings → SSH and GPG keys;③ ssh -T [email protected] 看到 Hi 你的用户名! 即配好。再在 GitHub 新建一个仓库(别勾自动建 README,省得首次推送冲突),接远程、推送:

bash
git remote add origin [email protected]:你的用户名/cua-camp.git   # 用 SSH 地址
git branch -M main
git push -u origin main

push 成功大概是这样:

text
Enumerating objects: 4, done.
...
To github.com:你的用户名/cua-camp.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

[email protected]: 开头的 SSH 地址,配合上一段的密钥,免密推。推完刷新 GitHub 页面,代码就在云端有备份了。

回滚实操(后悔药)

bash
git log --oneline                 # 先看提交号:每行开头那串短哈希(如 a1b2c3d)就是
git restore hello_world.py        # 还没 commit:丢弃工作区改动,退回上次提交的样子
git revert a1b2c3d                # 已经 commit:把 a1b2c3d 换成上一行看到的那串提交号

git restore 跑完没有任何提示是正常的——它已经默默把文件还原了,打开 hello_world.py 一看就回到了上次提交的样子。restore 丢掉还没存档的改动;revert 撤掉一个已存档的提交——提交号从 git log --oneline,就是每行开头那串短哈希(不用敲全,前 7 位就行)。注意 revert生成一个新提交,得再 git push 才同步到 GitHub;restore 只动工作区、没提交、不用 push。(revert 默认会弹编辑器填撤销说明,存盘退出即可,或加 --no-edit 跳过。)改崩了不慌,这就是后悔药。

分支(知道有这回事就行,本周不要求熟练)

bash
git switch -c try-something    # 开一条分支试新改动,不影响 main
# …改点东西、commit…
git switch main                # 回主线
git merge try-something        # 满意就合回来

想试个没把握的改动,开分支试,成了再合回主线,main 始终留着能跑的版本。

commit 信息规范(和后面每周一致):type: 说明,type 用 feat(新功能)/ fix(修 bug)/ chore(杂务)/ docs(文档)。说明写人话,一句话讲清这次干了什么。往后每周代码都 commit 进这个仓库、push 上 GitHub,结课时它就是一份逐周累积、能写进简历的完整作品。

课程地图 + 学习方法

整门课走 5 个 Phase:基础与安全 → GUI / 浏览器自动化 + 反检测 → 自己实现 Agent → 生产化 → 实战集成。每隔 3–4 周有一个能演示的产出。

学习方法就一条:动手 > 看视频。从今天起每周代码都进同一个 Git 仓库,逐周累积成结课作品。

配套代码 / 模板

下面这些文件都可以从配套代码仓库直接下载,别手敲复制:https://github.com/codesfly/cua_class_code/tree/main/W01

docker-compose.yml(W1 沙箱:Linux 桌面 + 浏览器可视化)

用 LinuxServer 维护的 Webtop 镜像(2025-06 起已基于 Selkies,流式走 WebCodecs、本地不需要 TURN,浏览器走 https://localhost:3001),开箱即用、浏览器直接看桌面。关键一行:Selkies 默认跑 Wayland,而 pyautogui 要 X11 才能注入鼠标键盘,所以 compose 里设了 PIXELFLUX_WAYLAND=false 强制 X11——这条不设,后面 W3 / W4 的自动化会打不动。放进 cua-camp/sandbox 文件夹(一个容器一个独立文件夹,数据卷 sandbox-data 也落在这里)。

yaml
services:
  sandbox:
    image: lscr.io/linuxserver/webtop:ubuntu-xfce   # 版本以官方最新为准
    container_name: cua-sandbox
    security_opt:
      - seccomp:unconfined          # 桌面应用需要,隔离仍在容器边界内
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - PIXELFLUX_WAYLAND=false     # 强制 X11:pyautogui 注入鼠标键盘、中文剪贴板才稳(Selkies 默认 Wayland 会打不动)
    ports:
      - "3001:3001"                 # 浏览器访问(https):https://localhost:3001
      - "3000:3000"                 # http 备用
    volumes:
      - ./sandbox-data:/config      # 桌面数据持久化到本地文件夹
    shm_size: "1gb"
    restart: unless-stopped

Docker 命令速查(这周够用)

命令作用
docker run hello-world装好后自检
docker compose up -d起沙箱(后台跑)
docker compose ps看容器状态
docker compose logs起不来时看报错
docker compose down停掉并删掉沙箱(挂载数据不丢)
docker ps看所有在跑的容器
docker exec -it cua-sandbox bash进沙箱容器拿一个 shell

hello_world.py(在沙箱桌面的终端里跑)

先装依赖(沙箱终端内):

bash
sudo apt update && sudo apt install -y python3-pip python3-tk scrot
pip3 install pyautogui     # 末尾打印 Successfully installed pyautogui-x.x 就算装好

pip3 installexternally-managed-environment(新版 Ubuntu 对系统 Python 的保护机制),改跑 pip3 install --break-system-packages pyautogui——沙箱里可以这么装,容器删了重建就回到初始状态。

脚本:

python
import time
import pyautogui

pyautogui.FAILSAFE = True   # 鼠标快速移到左上角可紧急中止
time.sleep(2)               # 留 2 秒切到桌面

# 让鼠标自己在桌面上画一个方块,证明“程序在操作这台机器”
points = [(200, 200), (600, 200), (600, 500), (200, 500), (200, 200)]
for x, y in points:
    pyautogui.moveTo(x, y, duration=0.5)

pyautogui.alert("Hello from your sandbox agent!")   # 弹窗收尾

SSH 密钥与命令速查

bash
ssh-keygen -t ed25519 -C "你的邮箱"     # 生成密钥对,一路回车用默认
cat ~/.ssh/id_ed25519.pub               # 打印公钥,复制去加到 GitHub
ssh -T [email protected]                   # 验证 GitHub 连通(看到 Hi 用户名! 即成功)
chmod 600 ~/.ssh/id_ed25519             # 收紧私钥权限
ssh 用户名@主机地址                       # 连远程主机(陪跑版云环境)

可选:用 ssh 连一个本地容器(完整练一遍 ssh)

想把 ssh 命令真正用在容器上(不只是 docker exec),有两种练法,任选一种单独测一遍即可。

方式 1:直接 ssh 连 webtop 沙箱本体

webtop 默认只开 3000/3001 网页桌面、没跑 sshd,要自己给它装一个、开出 22 端口、再放公钥进去。先给沙箱的 docker-compose.ymlsandbox 服务)ports 加一行(改完在 sandbox 文件夹里 docker compose up -d 重建容器才生效):

yaml
    ports:
      - "3001:3001"
      - "3000:3000"
      - "2223:22"      # 新增:容器里 sshd 的 22 端口映射到本机 2223

再进容器装 sshd、起服务、放公钥(exec 进去默认就是 root):

bash
docker exec -u root -it cua-sandbox bash
# —— 以下在容器内 ——
apt-get update && apt-get install -y openssh-server   # 装 sshd
ssh-keygen -A                                          # 生成主机密钥,缺了 sshd 起不来
mkdir -p /run/sshd                                     # sshd 的特权分离目录
install -d -m700 -o abc -g abc /config/.ssh            # abc 用户的家目录是 /config
echo 'ssh-ed25519 AAAA...粘贴你公钥整行...' > /config/.ssh/authorized_keys
chown abc:abc /config/.ssh/authorized_keys && chmod 600 /config/.ssh/authorized_keys
/usr/sbin/sshd                                         # 起 sshd,没报错即成功
exit

回本机连(用户名是 abc):

bash
ssh -p 2223 abc@localhost
# 首次问 yes/no 是正常的 known_hosts 确认;提示符变成 abc@容器id 就进去了

sshd 是装在运行中的容器里,docker compose down 重建后会没、得重装——这条适合演示一遍看效果。公钥放在 /config/.ssh(挂到 sandbox-data),重建不丢。连上立刻被断开的话,多半是 abc 用户没有登录 shell——再 exec 进去跑 usermod -s /bin/bash abc 后重连(该改动重建后同样失效)。想开机自动起 sshd,用 LinuxServer 的 custom-cont-init.d 启动脚本,属进阶,照官方文档自查。

方式 2:单独起一个 openssh-server 容器(不碰沙箱,最省事)

不想动 webtop,就另起一个本来就是 SSH 服务的最小容器——同样给它单开一个 ssh-lab 文件夹(和 sandbox 平级),把这份 compose 存成 ssh-lab/docker-compose.yml

yaml
services:
  ssh-lab:
    image: lscr.io/linuxserver/openssh-server:latest
    container_name: ssh-lab
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - PUBLIC_KEY_FILE=/keys/id_ed25519.pub   # 把你的公钥挂进来
      - USER_NAME=student
    volumes:
      - ~/.ssh/id_ed25519.pub:/keys/id_ed25519.pub:ro
    ports:
      - "2222:2222"

进到这个文件夹起容器、再连:

bash
docker compose up -d            # 在 cua-camp/ssh-lab 文件夹里执行
ssh -p 2222 student@localhost
# 首次问 yes/no 输 yes;提示符变成 student@ssh-lab 就进去了

linuxserver/openssh-server 的环境变量名与默认端口以官方文档当下版本为准,先在本机跑通再用。

想连的就是沙箱本体,用方式 1;只想最快练一遍 ssh、不碰沙箱,用方式 2。日常拿 webtop 的 shell 仍是 docker exec -it cua-sandbox bash 最省事。

.gitignore(建仓库后立刻写)

gitignore
sandbox-data/
.venv/
__pycache__/
*.png
.DS_Store
*.log
.env
.ssh/

Git 命令速查(这周够用)

命令作用
git config --global user.name/email第一次用配身份
git init在项目目录建仓库(一次即可)
git add .把改动放进暂存区
git commit -m "type: 说明"存一个版本
git log --oneline看提交历史
git remote add origin git@…接上 GitHub 远程(SSH 地址)
git push -u origin main推到 GitHub
git restore 文件丢弃还没提交的改动
git revert 提交号撤掉一个已提交的版本(提交号 = git log --oneline 开头短哈希;它生成新提交,要再 push)
git switch -c 分支名 / git merge 分支名开分支 / 合回主线

可选:先看官方的跑起来(beta)

想第一周就感受完整 Computer Use,可跑 Anthropic 官方 demo(需自备 API key)。它会真的操作容器里的桌面,官方标注为 beta——网页、图片里的文字可能构成 prompt injection 让它跑偏,别接入真实账号和敏感数据:

bash
docker run \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
  -v $HOME/.anthropic:/home/computeruse/.anthropic \
  -p 5900:5900 -p 8501:8501 -p 6080:6080 -p 8080:8080 \
  -it ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest
# 浏览器开 http://localhost:8080(combined 界面)

官方命令时有变动(端口、挂载),以 anthropic-quickstarts 仓库 computer-use-demo 的 README 当前版本为准。这是「用现成的」,本周只作体验;W9–W10 会带你拆它的实现、自己写一个。

本周作业

  • 作业 1(必做):跑通沙箱,截图:① 浏览器里的容器桌面;② hello_world.py 跑起来鼠标在动 / 弹窗出现(截图交作业打卡平台即可,不必进 Git——.gitignore 已忽略 *.png)。验收:沙箱能起、能看到桌面、脚本能跑完。
  • 作业 2(必做):配好 SSH 密钥并连上 GitHub。验收:ssh -T [email protected] 能看到 Hi 你的用户名!;说得清公钥和私钥哪个能公开、哪个绝不外传。
  • 作业 3(必做):把 cua-camp 建成 Git 仓库并推上 GitHub。验收:先写好 .gitignoregit log 有至少一条 commit;仓库里没有 sandbox-data / .venv / .env / 私钥;GitHub 上能看到这个仓库。
  • 作业 4(判断练习 → 出一张项目草图):挑一个你想自动化的真实任务,按五行填成一张项目草图,并判断它该写普通脚本还是上 Agent。五行是——① 一句话:想让它帮我做什么;② 现在我是怎么做的、卡在哪;③ 该写脚本还是上 Agent、为什么(看它要不要盯着屏幕随机应变);④ 会碰到哪些软件 / 网页(桌面?浏览器?);⑤ 怎么算做完(成功长什么样)。验收:五行都填上,第 ③ 行结论有理由,不是「感觉行」。课上讲师也会照这五行立项一个贯穿全课的样板——个人信息聚合助手:把自己有权访问的信息源(邮箱 / 日历 / 本地笔记 / 待办)聚合成每天一份自动生成的个人简报,W4 起每周把当周新学的技术加到它身上,到 W16 完整交付。想不出题目,可以直接选「我自己的信息聚合助手」。

常见坑

  • 不会打开 / 用终端:macOS 用「终端.app」、Windows 用 PowerShell、沙箱里用桌面自带终端;先 pwd 看自己在哪,cd 走过去,别在错的目录里敲命令。
  • 路径报「找不到文件 / No such file or directory」:多半是当前目录不对,或路径里有空格 / 中文;pwd + ls 确认,目录名尽量用英文无空格。
  • Docker 装不上:Windows 没启用 WSL2;macOS 选错芯片架构(Intel / Apple Silicon);企业电脑无管理员权限,改用云环境。
  • docker compose up 卡在 pulling 不动 / 极慢:没配代理,或代理没生效。按上面「配代理加速」给 Docker 配上 Clash 代理(别用国内镜像源,有的镜像它拉不到),重启 Docker 后 docker info 确认 HTTP Proxy 已生效再拉。
  • 镜像架构不对(exec format error / no matching manifest:Apple Silicon 拉了 x86 镜像之类。webtop 多架构通常会自动选对;个别镜像得在 compose 里指定 platform,或换支持你架构的镜像。
  • 浏览器拦「连接不安全 / 证书无效(NET::ERR_CERT_AUTHORITY_INVALID)」:webtop 用的是自签证书,正常现象,不是出错。点「高级 → 继续前往 localhost」即可——这是你本机的容器,不是钓鱼网站。
  • https://localhost:3001 打不开 / 一直转:容器没起来(docker compose ps 看状态、docker compose logs 看报错);端口被占就改 compose 左边端口(如 3002:3001)再开新地址。注意是 https、3001。
  • pyautogui 报错 no display / KeyError DISPLAY:脚本必须在沙箱桌面的终端里跑,不能在宿主机跑。
  • 沙箱里鼠标不动 / 截图全黑 / 点不准:沙箱跑成 Wayland 了(Selkies 默认 Wayland,pyautogui 打不动)。确认 compose 里有 PIXELFLUX_WAYLAND=false,重建容器;进沙箱终端 echo $DISPLAY 应能看到 :1 之类,再跑 hello_world.py 验证鼠标真动。
  • pip install pyautogui 失败:缺 python3-tk / scrot,按上面的 apt 命令补装。
  • ssh -T [email protected]Permission denied (publickey):公钥没加到 GitHub,或加错了;cat ~/.ssh/id_ed25519.pub 重新复制完整一行再加。
  • SSH 报私钥权限太开放(UNPROTECTED PRIVATE KEY FILEchmod 600 ~/.ssh/id_ed25519
  • git push 被拒(rejected / non-fast-forward):远程仓库建了 README 等内容、和本地历史不一致;git pull --rebase origin main 合一下再 push。
  • git 把 sandbox-data / .venv 提交了、仓库巨大:先写 .gitignoreadd;已经误加的用 git rm -r --cached 名字 撤出再提交。
  • 容器运行卡顿:内存不足,关闭宿主机其他大程序,或给 Docker 调高内存配额。

本周产出物

  • 一个能跑的隔离沙箱 + 跑通的 hello world(鼠标自己动起来了)。
  • 配好的开发环境:会用终端;SSH 密钥已生成、公钥加到 GitHub(连得上)。
  • 一个 Git 仓库(结课作品的起点):含 .gitignore + 至少一条 commit,已推上 GitHub——往后 15 周代码都进它,逐周累积。
  • 一张课程地图:看懂这门课 16 周、5 个 Phase 各造出什么,心里有全程、不慌。
  • 一张项目草图:写下一个你想用 Agent 解决的真实任务(作业 4 的产物)。

延伸阅读

  • 必看:Anthropic「Computer use」官方文档(docs.anthropic.com,Tool use → Computer use),了解官方能力边界。
  • 必看anthropics/anthropic-quickstarts 仓库的 computer-use-demo,后面 W9 拆解它的实现,先混个眼熟。
  • 想深入:Anthropic 发布 Computer Use 的官方公告或博客,了解背景与设计取向。
  • 命令行入门(零基础):任一篇「终端 / 命令行 10 分钟入门」,只认 pwd / ls / cd / mkdir 和路径概念即可。
  • Docker 入门(零基础):Docker 官方「Get started」教程(docs.docker.com/get-started),只看「概念 + 起一个容器」前两节,够本周用。
  • SSH:GitHub 官方「Connecting to GitHub with SSH」文档(docs.github.com),生成密钥、加公钥、验证,照着走一遍最稳。
  • Git(必看):《Pro Git》第 1–2 章(中文版免费,git-scm.com/book/zh),只看「起步 + 基础」,够本周用。
  • 工具文档:Docker Desktop 安装文档、LinuxServer Webtop / OpenSSH-Server 文档(docs.linuxserver.io)、PyAutoGUI 文档(pyautogui.readthedocs.io)。
W1 · 开营、工具地基(沙箱 · SSH · Git) | 资讯狗 | Zixungou