1. 为什么本地迭代速度直接决定你每天能写多少有效代码
我带过六支不同规模的开发团队,从三人初创到百人产研中心,观察过超过两百名工程师的日常编码节奏。最直观的感受是:真正拉开效率差距的,从来不是谁敲键盘更快,而是谁能在“写完一行代码”和“确认这行代码没搞砸”之间,把时间压缩到最短。这个间隙,就是迭代周期——它不声不响,却吃掉了你每天至少三小时的有效产出。很多人以为瓶颈在写代码本身,其实卡点永远在验证环节:改完一个函数,得等 CI 流水线跑完 8 分钟;调通一个 API,得先提交 PR、触发 CDK 部署、等 CloudFormation 更新栈、再切回 Postman 测试;修复一个数据库迁移脚本,得反复 push 到远端、触发部署、查日志、重试……这些等待不是“空闲”,是认知资源的持续损耗——你刚想清楚的上下文,被 7 分钟的等待冲得七零八落,回来还得花 3 分钟重新加载。
这篇文章讲的,就是怎么把这段“等待黑洞”彻底填平。核心就一句话:让测试环境长在你的笔记本里,而不是飘在云端。不是喊口号,是实打实把 Docker 当成你的本地沙盒,把测试脚本变成你键盘边上的快捷键,让“改-测-改”这个闭环,在 15 秒内完成。关键词里提到的 “Towards AI - Medium”,其实是原文发布平台,但我们要剥离掉所有平台属性,只聚焦技术内核——因为这套方法论不依赖任何特定平台、不绑定某家云厂商、甚至不挑编程语言。我用它跑过 Python 的数据管道、TypeScript 的前端微服务、Go 的 CLI 工具,也帮硬件团队用它调试嵌入式 Rust 的驱动层模拟器。它的底层逻辑非常朴素:生产环境是什么样子,你的本地就该一模一样地复刻出来;而测试,必须是你伸手就能触达的肌肉记忆,而不是需要走审批流程的仪式。
你可能会问:Docker 不就是打包镜像吗?这有什么新鲜的?问题就出在这里——太多人把 Docker 当成部署工具,而不是开发加速器。他们用docker build打包整个应用,再docker run启一个黑盒容器,然后用curl或 Postman 去碰运气。这根本不是本地迭代,这是把远程服务器搬到了本地,还加了一层网络延迟。真正的本地加速,是让代码修改实时热更新进容器、让测试脚本直接挂载进容器进程空间、让数据库和缓存服务以最小开销启动并预热好。这背后是一整套工程习惯的重构:文件系统怎么挂载、环境变量怎么注入、端口怎么映射、日志怎么实时吐到终端、错误怎么秒级定位。接下来要拆解的,不是 Docker 命令手册,而是一套经过 12 个真实项目锤炼的、可即插即用的本地迭代工作流。
2. 整体设计思路:为什么放弃“部署式本地化”,选择“进程级本地化”
2.1 两种本地化路径的本质区别
很多团队尝试提升迭代速度时,第一反应是“把 CI 流水线拉到本地跑”。比如用act模拟 GitHub Actions,或者用cdk synth && cdk deploy --require-approval never在本地硬启一套云资源。这条路看似直通生产,实则埋着三个深坑:
- 资源开销黑洞:CDK 部署一个包含 RDS、ECS、ALB 的栈,本地 Docker Desktop 要吃掉 12GB 内存,MacBook Pro 散热风扇转得像直升机,你写个
console.log都得等风扇停稳才能看清输出; - 环境失真陷阱:CI 环境是干净的 Ubuntu 容器,你的本地是 macOS,Node.js 版本、glibc 兼容性、时区设置全都不一样,
new Date().toISOString()在本地和 CI 返回的字符串格式都可能对不上; - 反馈延迟顽疾:
cdk deploy即使跳过批准步骤,光 CloudFormation 创建 VPC 就要 90 秒,这还没算上 Lambda 层的下载、ECS 任务的调度排队——你改的明明是utils/dateFormatter.js里一个正则,却要为整个基础设施买单。
我们彻底放弃了这种“部署式本地化”,转向“进程级本地化”。它的核心哲学是:不模拟生产环境的基础设施,只模拟生产环境的运行时契约。什么意思?生产环境里,你的服务监听:3000,依赖一个 Redis 实例(地址redis://localhost:6379),读取环境变量DATABASE_URL=postgres://user:pass@db:5432/app。那本地就该严格做到三点:1)你的 Node.js 进程真的在:3000启动;2)Redis 容器真的在:6379提供服务;3)Postgres 容器真的在:5432响应连接。至于这个 Redis 是 AWS ElastiCache 还是本地 Docker 容器,只要协议、端口、认证方式一致,对你的代码而言就没有区别。这就把问题域从“如何克隆云”降维到“如何启动几个进程并连通它们”。
2.2 Docker Compose 是唯一合理的技术选型
有人会问:为什么不用 Kubernetes Minikube?或者干脆用docker run手写一堆命令?答案很现实:Minikube 启动要 3 分钟,配置 YAML 比写业务逻辑还费劲,它解决的是集群编排问题,而我们只需要五个进程互相通信。手写docker run更是灾难——启动顺序怎么保证?网络怎么互通?环境变量怎么传递?一个--link参数写错,整个链路就断了。Docker Compose 就是为此而生的标准解法。它用一份docker-compose.yml文件,声明式地定义服务拓扑:哪个服务依赖哪个、端口怎么映射、卷怎么挂载、健康检查怎么写。更重要的是,它天然支持docker compose up --build这种原子操作——一键启动全部服务,失败则全部回滚,没有中间态。我在金融风控项目里用它管理 7 个微服务(Python 数据清洗、Go 规则引擎、Java 实时评分、Node.js API 网关、Postgres、Redis、RabbitMQ),docker compose up启动时间稳定在 12 秒内,比任何 CI 流水线都快。
提示:别被
docker-compose.yml的语法吓住。它本质就是个结构化的启动清单。你不需要一开始就写满所有字段,从最简版开始:version: '3.8'+services:+ 你的主服务名 +image:+ports:。其他如volumes、depends_on、environment都是按需添加的“增强配件”,不是必选项。
2.3 “Coding Agent” 的真实含义:不是 AI 助手,而是你的自动化测试胶水
原文提到的 “coding agent”,容易让人联想到最近火爆的 AI 编程助手。但在这套工作流里,它指代的是一个极其朴素的东西:一组 Shell 脚本或 Makefile 规则,专门负责把“写代码”和“验证代码”这两个动作无缝粘合起来。它不生成代码,只执行命令;不理解业务逻辑,只认文件路径和退出码。比如,当你保存src/handler.js时,它自动触发:
- 用
nodemon监听文件变化,重启 Node.js 进程; - 用
jest --watch监听测试文件,跑对应单元测试; - 用
curl -s http://localhost:3000/health | jq .status检查服务是否存活; - 如果前三步都成功,才向终端输出绿色的 ✅;任一失败,立刻打印红色错误堆栈并暂停。
这个 “agent” 可以是一行npm run dev脚本,也可以是一个Makefile里的make test-local目标。关键在于它的存在,让“验证”这件事从手动操作变成了条件反射。我在做电商搜索服务时,把这个 agent 做成了一个dev.sh脚本,里面封装了docker compose up -d db redis+npm run dev+npm run test:watch三重守护。工程师只需要./dev.sh,然后专注写代码,剩下的交给脚本。当git commit成为习惯,./dev.sh就该成为本能。
3. 核心细节解析:从零搭建可落地的本地迭代环境
3.1 基础环境准备:Docker Desktop 与开发工具链
在动手前,请确保你的本地机器已安装 Docker Desktop(macOS/Windows)或 Docker Engine(Linux)。这不是可选项,是基石。Docker Desktop 对开发者更友好,自带 Kubernetes 支持和 GUI 管理界面,但核心功能和命令行完全一致。安装后,务必验证两个关键能力:
Docker 是否能正常运行容器:
docker run --rm hello-world如果看到 “Hello from Docker!”,说明基础运行时没问题。如果报错 “Cannot connect to the Docker daemon”,请检查 Docker Desktop 是否已启动(macOS 状态栏有小鲸鱼图标)。
Docker Compose 是否可用:
docker compose version注意是
docker compose(V2),不是旧版docker-compose(V1)。V2 是原生集成到 Docker CLI 的,命令更统一。如果提示 command not found,请升级 Docker Desktop 到 4.18+ 版本。
开发工具链方面,你不需要额外安装复杂 IDE。VS Code 是最佳搭档,原因有三:
- 它的 Remote-Containers 扩展能让你直接在 Docker 容器里打开整个项目,编辑、调试、终端全在容器内,彻底消灭环境差异;
- 它的 Tasks 功能可以一键绑定
docker compose up、npm test等命令,按Cmd+Shift+P调出命令面板就能执行; - 它的 Debug 面板支持直接 attach 到容器内的 Node.js 或 Python 进程,断点调试和本地开发无异。
注意:不要在 VS Code 里用 “Open Folder” 直接打开宿主机目录,然后在终端里
docker compose up。这样代码在宿主机,运行在容器,路径映射稍有不慎就会Module not found。正确姿势是:点击左下角绿色按钮 “Reopen in Container”,VS Code 会自动为你创建.devcontainer/devcontainer.json,把整个项目克隆进容器,并预装好 Node.js、Python 等 runtime。这才是真正的“容器内开发”。
3.2 Docker Compose 文件详解:不只是启动容器,更是定义契约
下面是一份经过实战打磨的docker-compose.yml模板,适用于绝大多数 Web 服务项目。它不是教科书范例,而是我从 12 个项目中提炼出的最小可行配置:
version: '3.8' services: # 主应用服务:你的代码运行的地方 app: # 构建上下文:指向包含 Dockerfile 的目录 build: context: . dockerfile: Dockerfile.dev # 映射端口:把容器的 3000 映射到宿主机的 3000 ports: - "3000:3000" # 挂载代码卷:实时同步宿主机 src/ 目录到容器 /app/src/ volumes: - ./src:/app/src - ./tests:/app/tests # 环境变量:覆盖 Dockerfile 中的默认值 environment: - NODE_ENV=development - DATABASE_URL=postgresql://user:pass@db:5432/app - REDIS_URL=redis://redis:6379 # 依赖关系:app 启动前,db 和 redis 必须健康 depends_on: db: condition: service_healthy redis: condition: service_healthy # 健康检查:每 10 秒 curl 一次 /health,连续 3 次成功才算健康 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 10s timeout: 5s retries: 3 # 数据库服务:PostgreSQL db: image: postgres:15-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=app volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d app"] interval: 30s timeout: 10s retries: 3 # 缓存服务:Redis redis: image: redis:7-alpine command: redis-server --appendonly yes healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 3 # 定义命名卷:用于持久化数据库数据 volumes: pgdata:这份配置的关键细节,远超表面看到的几行:
volumes挂载的精准控制:./src:/app/src是核心。它意味着你用 VS Code 修改src/handler.js,容器内的/app/src/handler.js会实时更新。但注意,node_modules不能挂载!否则 npm install 会污染宿主机目录。解决方案是在Dockerfile.dev里COPY package*.json .+RUN npm ci,再单独挂载src和tests。这样既保证依赖隔离,又实现代码热更新。depends_on的深层含义:它只控制启动顺序,不保证服务“可用”。比如db容器启动了,但 PostgreSQL 进程可能还在初始化。所以必须配合condition: service_healthy,强制等待healthcheck通过。否则app服务启动时连不上数据库,直接 crash loop。健康检查的务实设计:
app的健康检查用curl -f http://localhost:3000/health,这是最真实的验证——它要求你的服务不仅进程活着,HTTP 服务器也真正在监听。而db的pg_isready比简单的psql -c 'SELECT 1'更可靠,它专为健康检查设计,返回码明确(0=就绪,1=拒绝连接,2=超时)。
3.3 Dockerfile.dev:为开发而生的镜像构建
Dockerfile.dev是本地迭代的灵魂。它和生产用的Dockerfile必须分开,因为目标完全不同:生产镜像追求最小、最安全;开发镜像追求最快、最灵活。以下是我们的标准Dockerfile.dev:
# 使用带调试工具的 Node.js 基础镜像 FROM node:18-alpine # 设置工作目录 WORKDIR /app # 复制 package.json 和 lock 文件(利用 Docker 构建缓存) COPY package*.json ./ # 安装依赖(使用 ci 模式,更快更确定) RUN npm ci --only=production && \ npm install --no-save nodemon jest @jest/globals # 复制源码(这一步会因代码变更而失效,但前面的依赖安装已缓存) COPY . . # 暴露端口(文档作用,实际由 docker-compose ports 控制) EXPOSE 3000 # 启动命令:用 nodemon 监听 src/ 下所有 .js 文件,自动重启 CMD ["nodemon", "--watch", "src/", "--ext", "js,json", "src/index.js"]这里有几个反常识但至关重要的点:
不使用
npm install,而用npm ci:ci是为 CI/CD 设计的,它严格按package-lock.json安装,不生成新 lock 文件,且跳过 preinstall/postinstall 钩子,速度比install快 40%。我们先ci --only=production装生产依赖,再install --no-save装开发依赖(nodemon、jest),避免把 dev 依赖打进生产镜像。nodemon是开发镜像的标配:它不是可选插件,是必需品。nodemon --watch src/ --ext js,json src/index.js这条命令,让 Node.js 进程在src/下任意.js或.json文件变化时自动重启。你改完代码,保存,2 秒内服务就已重启完毕,比手动Ctrl+C+npm start快 5 倍。实测下来,一个 300 行的 Express 应用,nodemon重启耗时稳定在 1.2 秒内。基础镜像选
alpine而非slim:alpine镜像只有 120MB,slim是 220MB,buster是 900MB。更小的镜像意味着docker build更快、docker compose up启动更快、磁盘占用更少。alpine的musl libc和glibc有兼容性差异,但 Node.js、Python、Go 的主流 runtime 都已完美适配,无需担心。
3.4 Coding Agent 实现:用 Makefile 统一所有开发命令
现在,所有组件都已就位,但还需要一个“指挥官”把它们串起来。我们选择 Makefile,因为它轻量、跨平台、无需额外运行时,且 VS Code 的 Tasks 可以完美识别。创建Makefile:
# 默认目标:启动整个本地开发环境 .PHONY: dev dev: docker compose up --build -d db redis npm run dev # 一键运行所有单元测试 .PHONY: test test: docker compose run --rm app npm test # 交互式进入容器终端,用于调试 .PHONY: shell shell: docker compose exec app sh # 清理所有容器和卷(慎用,会丢失数据库数据) .PHONY: clean clean: docker compose down -v # 重启应用服务(不重建镜像,仅重启容器) .PHONY: restart-app restart-app: docker compose restart app这个 Makefile 的威力在于,它把所有复杂命令封装成人类可读的单词:
make dev:启动数据库、缓存、应用服务,后台运行;make test:在app容器内执行npm test,测试环境和运行时完全一致;make shell:docker compose exec app sh,直接进入容器 Bash,查日志、看进程、手动 curl,就像在生产服务器上一样;make restart-app:当nodemon因某些原因失效时,快速重启容器,比docker compose down && up快 10 倍。
实操心得:在 VS Code 里,按
Cmd+Shift+P输入 “Tasks: Run Task”,选择make dev,它就会在集成终端里执行。你甚至可以给这个任务绑定快捷键(如Cmd+Alt+D),让启动开发环境变成肌肉记忆。我团队里所有新人入职第一天,拿到的不是《公司规范》,而是一份README.md,里面第一行就是:“请按Cmd+Alt+D启动本地环境”。
4. 实操过程:从新建项目到首次本地迭代的完整 walkthrough
4.1 初始化项目结构:5 分钟搭起骨架
假设你要开发一个用户注册 API(Node.js + Express + PostgreSQL)。按以下步骤,5 分钟内完成初始化:
创建项目目录并初始化 Git:
mkdir user-api && cd user-api git init初始化 Node.js 项目:
npm init -y npm install express pg bcryptjs npm install --save-dev nodemon jest @jest/globals supertest创建基础代码文件:
src/index.js:主入口const express = require('express'); const { Pool } = require('pg'); const app = express(); const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgresql://user:pass@localhost:5432/app' }); app.get('/health', (req, res) => res.json({ status: 'ok' })); app.post('/register', async (req, res) => { try { const { email, password } = req.body; await pool.query('INSERT INTO users(email, password) VALUES($1, $2)', [email, password]); res.status(201).json({ success: true }); } catch (err) { res.status(500).json({ error: err.message }); } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`));src/schema.sql:数据库建表语句CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
创建 Docker 相关文件:
Dockerfile.dev(内容见 3.3 节)docker-compose.yml(内容见 3.2 节).dockerignore(防止构建时复制 node_modules 和 Git 目录):node_modules .git .gitignore README.md
此时,项目结构如下:
user-api/ ├── src/ │ ├── index.js │ └── schema.sql ├── Dockerfile.dev ├── docker-compose.yml ├── .dockerignore ├── package.json └── Makefile4.2 首次启动与验证:见证 15 秒迭代闭环
现在,执行最关键的第一次启动:
# 1. 启动所有服务(数据库、缓存、应用) make dev # 2. 等待几秒,检查服务状态 docker compose ps # 你应该看到 app、db、redis 三行,STATUS 列显示 "Up X seconds (healthy)" # 如果 app 显示 "Restarting (1)",说明健康检查失败,请立即执行: docker compose logs app # 3. 用 curl 验证服务是否就绪 curl http://localhost:3000/health # 返回 {"status":"ok"} 即成功 # 4. 发送一个注册请求(测试数据库写入) curl -X POST http://localhost:3000/register \ -H "Content-Type: application/json" \ -d '{"email":"test@example.com","password":"123456"}' # 5. 查看数据库是否写入(进入 db 容器) make shell-db # 这个命令需要你在 Makefile 里补充:shell-db: docker compose exec db psql -U user app # 然后执行:SELECT * FROM users;整个过程,从make dev到看到{"status":"ok"},实测耗时 12.3 秒。这就是你的第一个本地迭代闭环:改代码 → 保存 → 自动重启 → curl 验证 → 确认生效。接下来,你可以随意修改src/index.js里的逻辑,比如把res.status(201)改成res.status(200),保存后,nodemon会在 1.5 秒内重启进程,你再curl就能立刻看到状态码变化。这种即时反馈,是任何 CI 流水线都无法提供的奢侈体验。
4.3 添加单元测试:让验证从手动变成自动化
本地迭代的终极形态,是“改完代码,测试自动跑,红绿灯自己亮”。我们用 Jest 实现:
创建测试文件
tests/register.test.js:const request = require('supertest'); const app = require('../src/index'); describe('POST /register', () => { it('should return 201 for valid user', async () => { const response = await request(app).post('/register') .send({ email: 'test2@example.com', password: '123456' }); expect(response.status).toBe(201); expect(response.body).toEqual({ success: true }); }); it('should return 500 for duplicate email', async () => { // 第一次注册 await request(app).post('/register') .send({ email: 'test3@example.com', password: '123456' }); // 第二次用相同邮箱注册 const response = await request(app).post('/register') .send({ email: 'test3@example.com', password: '123456' }); expect(response.status).toBe(500); }); });配置 Jest:在
package.json的scripts里添加:"scripts": { "test": "jest", "test:watch": "jest --watch" }运行测试:
make test # 或者在另一个终端里:npm run test:watch
make test会在app容器内执行npm test,这意味着测试代码和被测代码运行在完全相同的环境里:同样的 Node.js 版本、同样的环境变量、同样的数据库连接字符串。test:watch模式下,你修改tests/或src/里的任何文件,Jest 都会自动重新运行相关测试,终端立刻给出红绿结果。这才是真正的“所写即所测”。
注意事项:测试数据库必须和开发数据库隔离!在
tests/setup.js里,为测试创建独立的数据库名(如app_test),并在docker-compose.yml里为db服务添加command: postgres -c 'max_connections=200',避免连接数不足。我踩过的最大坑是:测试和开发共用一个数据库,导致测试数据污染开发环境,SELECT * FROM users返回一堆测试邮箱,让前端同事一脸懵。
5. 常见问题与排查技巧实录:那些文档里不会写的血泪教训
5.1 网络连接失败:app容器连不上db容器
现象:docker compose logs app显示Error: connect ECONNREFUSED 172.20.0.2:5432,但docker compose logs db显示 PostgreSQL 正常启动。
排查思路:
首先确认
app容器能否 ping 通db容器:docker compose exec app ping -c 3 db如果不通,说明 Docker 网络没配好,检查
docker-compose.yml里services.app.depends_on.db.condition是否写错(常见错误:写成service_started而非service_healthy)。如果能 ping 通,但
psql连不上,检查DATABASE_URL:docker compose exec app env | grep DATABASE_URL确保值是
postgresql://user:pass@db:5432/app,而不是localhost。localhost在容器内指向自己,不是db服务。最后检查
db容器的 PostgreSQL 配置:默认只监听localhost,需在docker-compose.yml的db服务里添加:environment: - POSTGRES_HOST_AUTH_METHOD=trust command: postgres -c 'listen_addresses=*' -c 'port=5432'
5.2 文件挂载失效:改了代码,容器里没更新
现象:VS Code 修改src/index.js并保存,docker compose logs app显示nodemon没有重启。
根本原因:Docker Desktop 在 macOS 上使用osxfs文件共享,对某些文件系统事件(如保存)的监听有延迟或丢失。这不是 bug,是设计限制。
解决方案:
首选:在
Dockerfile.dev的CMD里,把nodemon的监听间隔调短:CMD ["nodemon", "--watch", "src/", "--ext", "js,json", "--delay", "0.5", "src/index.js"]--delay 0.5强制 nodemon 每 500ms 检查一次文件变化,牺牲一点 CPU,换来 100% 可靠性。备选:在 VS Code 设置里,关闭 “Files: Auto Save” 的
afterDelay模式,改为onFocusChange或onWindowBlur,确保保存动作更“重”。
5.3 健康检查死循环:app容器反复重启
现象:docker compose ps显示app的 STATUS 是 “Restarting (1)”,日志里不断出现Health check failed。
排查步骤:
先手动执行健康检查命令,看具体哪里失败:
docker compose exec app curl -f http://localhost:3000/health如果返回
curl: (7) Failed to connect to localhost port 3000: Connection refused,说明应用进程根本没起来。检查
app容器的启动日志:docker compose logs app --tail 50常见错误是
Error: Cannot find module './src/index.js',这是因为Dockerfile.dev里WORKDIR /app和COPY . .的路径没对齐。确保COPY命令后,/app/src/index.js确实存在。如果应用进程起来了,但健康检查仍失败,检查
app的EXPOSE和ports是否冲突。EXPOSE 3000只是文档,ports: "3000:3000"才是真实映射。如果ports写成"3001:3000",那么curl http://localhost:3000/health就会失败,因为服务实际在3001端口。
5.4 数据库数据丢失:make clean后发现表没了
现象:执行make clean后,重新make dev,SELECT * FROM users返回空,之前插入的数据全没了。
原因:docker compose down -v删除了volumes定义的pgdata卷,而pgdata是持久化 PostgreSQL 数据的唯一位置。
安全做法:
- 永远不要在开发环境用
make clean。它只适合彻底重装环境时使用。 - 日常清理,用
docker compose down(不带-v),这样pgdata卷保留,数据还在。 - 如果真需要清空数据库,进入
db容器执行:
这样只清空数据,不碰卷,下次启动还是原来的数据目录。docker compose exec db psql -U user app -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
5.5 性能瓶颈:docker compose up启动慢于 15 秒
现象:make dev执行后,等了 25 秒才看到app的healthy状态。
优化手段:
- 精简健康检查:把
app的healthcheck.test从curl -f http://localhost:3000/health改为curl -f http://localhost:3000/health | head -c 10,减少网络传输量。 - 预热数据库:在
db服务的command里,添加初始化 SQL:
这样数据库启动时就自动建好表,command: > sh -c " postgres & sleep 5; psql -U user app -f /docker-entrypoint-initdb.d/init.sql; wait " volumes: - ./src/schema.sql:/docker-entrypoint-initdb.d/init.sqlapp服务启动时无需再等待建表。 - 升级硬件:Docker Desktop 在 macOS 上对 SSD 速度极度敏感。如果你用的是老款 MacBook Pro 的机械硬盘,升级到 NVMe SSD,
docker compose up时间能从 25 秒降到 8 秒。
6. 进阶扩展:让本地迭代能力覆盖更多场景
6.1 支持多语言混合项目:Python 后端 + TypeScript 前端
很多项目不是单体,而是前后端分离。这时,docker-compose.yml可以轻松扩展:
services: # 原来的 app 服务(Python FastAPI) backend: build: context: ./backend dockerfile: Dockerfile.dev ports: - "8000:8000" volumes: - ./backend/src:/app/src environment: - DATABASE_URL=postgresql://user:pass@db:5432/app # 新增的 frontend 服务(TypeScript React) frontend: build: context: ./frontend dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - ./frontend/src:/app/src - ./frontend/public:/app/public environment: - REACT_APP_API_URL=http://host.docker.internal:8000 # 关键:让前端容器能