Appearance
Docker Compose:一条命令拉起前端 + 后端 + 数据库
更新: 8/8/2026 字数: 0 字 时长: 0 分钟
一、开篇:前端本地联调,到底难在哪?
作为有后端接口基础的前端开发者,你一定经历过这种“启动仪式”:
text
终端 1:cd frontend && npm run dev
终端 2:cd backend && npm run start
终端 3:本地装 MySQL / Postgres,改配置,建库建表
再回头:改后端的数据库连接串
最后:还要处理跨域、端口冲突、环境变量……开三四个终端窗口,配一堆环境,稍不注意就报错。更糟的是,新同事入职、换台电脑、或者你三个月后回到这个项目,又要从头折腾一遍环境。
联调的痛点其实就三个:
- 服务多:前端、后端、数据库要一个个手动起;
- 依赖装环境:本地要装数据库、装运行时,版本还容易不一致;
- 难复现:“在我电脑上是好的”,换个人就崩。
Docker Compose 就是来解决这件事的:把前端、后端、数据库的启动方式写进一个配置文件,然后用一条命令全部拉起来。

二、Compose 是什么?一句话理解
如果说 Dockerfile 是“如何打包一个服务”,那么 Docker Compose 就是“如何一次编排并启动多个服务”。
你可以把它类比成前端的 package.json + npm scripts:
一份声明式的配置文件,描述“我要哪些东西、怎么跑、谁依赖谁”,然后一条命令搞定。
区别是,package.json 管的是依赖包,Compose 管的是一整套运行中的服务。

三、核心实操:含 3 个服务的 docker-compose.yml
假设我们有一个典型全栈项目,目录结构如下:
text
my-fullstack-app/
├── frontend/ # Vue / React 项目
│ └── Dockerfile
├── backend/ # Node.js / Express 接口服务
│ └── Dockerfile
└── docker-compose.yml # 编排文件(本文主角)下面是完整可运行的 docker-compose.yml:
yaml
# docker-compose.yml
services:
# ---------- 服务一:前端 ----------
web:
build: ./frontend # 用 frontend 目录下的 Dockerfile 构建
ports:
- "5173:5173" # 宿主机端口:容器端口,浏览器访问 5173
volumes:
- ./frontend:/app # 把本地代码挂进容器,实现热更新
- /app/node_modules # 匿名卷:避免本地覆盖容器内依赖
environment:
- VITE_API_BASE=http://localhost:8080 # 前端请求后端的地址
depends_on:
- api # 声明依赖:api 先启动
# ---------- 服务二:后端 ----------
api:
build: ./backend
ports:
- "8080:8080"
environment:
# 注意:这里连数据库用的是服务名 db,不是 localhost
- DB_HOST=db
- DB_PORT=5432
- DB_USER=appuser
- DB_PASSWORD=apppass
- DB_NAME=appdb
depends_on:
db:
condition: service_healthy # 等数据库健康后再启动
# ---------- 服务三:数据库 ----------
db:
image: postgres:16-alpine # 直接用官方镜像,无需本地安装
environment:
- POSTGRES_USER=appuser
- POSTGRES_PASSWORD=apppass
- POSTGRES_DB=appdb
ports:
- "5432:5432" # 方便本地用数据库工具连接调试
volumes:
- db_data:/var/lib/postgresql/data # 数据持久化,删容器也不丢
healthcheck: # 健康检查,供 api 的 depends_on 用
test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
interval: 5s
timeout: 3s
retries: 5
# 具名卷:由 Docker 管理,用于持久化数据库数据
volumes:
db_data:逐段解释(前端视角)
1. services 下三个服务:web / api / db
这就是你要的三样东西:前端、后端、数据库。每个服务名(web、api、db)很重要——它同时也是容器之间互相访问的主机名。
2. build vs image
web和api用build,表示用你项目里的 Dockerfile 现场构建(因为是你自己的代码);db用image: postgres:16-alpine,直接拉官方镜像,你不用在本机安装 Postgres。
3. ports:端口映射
格式是 "宿主机端口:容器端口"。"5173:5173" 意味着你在浏览器访问 localhost:5173 就能打开前端。
4. environment:环境变量
这里有个关键点:后端连数据库时,DB_HOST=db,用的是服务名 db,而不是 localhost。因为在 Compose 里,各服务在同一个虚拟网络中,可以直接用服务名互相访问(下文详解)。
5. depends_on:启动顺序
保证数据库先起、后端再起。配合 healthcheck,还能做到“等数据库真正就绪”,避免后端启动太快连不上库。
启动命令:真正的“一条命令”
bash
# 在 docker-compose.yml 所在目录执行
docker compose up想在后台运行(不占用终端):
bash
docker compose up -d首次会构建镜像、拉取 Postgres、创建网络和卷,然后三个服务一起跑起来。停止并清理:
bash
docker compose down四、服务之间怎么互相“看见”?网络与数据持久化

