1. ${NODE_ENV:-production} 语法解释
这是Docker Compose的环境变量替换语法:
${NODE_ENV:-production}表示:如果环境变量NODE_ENV存在且不为空,则使用NODE_ENV的值;否则使用默认值production:-是默认值操作符- 等价于:
NODE_ENV=${NODE_ENV:-production}
示例:
# 如果 .env 文件中有 NODE_ENV=development
# 则实际值为 development
# 如果 .env 文件中没有 NODE_ENV 或为空
# 则使用默认值 production
2. Docker服务重启和更新
Docker不会自动监听文件变化,需要手动重启:
修改docker-compose.yaml后:
# 停止所有服务
docker-compose down
# 强制重新构建镜像
docker-compose build --no-cache app
# 强制重启所有服务
docker-compose up -d
# 重新构建并启动所有服务
docker-compose up --build -d <service_name>
# 或者只重启特定服务
docker-compose restart app
# docker-compose 进入容器(交互式)
docker compose exec <service_name> bash
docker compose exec <service_name> sh
# docker-compose 进入容器并执行命令(直接执行命令)
docker compose exec <service_name> <command>
# 直接执行命令
docker compose exec backend sh -c "npm run build"
docker compose exec backend sh -c "cd /app && node index.js"
# 创建临时容器执行命令
docker compose run --rm <service_name> <command>
3. restart: unless-stopped 含义
这是Docker容器的重启策略:
| 策略 | 说明 |
|---|---|
no | 不自动重启(默认) |
always | 总是重启,无论退出状态如何 |
on-failure | 只在非零退出状态时重启 |
unless-stopped | 总是重启,除非手动停止 |
unless-stopped 的优势:
- 容器异常退出时自动重启
- 系统重启后自动启动容器
- 手动停止后不会自动重启(避免干扰调试)
4. 完整的重启流程示例
# 1. 停止所有服务
docker-compose down
# 2. 查看当前状态
docker-compose ps
# 3. 重新构建并启动
docker-compose up --build -d
# 4. 查看日志
docker-compose logs -f app
# 5. 检查服务状态
docker-compose ps
5. 开发环境建议
对于开发环境,建议使用卷挂载来避免频繁重建:
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app # 代码同步
- /app/node_modules # 避免覆盖依赖
command: pnpm run start:dev # 开发模式,支持热重载
这样代码修改后,只需要重启应用进程,不需要重新构建镜像。
6.修改配置
非常好的问题 👍,你这个担心是非常现实的 ——
在 docker-compose 项目中执行 up -d --build 确实会重新构建所有 build 声明的服务镜像,但默认情况下 不会自动清除已有的数据卷(volumes)或数据库数据,除非你显式删除了容器或卷。
不过,让我们来非常清晰地分辨几种情况👇
🧱 一、
docker-compose up -d --build
实际做了什么?
执行:
docker-compose up -d --build
Compose 会:
- 检查哪些服务定义了 build:;
- 对这些服务重新构建镜像;
- 停止并重启依赖该镜像的容器;
- 保留挂载的卷(volumes)内容;
- 不会删除数据卷;
- 不会影响使用外部镜像(如 image: mysql:8.0)的服务。
✅ 举个例子:
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
volumes:
- ./app:/usr/src/app
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:
执行:
docker-compose up -d --build
结果:****
- ✅ app 会被重新 build;
- 🚫 mysql 和 redis 不会被重新构建;
- ✅ 数据卷 mysql_data / redis_data 不会丢失。
⚙️ 二、只重建(build + restart)某一个服务
你可以只 rebuild 某个服务,而不动其他的服务:
docker-compose up -d --build app
或者如果你只想重新 build 但暂不运行容器:
docker-compose build app
再启动:
docker-compose up -d app
👉 这不会动 mysql、redis,也不会影响数据卷。
🧩 三、如果你真的删除了容器,会不会丢数据?
这取决于是否挂了 volume:
| 情况 | 数据是否丢失 |
|---|---|
| 使用了命名卷(volumes:) | ❌ 不会丢 |
| 使用了匿名卷(未命名) | ⚠️ 会丢 |
| 用了 bind 挂载(./mysql_data:/var/lib/mysql) | ❌ 不会丢(在宿主机文件夹中) |
| 手动执行了 docker-compose down -v | ❌ 会清除所有卷 |
🧠 四、正确的安全更新姿势(推荐)
✅ 推荐方式 1:只重建目标服务
docker-compose up -d --build app
✅ 推荐方式 2:重建但不影响数据库
docker-compose up -d --no-deps --build app
--no-deps 表示不重启依赖的容器,比如数据库。
✅ 推荐方式 3:手动重建镜像
docker-compose build app
docker-compose restart app
💣 五、注意哪些操作会真的清空数据库数据
| 命令 | 说明 |
|---|---|
| docker-compose down -v | ❌ 删除容器 + 数据卷(会清空数据) |
| docker-compose rm -f mysql | ❌ 删除容器,如果卷是匿名的,会丢数据 |
| docker volume prune | ❌ 删除所有未使用的卷(危险) |
| docker system prune -a | ⚠️ 会清空所有未运行容器和未挂载卷 |
✅ 六、最佳实践总结
| 目的 | 命令 | 说明 |
|---|---|---|
| 只重建某个服务 | docker-compose up -d --build app | 推荐方式 |
| 不重启依赖容器 | docker-compose up -d --no-deps --build app | 更稳妥 |
| 只编译镜像,不运行 | docker-compose build app | 手动控制启动 |
| 检查卷挂载情况 | docker volume ls | 确认数据安全 |
| 恢复卷数据 | 使用命名卷或宿主机挂载 | 永远别用匿名卷保存数据 |
✅ 一句话总结:****
修改了 Dockerfile,只想让该服务重建而不影响数据库:
docker-compose up -d --no-deps --build app
💡 数据卷不会丢失,MySQL / Redis 会继续使用原数据。
是否要我帮你生成一个“多服务项目安全更新模板”,
包含 Makefile + docker-compose 的命令脚本(支持一键安全更新应用服务但不动数据库)?