用 Docker 跑单个应用不难,但一个项目往往要同时跑好几个容器:Web 响应、数据库、Redis、后台任务……一个个 docker run 又长又容易乱,容器的启动顺序、网络、依赖全要手动管。Docker Compose 就是来解决这个问题的:用一个 docker-compose.yml 把整套应用的容器、网络、卷、依赖关系都写好,一条命令一键启动、停止、重建。这篇把它讲清楚。
一、Docker Compose 是什么
Compose 是 Docker 官方的"多容器编排工具"。你用声明式写法,描述一套应用包含哪些服务、每个服务用什么镜像、暴露什么端口、挂载哪些数据卷、谁和谁有依赖,然后一条 docker compose up 就全部拉起来。
相比一个个 docker run,Compose 的优势:
- 可读可复用:完整配置写在一个文件里,看懂即掌握
- 一键启停:
up启动、down停止、logs看日志 - 自动建网络:服务之间用服务名互通,不用记 IP
- 统一管理卷:数据持久化、环境变量集中配置
二、安装 Docker Compose
新版 Docker 已内置 docker compose 插件(带空格)。检查:
docker compose version
若没有,按 Docker 安装教程装好 Docker 后,再装 Compose 插件:
apt install -y docker-compose-plugin # Debian/Ubuntu
yum install -y docker-compose-plugin # CentOS 系
老版本是单独的二进制 docker-compose,命令用法几乎一致。
三、第一个 docker-compose.yml
在项目目录新建 docker-compose.yml,来个 WordPress + MySQL 的例子:
version: "3.8"
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80" # 宿主机8080 → 容器80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_PASSWORD: secret
depends_on:
- db
volumes:
- wp_data:/var/www/html
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
volumes:
wp_data:
db_data:
关键语句含义:
services:定义有哪些服务(容器)image:用哪个镜像ports:映射端口宿主机:容器environment:注入环境变量depends_on:启动顺序依赖volumes:数据卷,持久化数据
在项目目录运行:
docker compose up -d # 后台启动整套
浏览器访问 http://服务器IP:8080,WordPress 安装界面就出来了。
四、常用命令速查
docker compose up -d # 后台启动/更新
docker compose ps # 查看各服务状态
docker compose logs -f # 跟随查看日志
docker compose down # 停止并删除容器/网络
docker compose down -v # 连数据卷一起删(慎用,会清数据)
docker compose restart # 重启
docker compose exec 服务名 命令 # 进入某容器(如 bash)
docker compose config # 检查/预览最终配置
改动配置后,重新应用用 up -d 即可,它会按需重建变更的服务。
五、配置文件详解
1. 端口映射:
ports:
- "8080:80" # 宿主机8080 → 容器80
- "127.0.0.1:9000:9000" # 只对本机开放
2. 环境变量(两种方式):
environment:
- KEY=value # 数组写法
KEY2: value2 # 映射写法
# 或从 .env 文件读取
env_file:
- .env
3. 数据卷与目录挂载:
volumes:
- ./本地目录:/容器内路径 # 挂宿主机目录(开发常用)
- named_vol:/容器内路径 # 用命名卷持久化(生产推荐)
4. 依赖与健康检查:
depends_on:
db:
condition: service_healthy
5. 固定容器与重启策略:
restart: unless-stopped # 断电/崩溃自动重启
container_name: my-web # 指定容器名
六、实战:一个完整的 LNMP 风格栈
把 Python/Node API + Redis + PostgreSQL 组在一起:
services:
app:
build: . # 用当前目录 Dockerfile 构建
ports:
- "5000:5000"
depends_on:
- redis
- db
environment:
REDIS_HOST: redis
DB_HOST: db
redis:
image: redis:7
restart: unless-stopped
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
build: . 说明 app 是用当前目录里的 Dockerfile 自己构建的,适合自己的代码。
七、会用到的几个技巧
1. 自定义网络: Compose 默认自动建一个网络,服务之间用服务名访问。要自定义就加:
networks:
mynet:
driver: bridge
2. 不同环境多份文件: 可拆 docker-compose.yml + docker-compose.prod.yml,用 -f 合并:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
3. 扩容服务: Compose 简单场景一条命令拉多副本:
docker compose up --scale app=3 -d
(真正的负载均衡建议配合本站 Nginx 反向代理教程做接入层。)
八、常见问题
Q1:启动报端口被占用?
ports 里宿主机端口已被占用。换个端口,或先 docker compose down 释放再起。
Q2:depends_on 拉起顺序不对,服务一直失败?
depends_on 只保证启动顺序,不保证服务就绪。配合 healthcheck 和 condition: service_healthy 更稳妥,或加 restart: unless-stopped 让它重试。
Q3:数据丢了?
确认用命名卷或挂载目录持久化,避免只用容器内路径。down -v 会删卷,别乱用。
Q4:容器时间不对 / 时区问题?
在服务里挂载时区或设 TZ 环境变量,或挂 /etc/localtime。
Q5:Compose 和 k8s 的关系?
个人站/小项目用 Compose 足够;大规模集群、自动扩缩、滚动更新才上 Kubernetes。别动不动就上 k8s,徒增复杂度。
九、和 Docker 底层的关系
Compose 底层还是用 Docker 的镜像、容器、网络、卷,只是把你"要跑哪些容器、怎么连"写成了声明式文件。掌握好基础 Docker 命令(本站 Docker 安装教程)后,用 Compose 能让部署从"一堆命令"变成"一个文件一段命令",是 Docker 建站运维的进阶必备。
总结
Docker Compose 把复杂应用栈的部署写成一份可读的 docker-compose.yml,up -d 一键起整套:写 services → 定义端口/环境/卷/依赖 → up 启动 → logs 排障。配合数据卷持久化、健康检查、restart 策略,就能稳定地跑起真实业务。一台服务器上部署多套服务再配合 Nginx 反向代理,就能优雅地运营多个项目。