1. 自动组网:服务名就是主机名
Compose 会自动为这一组服务创建一个虚拟网络。在这个网络里:
- 后端连数据库:
DB_HOST=db; - 如果后端要调另一个服务,也直接用服务名。
这是新手最容易踩的坑:在容器里写 localhost 指的是容器自己,不是别的服务。所以容器间通信一定用服务名。
2. 数据持久化:具名卷(volume)
数据库数据默认存在容器里,容器一删数据就没了。通过:
yaml
volumes:
- db_data:/var/lib/postgresql/data把数据存进 Docker 管理的具名卷 db_data,即使 docker compose down 删掉容器,数据依然保留。只有执行 docker compose down -v 才会连卷一起删。
五、前端常用拓展知识点

1. 卷挂载实现热更新(前端开发必备)
前端开发最怕“改一行代码要重新构建镜像”。用绑定挂载把本地代码映射进容器:
yaml
volumes:
- ./frontend:/app # 本地代码 → 容器,改代码容器内实时同步
- /app/node_modules # 匿名卷,保护容器内已装好的依赖不被覆盖这样你在本地编辑器改代码,容器里的 dev server 会自动热更新。
注意第二行:
- /app/node_modules是为了防止本地目录(可能没装依赖或平台不兼容)覆盖掉容器里的node_modules。这是前端用 Compose 的高频坑点。
2. 跨域处理:两种主流思路
本地联调最烦的就是 CORS 跨域。有两种常见解法:
思路 A:后端开发环境放开 CORS
js
// backend 仅在开发环境
app.use(cors({ origin: 'http://localhost:5173' }));思路 B:前端 dev server 配代理(推荐,更贴近生产)
以 Vite 为例:
js
// vite.config.js
export default {
server: {
host: '0.0.0.0', // 容器里必须监听 0.0.0.0,否则外部访问不到
proxy: {
'/api': {
target: 'http://api:8080', // 用服务名 api
changeOrigin: true
}
}
}
}前端请求 /api/xxx,由 dev server 转发到后端,浏览器视角没有跨域,也更接近生产环境的网关代理模式。
前端专属坑:容器里 dev server 一定要监听
0.0.0.0,只监听localhost会导致宿主机浏览器打不开。
3. 常用命令速查
bash
# 启动(前台,看日志)
docker compose up
# 后台启动
docker compose up -d
# 重新构建并启动(改了 Dockerfile / 依赖后用)
docker compose up -d --build
# 查看所有服务日志
docker compose logs -f
# 只看某个服务日志
docker compose logs -f api
# 查看运行状态
docker compose ps
# 停止并删除容器、网络(保留数据卷)
docker compose down
# 连数据卷一起删(慎用,数据会丢)
docker compose down -v
# 进入某个容器调试
docker compose exec api sh4. 用 .env 管理配置
把敏感信息和易变配置抽到 .env 文件,Compose 会自动读取:
text
# .env
DB_USER=appuser
DB_PASSWORD=apppass
DB_NAME=appdb在 yml 里引用:
yaml
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}记得把 .env 加进 .gitignore,别把密码提交上去。
5. 数据库初始化脚本
想让数据库启动时自动建表、灌初始数据,可以挂载初始化脚本:
yaml
db:
image: postgres:16-alpine
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 首次启动自动执行init.sql 会在数据库首次初始化时执行,非常适合本地联调准备测试数据。
六、常见坑与上手建议
常见坑
容器内用 localhost 连别的服务
- 错误:
DB_HOST=localhost - 正确:
DB_HOST=db(用服务名)
- 错误:
dev server 只监听 localhost
- 容器里必须
host: 0.0.0.0,否则宿主机浏览器访问不了。
- 容器里必须
本地 node_modules 覆盖容器依赖
- 记得加匿名卷
- /app/node_modules。
- 记得加匿名卷
后端启动比数据库快,连不上库
- 用
depends_on+healthcheck+condition: service_healthy。
- 用
down -v误删数据- 日常停服务用
docker compose down,别随手加-v。
- 日常停服务用
端口冲突
- 本地已占用 5432/8080 时,改宿主机端口即可,如
"15432:5432"。
- 本地已占用 5432/8080 时,改宿主机端口即可,如
上手建议
- 先跑通再优化:先用最简配置把三个服务连起来,再逐步加 healthcheck、代理、初始化脚本。
- 善用
logs -f:出问题第一时间看日志,定位是哪个服务、哪一步失败。 - 前端优先用代理方案:
proxy转发比放开 CORS 更贴近生产,减少“本地能跑上线跨域”的问题。 - 把 compose 文件纳入版本管理:这是团队“环境即代码”的核心资产,新人
git clone+docker compose up就能开工。
七、总结
Docker Compose 对前端开发者的价值,可以浓缩成一句话:
把“开好几个终端、装一堆环境”的联调仪式,变成一个文件 + 一条命令。
核心要点回顾:
text
1. 一个 docker-compose.yml 描述前端、后端、数据库三个服务
2. docker compose up 一键拉起,down 一键清理
3. 服务间通信用「服务名」,不是 localhost
4. 数据库数据用具名卷持久化,不怕删容器
5. 前端热更新靠卷挂载,跨域优先用 dev server 代理
6. 用 depends_on + healthcheck 控制启动顺序掌握它之后,无论是本地全栈联调、新人环境搭建,还是给项目写一份“开箱即用”的运行说明,你都能做到克隆代码 → 一条命令 → 环境起来。这正是现代前端工程化里“环境即代码”的重要一环。