docker-compose.yml 详细介绍
docker-compose.yml 是 Docker Compose 的配置文件,用来一次性定义、编排多个容器服务,实现多容器应用一键启动/停止。
Compose 核心用途:一个项目由多个容器(如web、数据库、redis)组成,写在这个yml里,一条命令管理整套环境。
版本说明:现在推荐使用 Compose Specification(新版,不再写
version:字段);旧版 v1/v2 会写version: '3.8'这种,已经逐步废弃。
一、基础语法规则(YAML)
# 注释以 # 开头
key: value
list:
- item1
- item2
YAML 对缩进极其敏感,必须用空格,不能用Tab,冒号后面必须带空格。
# 注释以 # 开头
key: value
list:
- item1
- item2
二、完整示例(带注释)
# docker-compose.yml
services:
# 服务名称,自定义,后续可作为容器间访问的域名
web:
# 镜像名称,本地没有会自动pull
image: nginx:alpine
# 构建:从Dockerfile构建镜像(二选一,image / build)
# build: ./docker/nginx
# build:
# context: ./
# dockerfile: Dockerfile
# args:
# APP_VERSION: v1.0
# 端口映射:主机端口:容器端口
ports:
- "8080:80"
- "443:443"
# 挂载数据卷:主机目录/命名卷:容器内路径
volumes:
# 绑定挂载(主机目录映射)
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
# 命名数据卷
- nginx_log:/var/log/nginx
# 环境变量
environment:
- TZ=Asia/Shanghai
- APP_ENV=prod
# 也可以单独加载env文件
env_file:
- ./.env
# 容器启动依赖(只是启动顺序,不等待服务就绪!)
depends_on:
- mysql
- redis
# 容器网络
networks:
- app_net
# 容器重启策略
restart: always
# no:退出不重启;on-failure:异常退出才重启;always:总是重启;unless-stopped:除非手动停止
# 覆盖容器启动命令
# command: nginx -g 'daemon off;'
# 容器内执行权限,用户id
user: "1000:1000"
# 资源限制(docker版本>=19.03)
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.2'
memory: 256M
# 健康检查
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "[http://localhost](http://localhost)"]
interval: 10s
timeout: 5s
retries: 3
start_period: 20s
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root123456
- MYSQL_DATABASE=demo_db
- TZ=Asia/Shanghai
volumes:
- mysql_data:/var/lib/mysql
networks:
- app_net
restart: always
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app_net
restart: always
# 定义命名数据卷
volumes:
nginx_log:
mysql_data:
redis_data:
# 自定义网络(默认compose会自动创建网络,推荐手动定义)
networks:
app_net:
driver: bridge # 网络驱动 bridge/host/none
三、顶级字段详解
1. services【最重要】
所有容器服务都写在这里,每一个子项就是一个容器服务。
服务名就是容器之间通信的DNS域名,比如在web容器里,直接用 mysql:3306 就能访问mysql容器,不用IP。
常用service子配置项
image
指定镜像,格式 镜像名:标签,如 mysql:8.0。
build
不从远程拉镜像,本地通过Dockerfile构建镜像。
context:构建上下文目录dockerfile:Dockerfile文件名(非默认时指定)args:构建时的构建参数
ports端口映射
格式:"主机端口:容器端口"
注意加引号,避免yaml解析出错。
- 只写容器端口:
- "80",随机主机端口映射。
⚠️ 不要和
network_mode: host同时使用,host网络不需要端口映射。
volumes数据挂载
三种类型:
- 绑定挂载:
./host目录:/容器目录,主机和容器双向同步,文件直接存在主机。 - 命名卷:
卷名:/容器目录,由docker管理,存在docker数据目录。 - 匿名卷:
/容器目录,自动生成随机名称,compose down默认会删除。
用途:持久化数据、挂载配置文件、代码目录。
environment环境变量
environment:
KEY1: value1
- KEY2=value2
两种写法:
environment:
KEY1: value1
- KEY2=value2
env_file: .env 读取外部环境变量文件,适合放密码。
depends_on依赖
控制容器启动顺序:先启动依赖服务,再启动当前服务。
❗ 重要坑:只保证容器启动顺序,不会等待mysql/redis服务完全就绪,容器启动成功不等于里面数据库就绪,业务代码自己要做重试。
restart重启策略no(默认):退出不重启on-failure:只有异常退出(退出码≠0)才重启always:无论正常/异常退出,总是重启unless-stopped:一直重启,除非手动stop容器,重启docker也会自动拉起
networks网络
指定服务加入哪个网络。同一个网络内,服务名互相DNS解析通信。
command
command: ["php", "-S", "0.0.0.0:8000"]
覆盖镜像默认的启动命令。
command: ["php", "-S", "0.0.0.0:8000"]
healthcheck健康检查
定期执行命令判断容器是否正常,不健康会标记状态。
deploy资源限制
限制容器CPU、内存。
注意:
docker-compose up默认不读取deploy,需要docker compose up --compatibility;docker stack deploy原生支持。
2. volumes 顶级卷定义
volumes:
mysql_data: # 直接声明,默认驱动local
声明命名卷,由docker管理,数据持久化。
执行 docker volume ls 可以查看。
volumes:
mysql_data: # 直接声明,默认驱动local
3. networks 顶级网络定义
networks:
app_net:
driver: bridge
自定义bridge网络,隔离不同项目容器。
networks:
app_net:
driver: bridge
Compose默认自动创建一个默认bridge网络,所有服务默认加入,但是自定义网络更清晰,适合多项目隔离。
4. configs / secrets(进阶)
用于Swarm集群,配置文件、敏感密码管理,单机compose很少用。
四、配套常用命令
新版命令:
docker compose(中间空格,推荐),旧版docker-compose(横杠,二进制工具)
# 启动所有服务(后台守护运行)
docker compose up -d
# 查看运行容器
docker compose ps
# 查看日志
docker compose logs -f web
# 停止服务,容器保留
docker compose stop
# 停止并删除容器、网络(卷默认保留)
docker compose down
# down同时删除命名卷(谨慎!会清空数据)
docker compose down -v
# 重新构建镜像再启动
docker compose up -d --build
五、常见坑点
- 缩进错误:yaml缩进错直接报错,不能用Tab。
- depends_on 只等容器启动,不等应用就绪,数据库连接需要业务重试。
- 端口冲突:主机端口被占用会启动失败。
- 挂载目录权限:linux主机目录uid/gid和容器不一致,会出现permission denied。
.env文件:和docker-compose.yml同目录,会自动加载里面变量,可以在yml中${VAR}引用。- windows路径:windows挂载路径要注意斜杠,推荐用相对路径。
六、.env 文件示例(配套使用)
# .env
MYSQL_ROOT_PASSWORD=root123
TZ=Asia/Shanghai
APP_PORT=8080
ports:
- "${APP_PORT}:80"
在yml中引用:
ports:
- "${APP_PORT}:80"
如果你需要,我可以:
- 给一份生产可用精简模板
- 或者一份本地开发用模板(带热加载)
- 或者讲解
docker compose和docker stack的区别。