深色模式
Docker Compose
概述
单个容器用 docker run 就能管理,但只要服务一多,事情马上开始变得重复:这个容器要挂卷,那个容器要连数据库,另一个容器还要依赖前两个一起启动。命令本身没有变复杂,复杂的是“多个容器之间的关系”。
Compose 解决的正是这件事。它把多容器应用的定义写进一个 YAML 文件里,再用 docker compose 统一创建、启动、查看和销毁。
先统一一个写法
现在应该优先使用:
sh
docker compose而不是旧式:
sh
docker-compose这不是单纯的命令别名之争,而是 Compose v2 已经作为 Docker CLI 的子命令存在。新文章和新项目,最好都按这个口径写。
Compose 文件负责描述多容器关系
Compose 文件常见名字是:
compose.yamlcompose.ymldocker-compose.yml
现在官方文档更偏向使用 compose.yaml 这个名字,但旧项目里仍然经常能看到 docker-compose.yml。名字不是重点,结构才是重点。
先看一个完整示例
yaml
services:
app:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: production
DB_HOST: db
depends_on:
- db
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:这份文件里最重要的对象是 services。每个 service 本质上就是一个“容器定义模板”。
上面的示例表达了几件事:
app服务通过当前目录里的 Dockerfile 构建镜像db服务直接使用现成的 MySQL 镜像app依赖db- 数据库数据落在命名卷
db-data里
build 和 image 的差别
Compose 文件里最常见的一个疑问是:到底写 build 还是 image。
build:表示这个服务需要根据本地源码构建镜像image:表示这个服务直接使用现成镜像
例如:
yaml
services:
app:
build: .
redis:
image: redis:7应用服务常常用 build,数据库、缓存、反向代理这类基础服务常常用 image。这个分工很自然,不必强行统一。
常用字段先掌握这些
services
services 是 Compose 文件的主体。每个服务通常至少要定义镜像来源,以及它在运行时需要的配置。
ports
ports 用来把容器端口暴露到宿主机:
yaml
ports:
- "8080:80"左边是宿主机端口,右边是容器端口。
environment
environment 用来给容器注入环境变量:
yaml
environment:
NODE_ENV: productionvolumes
volumes 用来做数据持久化或文件挂载:
yaml
volumes:
- db-data:/var/lib/mysqlnetworks
如果不显式声明,Compose 通常也会给当前项目创建默认网络。大多数日常场景,这已经够用。只有在需要更细致地控制容器互联关系时,再单独写 networks。
depends_on
depends_on 用来表达服务依赖关系:
yaml
depends_on:
- db它能保证启动顺序,但不等于“依赖服务已经完全可用”。例如数据库进程启动了,不代表数据库初始化已经完成。这个边界最好心里有数。
最常用的 Compose 命令
启动项目:
sh
docker compose up后台启动:
sh
docker compose up -d停止并删除当前项目创建的容器、网络等资源:
sh
docker compose down查看日志:
sh
docker compose logs
docker compose logs -f app进入某个服务容器:
sh
docker compose exec app sh查看当前项目状态:
sh
docker compose ps这几组命令已经覆盖了 Compose 日常操作的大部分需求。
Compose 的真正价值在哪
Compose 最有价值的地方,不是少打几次 docker run,而是把“应用由哪些服务组成、它们怎么连接、数据放在哪里”写成了可版本化的配置。
这意味着:
- 新机器上更容易复现环境
- 团队成员之间更容易共享统一启动方式
- 本地开发和轻量部署的差距会小很多
只要项目开始涉及数据库、缓存、反向代理或多服务协作,Compose 的收益通常就已经很明显了。
