一、容器多了怎么管
docker 官方的开源项目,负责对 docker 集群的快速编排。说白了就是:多个容器之间的调用关系写在一个文件里,一条命令同时启停。

docker 建议一个容器里只跑一个服务,容器本身占资源很少,把服务拆开是好事,但拆完就面临一个新问题 —— 我难道要给每个服务单独写 Dockerfile、构建镜像、再一个个起容器?

比如一个 Web 微服务,除了自己,后面还得跟 MySQL、Redis、注册中心 eureka,甚至负载均衡。Compose 就是来解决这个的:用一份 docker-compose.yml 把这一组容器定义成一个项目(project),一条指令把依赖全都装好、构建、跑起来。
这块对运维的要求其实不高,会这四件事就够用:
- 能看懂参数配置
- 能修改版本、端口、变量
- 会排错
docker compose logs/config看日志/验证语法,处理常见的启动失败(端口冲突、挂载目录权限) - 写基础shell脚本(部署、重启、备份)调用yml
二、安装
现在官方推荐的是 Compose V2,装完命令是 docker compose(中间有空格);老版本的 docker-compose(连字符)是 V1,已经停止维护了。V1 和 V2 语法大部分一样,但文件写法上有区别。
方法一:走 Docker 官方源(最推荐),前提是机器上已经按官方方式装好了 docker:
sudo apt update
sudo apt install docker-compose-plugin
# 如果报错需要修复
apt --fix-broken install -y
# v1旧命令
docker-compose --version
# 检查
docker compose version
root@VM-0-12-ubuntu:~# docker compose version
Docker Compose version v5.5.1
CentOS / RHEL 换成:
sudo yum install docker-compose-plugin
方法二:手动下二进制(没配官方源的时候用),把它丢进 docker 的插件目录就行:
sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
GitHub 下载慢的话,把链接里的域名换成国内加速镜像,比如 github.com 换成 ghproxy.com/https://github.com 这种形式。
装完用 docker compose version 验证,能输出 Docker Compose version v2.x.x 就成了。
三、核心概念
核心就是编写 docker-compose.yml 这一个文件,用到的也就三步:

- 编写 Dockerfile 定义各个微服务应用并构建出对应的镜像文件
- 使用
docker-compose.yml定义一个完整业务单元,安排好整体应用中的各个容器服务 - 执行
docker compose up启动并运行整个应用程序,完成一键部署上线
常用命令
# Compose常用命令
docker compose -h # 查看帮助
docker compose up # 启动所有docker-compose服务
docker compose up -d # 启动所有docker-compose服务并后台运行
docker compose down # 停止并删除容器、网络、卷、镜像。
docker compose exec yml里面的服务id # 进入容器实例内部 docker compose exec docker-compose.yml文件中写的服务id /bin/bash
docker compose ps # 展示当前docker-compose编排过的运行的所有容器
docker compose top # 展示当前docker-compose编排过的容器进程
docker compose logs yml里面的服务id # 查看容器输出日志
docker compose config # 检查配置
docker compose config -q # 检查配置,有问题才有输出
docker compose restart # 重启服务
docker compose start # 启动服务
docker compose stop # 停止服务
真正排错的时候用得最多的三组:docker compose config -q 验语法、docker compose ps 看状态、docker compose logs 服务id 看日志。
四、案例:把微服务改成 compose 项目
这块有不少开发的东西,只关注两个重点:构建镜像用的 Dockerfile 和 编排用的 docker-compose.yml。

先把微服务打包成 jar 传到 linux 的 /mydocker 下,一开始这个目录里就只有 jar 包和 Dockerfile:

这份 Dockerfile 在 Dockerfile 那两页里已经逐行解释过了,这里再放一遍方便对照:

镜像构建就一条命令:
docker build -t zzyy_docker:1.6 .
构建完是这样:

接下来是关键的一步: 微服务里原来连 MySQL、Redis 写的都是宿主机的 IP,现在容器在一个网络里,直接把 IP 换成服务名:

改成服务名之后,IP 变了也不用动配置,这也是 compose 编排里最省事的地方。
然后写 /mydocker/docker-compose.yml:
version: "3" # 指定 Compose 文件版本
services:
# 业务微服务模块(定义服务名称)
microService:
image: zzyy_docker:1.6
container_name: ms01
ports:
- "6001:6001" # 映射宿主机 6001 到容器 6001
volumes:
- /app/microService:/data # 挂载数据目录
networks:
- atguigu_net
depends_on: # 本快服务依赖于redis和mysql先启动
- redis
- mysql
# Redis 缓存服务
redis:
image: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /app/redis/redis.conf:/etc/redis/redis.conf # 挂载配置文件
- /app/redis/data:/data
networks:
- atguigu_net
command: redis-server /etc/redis/redis.conf
# MySQL 数据库服务
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456' # 设置 root 密码
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2021'
MYSQL_USER: 'zzyy'
MYSQL_PASSWORD: 'zzyy123'
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql # 持久化数据
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- atguigu_net
command: --default-authentication-plugin=mysql_native_password
# 自定义网络(network create)
# 这样容器之间就能用服务名访问了而不是IP
networks:
atguigu_net:
这份 yml 里的 microService 服务,等价于下面这条手工 run 的命令,对照着看就明白 ports、volumes、networks 分别对应命令行里的什么参数:
# 这个服务的配置相当于:
# 先确保 redis 和 mysql 容器已运行且在同一网络
docker run -d \
--name ms01 \
--network atguigu_net \
-p 6001:6001 \
-v /app/microService:/data \
zzyy_docker:1.6
depends_on 这一段的意思是,本服务依赖 redis 和 mysql 先启动,compose 会按顺序把它们拉起来。
写之前记得把旧的 jar、旧容器、旧镜像都删掉再重新上传,这时候 /mydocker 里就是三件套齐全了:

启动之前先验一下语法:
# 检查
docker compose config -q
# 启动
docker compose up -d
docker ps
docker compose stop
一键起来的输出是这样,网络、redis、mysql、ms01 一个不落:

容器名的前缀跟文件所在的目录有关(yml 里没写 container_name 的话就会带上项目名前缀),所以我们看到的是 mydocker_redis_1、mydocker_mysql_1,而写了 container_name: ms01 的就直接叫 ms01。
自定义网络的名字也是同理,按 compose 编排规则,生成的自定义网络由文件路径(项目名)决定,这里就变成了 mydocker_atguigu_net:

最后验证业务:通过网页的微服务给 redis 写入数据,然后给到 mysql,在 mysql 里创建表,进网页插入数据,再分别到 redis 和 mysql 里查一下数据在不在,都在就说明这套编排是通的。
五、图形化管理工具
图形界面的管理工具(Portainer)在容器实战那一页已经用过一遍了,这里不重复。到 compose 这一层,docker compose ps / logs / config 基本就够用 —— 编排过的容器状态、日志、配置都能从命令行看完。
Docker 的基础体系到这儿就齐了:镜像、容器、数据卷、网络,加上这一篇的 compose 编排。再往下就是 CI/CD 那些事了。