首页  /  云原生  /  正文

Docker Compose 编排实战

云原生 2026-10-02📖 12 分钟👁 —
🐳 云原生 · Docker第 6 / 9 页123456789📖 完整导航 →

一、容器多了怎么管

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

Compose 是什么:用 YAML 描述多个容器组成的应用,一个命令同时启动或关闭

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

单独部署多个服务的痛点和 Compose 的定位:一个 yml 定义一组关联容器

比如一个 Web 微服务,除了自己,后面还得跟 MySQL、Redis、注册中心 eureka,甚至负载均衡。Compose 就是来解决这个的:用一份 docker-compose.yml 把这一组容器定义成一个项目(project),一条指令把依赖全都装好、构建、跑起来。

这块对运维的要求其实不高,会这四件事就够用:

  1. 能看懂参数配置
  2. 能修改版本、端口、变量
  3. 会排错 docker compose logs/config 看日志/验证语法,处理常见的启动失败(端口冲突、挂载目录权限)
  4. 写基础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 这一个文件,用到的也就三步:

Compose 使用的三个步骤:写 Dockerfile 构建镜像、用 docker-compose.yml 定义业务单元、docker compose up 启动
  1. 编写 Dockerfile 定义各个微服务应用并构建出对应的镜像文件
  2. 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务
  3. 执行 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。

改造升级微服务工程 docker_boot 的路线:先不用 Compose 手工跑一遍,再改成 Compose

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

pwd 显示在 /mydocker,ll 里只有 docker_boot-0.0.1-SNAPSHOT.jar 和 Dockerfile

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

微服务的 Dockerfile:FROM java:8,VOLUME /tmp,ADD 把 jar 改名,ENTRYPOINT 启动,EXPOSE 6001

镜像构建就一条命令:

docker build -t zzyy_docker:1.6 .

构建完是这样:

docker images zzyy_docker:1.6 构建成功,镜像 ID 423140943d00,大小 760MB

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

配置文件里把 jdbc 的 IP 改成 mysql、redis.host 改成 redis

改成服务名之后,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 里就是三件套齐全了:

重新上传后 /mydocker 目录下的 docker_boot-0.0.1-SNAPSHOT.jar、docker-compose.yml 和 Dockerfile

启动之前先验一下语法:

# 检查
docker compose config -q

# 启动
docker compose up -d

docker ps

docker compose stop

一键起来的输出是这样,网络、redis、mysql、ms01 一个不落:

docker compose up -d 的输出:创建 mydocker_atguigu_net 网络,依次创建 redis、mysql、ms01 容器

容器名的前缀跟文件所在的目录有关(yml 里没写 container_name 的话就会带上项目名前缀),所以我们看到的是 mydocker_redis_1、mydocker_mysql_1,而写了 container_name: ms01 的就直接叫 ms01。

自定义网络的名字也是同理,按 compose 编排规则,生成的自定义网络由文件路径(项目名)决定,这里就变成了 mydocker_atguigu_net:

docker network ls 里出现了 mydocker_atguigu_net,驱动是 bridge

最后验证业务:通过网页的微服务给 redis 写入数据,然后给到 mysql,在 mysql 里创建表,进网页插入数据,再分别到 redis 和 mysql 里查一下数据在不在,都在就说明这套编排是通的。


五、图形化管理工具

图形界面的管理工具(Portainer)在容器实战那一页已经用过一遍了,这里不重复。到 compose 这一层,docker compose ps / logs / config 基本就够用 —— 编排过的容器状态、日志、配置都能从命令行看完。

Docker 的基础体系到这儿就齐了:镜像、容器、数据卷、网络,加上这一篇的 compose 编排。再往下就是 CI/CD 那些事了。