起因
新项目要装:PostgreSQL 16 + Redis 7 + Node 20 + Python 3.12 + ImageMagick +
ffmpeg。同事的机器版本各异,"在我机器上能跑"频繁出现。
两种主流策略:
A. mise + direnv 安装到 host
B. docker compose 把依赖装容器
我俩都试过几次,下面记录适用场景 + 优缺点。
方案 A:mise + direnv(本地原生)
.tool-versions:
python 3.12.5
nodejs 20.10.0
go 1.22.1
postgres 16.4
redis 7.4.0
.envrc:
use mise
dotenv .env
PATH_add ./bin
export DATABASE_URL=postgresql://localhost/myapp
cd myapp
mise install # 装 Python 3.12.5 + Node 20.10 + Go ...
# 第一次几分钟,之后秒级
DB / Redis 还是装 host:
brew install postgresql@16 redis
brew services start postgresql@16 redis
或者 host 上跑 docker 单独管 DB:
docker run -d --name pg -p 5432:5432 -v pg-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=dev postgres:16
docker run -d --name redis -p 6379:6379 redis:7
优点:
- IDE 直接看到源码 + linter / 跳定义 / debugger 都丝滑
- 启动快(mise install 几秒;之后开机即可用)
- 不依赖 docker daemon(笔记本 RAM 友好)
- 测试 / lint / build 直接跑 host CPU 速度
缺点:
- ImageMagick / ffmpeg 之类系统依赖每个 OS 装法不同
- C 扩展可能因 OS / glibc 版本兼容问题
- 多个项目用不同 Node 版本时偶尔切版本(mise 自动)
方案 B:docker compose(容器化)
docker-compose.yml:
services:
web:
build: .
volumes:
- .:/app
- node-modules:/app/node_modules # 不让 host 的覆盖
ports: ["3000:3000"]
environment:
DATABASE_URL: postgresql://app:dev@db/myapp
REDIS_URL: redis://redis:6379
depends_on:
- db
- redis
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: dev
POSTGRES_DB: myapp
volumes:
- pg-data:/var/lib/postgresql/data
ports: ["5432:5432"]
redis:
image: redis:7
volumes:
- redis-data:/data
volumes:
pg-data:
redis-data:
node-modules:
Dockerfile:
FROM node:20-slim
RUN apt update && apt install -y python3 build-essential libpq-dev \
ffmpeg imagemagick
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npm", "run", "dev"]
docker compose up
优点:
- 跨 OS 完全一致(Mac / Linux / Windows 同结果)
- 系统依赖 (ffmpeg 等) 在 Dockerfile,新人 onboarding
docker compose up
完事 - 接近生产环境
- 多项目隔离(每个项目自己一组 service)
缺点:
- 启动慢(image build 几分钟;首次 download image 几 GB)
- IDE 集成稍复杂(要让 IDE 知道 venv 在容器里)
- Mac / Windows 上 docker desktop 占内存(默认 4-8 GB)
- 文件系统 bind mount 在 macOS 上有性能损失(npm install / build 慢 3-5x)
我的选择矩阵
| 场景 | 推荐 |
|---|---|
| 个人项目 + Linux 桌面 | mise + direnv |
| 个人项目 + Mac/Win | mise + Docker for DB only |
| 团队多人多 OS | docker compose |
| 复杂多服务(5+ container) | docker compose(基本必须) |
| 需要 IDE 强 debug | mise(host 跑 Python/Node 直 debug) |
| onboarding 时间宝贵 | docker compose |
| CI 跑测试 | docker compose 镜像 + GitHub Action |
混合方案(我个人用)
主要业务代码跑 host(mise 装好 Node/Python),仅 DB / Redis /
LocalStack 等 service 跑 docker。
docker-compose.dev.yml:
services:
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: dev
POSTGRES_DB: myapp
ports: ["127.0.0.1:5432:5432"]
volumes: [pg-data:/var/lib/postgresql/data]
redis:
image: redis:7-alpine
ports: ["127.0.0.1:6379:6379"]
volumes:
pg-data:
docker compose -f docker-compose.dev.yml up -d
mise install
direnv allow
npm run dev # 跑 host
两者优点结合:IDE debug 顺滑 + 数据库环境一致。
痛点解决
Mac docker 文件慢
volumes:
- .:/app:delegated # macOS 优化(让容器写少同步给 host)
或用 mutagen-compose:rsync 风格双向同步代替 bind mount,
性能 10x。
node_modules 不同步
volumes:
- .:/app
- /app/node_modules # named volume 让容器内的 node_modules 不被 host 空目录覆盖
多项目端口冲突
每个项目用不同端口:
ports: ["127.0.0.1:5433:5432"] # 项目 A
ports: ["127.0.0.1:5434:5432"] # 项目 B
或者用 Traefik 共享一个反代(前面有篇)。
完全云端 dev:Codespaces / Gitpod
// .devcontainer/devcontainer.json
{
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "20" },
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"postCreateCommand": "uv sync"
}
GitHub Codespaces 一键起一个云端 VSCode(已配齐所有依赖)。新人 30 秒
能 contribute,不需要本地装任何东西。
效果
我们团队(5 人,Mac/Linux 混用)现在用"混合方案":
- 新人 onboarding 从 2 天 → 30 分钟(mise install + docker compose up)
- IDE 调试体验保持原生
- 数据库版本统一(postgres 16)跨所有人无差异
- CI 用同样 docker image 测试 → 部署
- "我机器能跑" 类问题归零
踩过的坑
-
mise 装的 Python 链接 libssl 失败:openssl 升级后老 Python
坏。mise reshim重新链接,或mise uninstall python && mise install。 -
docker compose volume 跨用户权限:root 跑了 docker,host
非 root 用户读不了 volume 文件。改 docker-composeuser: "1000:1000"
或 chown。 -
.env进 git:永远.env.example进 git,.env进 gitignore。 -
依赖装到全局:用 mise 跑
npm install -g会装到 mise 管的
Node 里。换 Node 版本就丢。改npx some-tool或本地 dev dep。 -
VSCode 用错 venv:
.vscode/settings.json指明
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"。
登录后参与评论。