Docker-compose知识点梳理,你要懂的都在这

前言

再说 Docker Compose 之前,先聊聊 DockerDocker 就像是一个超级 "集装箱",把你的应用程序及其依赖项一股脑打包起来,扔到任何环境都能稳定运行,完全不用担心 "水土不服"。

部署和管理繁多的服务是困难的。而这正是 Docker Compose 要解决的问题, 比如服务端除了服务端程序,可能还有mysql,redis等服务,他们都是互相依赖的关系,所以如何把这些集装箱都装在船上,一起打包过去,这就是Docker Compose要解决的问题 、

所以如果说Docker是集装箱的话,那么Docker Compose就是船

什么是Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。它通过一个 YAML 格式的配置文件(通常名为docker-compose.yml)来管理多个相关联的容器服务,允许你在一个文件中定义所有容器的配置信息,如镜像、端口映射、环境变量、数据卷挂载等,然后使用简单的命令一次性启动、停止或重新部署整个应用栈,极大地简化了容器编排的过程

Docker Compose的安装

在linux上的安装

因为我们学习Docker Compose是为了完善我们的CI/CD流程的, 所以我们会把我们本地的Docker Compose部署到linux服务器

我们不建议在服务器上下载二进制文件,因为非常的慢, 当然了,也有可能是咱的服务器垃圾

通过github下载二进制文件

进入到docker-compose的github发布页,

在对应版本的页面,往下拉到页尾,可以看到支持不同环境的下载选项。

本人这里选择docker-compose-linux-x86_64版本(注意不同linux主机的硬件不一致,根据实际硬件选择二进制文件)

上传文件,修改文件名
js 复制代码
# 拷贝文件到/usr/local/bin,如果文件已经在/usr/local/bin目录,忽略此步骤
# 假如二进制文件docker-compose-linux-x86_64上传的目录是:/opt/docker
cp /opt/docker/docker-compose-linux-x86_64 /usr/local/bin


# 更改二进制文件名字
mv docker-compose-linux-x86_64 docker-compose

授予权限

js 复制代码
sudo chmod +x /usr/local/bin/docker-compose

测试安装结果

js 复制代码
docker-compose --version

在mac上的安装

  • 通过 Homebrew 安装:如果你已经安装了 Homebrew,那么安装 Docker Compose 非常简单。只需在终端中运行以下命令:
bash 复制代码
brew install docker-compose
  • 手动安装 :首先,从 Docker Compose 的官方仓库下载适合 Mac 系统的二进制文件。然后,将下载的文件移动到系统路径中,例如/usr/local/bin/目录,并赋予其执行权限。假设下载的文件名为docker-compose-darwin-x86_64,可执行以下命令:
bash 复制代码
sudo mv docker - compose - darwin - x86_64 /usr/local/bin/docker - compose
sudo chmod +x /usr/local/bin/docker - compose
  • 通过 Docker Desktop 安装:如果你使用的是 Docker Desktop for Mac,它通常会自带 Docker Compose,无需额外安装。只需确保 Docker Desktop 已正确安装并启动,即可直接使用 Docker Compose。

Docker Compose的YAML配置文件重要知识点说明

Docker Compose 使用 YAML 格式的文件来定义应用服务。以下是其基本结构和常用字段介绍:

数据卷定义(volumes):

在 Docker Compose 中,volumes(卷)是用于持久化容器数据或共享容器与主机文件的重要机制。它可以解决容器重启后数据丢失的问题,还能方便地在主机和容器之间共享代码或配置文件。

  • 作用:将容器内的目录或文件映射到主机(或 Docker 管理的卷),实现数据持久化或双向同步。
  • 优势: 容器删除后,数据仍保存在主机或卷中。 主机修改文件后,容器内可实时生效(开发环境常用)。 多个容器可共享同一卷数据。

例:

yaml 复制代码
volumes:
  - mysql_data:/var/lib/mysql

也可以使用命令清除卷

bash 复制代码
# 删除卷(确保卷未被容器使用)
docker volume rm 卷名

网络定义(networks):

在 Docker Compose 中,networks 用于管理容器之间的网络连接,允许服务(容器)相互通信或隔离。通过自定义网络,你可以灵活控制哪些容器可以相互访问,以及如何暴露服务。例如:

yaml 复制代码
   networks:
      - flask-network # 在同一个网络下

depends_on

depends_on 可以保证容器的启动顺序, 但是不能保证是否启动完成

Docker Compose 常用命令

  1. docker compose up:启动所有服务。常用参数有-d(后台运行容器)、--build(在启动前重新构建服务镜像)等。如docker compose up -d --build表示以后台模式启动容器并重新构建镜像。
  2. docker compose down:停止并删除所有容器、网络和挂载卷。可搭配--volumes参数删除所有挂载的卷,--rmi all参数删除所有镜像。
  3. docker compose ps:查看当前 Compose 管理的容器状态。
  4. docker compose logs:查看服务的日志输出。-f参数可实时输出日志,--tail n参数仅显示最近 n 行日志。
  5. docker compose exec:在指定的服务容器中执行命令,如docker compose exec web sh可进入web容器的 shell 环境。
  6. docker compose build:构建配置文件中定义的所有服务镜像。--no - cache参数可禁用缓存构建,--pull参数强制拉取最新的基础镜像。

例子:flask+mysql

flask的dockerfile

yml 复制代码
FROM python:3.11-slim

WORKDIR /app

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 复制迁移脚本并赋予执行权限
COPY scripts/run_migrations.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/run_migrations.sh

# 暴露端口
EXPOSE 5000

# 启动命令(先执行迁移,再启动应用)
CMD ["sh", "-c", "run_migrations.sh && python run.py"]

其中run_migrations.sh的作用是迁移数据库

sh 复制代码
#!/bin/sh

# 检查迁移目录是否存在,不存在则初始化
if [ ! -d "migrations" ]; then
  echo "初始化数据库迁移..."
  flask db init
fi

# 创建迁移版本
echo "生成数据库迁移版本..."
flask db migrate

# 应用迁移
echo "应用数据库迁移..."
flask db upgrade

echo "数据库迁移完成"

接下来来配置一下docker-compose.yml文件

yml 复制代码
services:
  web:
    build: 
      context: .
      dockerfile: dockerfile
    ports:
      - "9002:9001"
    depends_on:
      - mysql
    environment:
      - DB_USER=root  # 数据库用户名(必填)
      - DB_PASSWORD=12345  # 数据库密码
      - DB_HOST=mysql  # 数据库服务名(docker 内部网络)
      - DB_PORT=3306
      - DB_NAME=stock
    volumes:
      - migrations_data:/app/migrations  # 持久化迁移文件
    networks:
      - flask-network # 在同一个网络下

  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=stock
      - LANG=C.UTF-8
    ports:
      - "3307:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    restart: always
    healthcheck:
            test: mysqladmin ping -h 127.0.0.1 -uroot -p123456;
            start_period: 5s
            interval: 5s
            timeout: 5s
            retries: 55
    networks:
      - flask-network # 在同一个网络下
    command: # 设置可以存储中文
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake

networks:
  flask-network: # 在同一个网络下
    driver: bridge

volumes:
  mysql_data:

如何在数据库打开以后再执行迁移数据库

比如flask想要迁移数据库就会有三个经常使用的命令

csharp 复制代码
flask db init
flask db migrate
flask db upgrade

但是这三个命令依赖于数据库已经启动的情况,上面我们说了depend_on,那么这个属性可以保证我们先启动数据库,再启动数据库迁移么,答案是不可以的, 因为他只能保证启动顺序,不能保证已经准备就绪

如果保证先启动数据库,在进行迁移

  1. 使用 depends_on + 脚本检测(推荐)
    depends_on 仅能保证容器的启动顺序(先启动数据库,再启动 web),但无法判断数据库是否 "就绪"(比如 MySQL 容器启动后,还需要初始化数据、加载配置,这期间无法接受连接)。因此需要配合就绪检测脚本使用。
    步骤:
    在 web 服务中添加检测脚本,判断数据库是否可连接。
    通过 depends_on 确保启动顺序,再用脚本阻塞 web 启动,直到数据库就绪。
    示例(以 MySQL 为例):
yaml 复制代码
version: '3'
services:
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=testdb
    ports:
      - "3306:3306"

  web:
    build: ./web  # 假设 web 服务的 Dockerfile 在 ./web 目录
    depends_on:
      - db  # 确保 db 先启动
    command: ["./wait-for-db.sh", "db", "3306", "--", "python", "app.py"]
    # 含义:先执行 wait-for-db.sh 检测 db:3306 是否就绪,就绪后再执行 python app.py

检测脚本(wait-for-db.sh):

在 web 服务的镜像中添加一个脚本(如 wait-for-db.sh),用于检测 MySQL 端口是否可连接:

bash 复制代码
#!/bin/bash
# 用法:./wait-for-db.sh 主机 端口 [-- 命令]
HOST=$1
PORT=$2
shift 2
CMD=$@

# 循环检测数据库端口,直到可连接
until nc -z $HOST $PORT; do
  echo "等待数据库 $HOST:$PORT 启动中..."
  sleep 2
done

echo "数据库已就绪,启动 web 服务..."
exec $CMD

需确保 web 镜像中安装了 nc(netcat,用于端口检测),可在 Dockerfile 中添加:

dockerfile 复制代码
RUN apt-get update && apt-get install -y netcat  # Debian/Ubuntu 系统
# 或 RUN yum install -y nc  # CentOS 系统
  1. 使用第三方工具(更通用)
    如果不想手动写脚本,可以使用成熟的工具(如 wait-for-it、dockerize),支持检测 TCP 端口、HTTP 接口等。
    示例(使用 wait-for-it):
    在 web 服务的 Dockerfile 中下载 wait-for-it:
dockerfile 复制代码
RUN wget -q https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -O /wait-for-it.sh && \
    chmod +x /wait-for-it.sh

在 docker-compose.yml 中使用:

yaml 复制代码
services:
  web:
    build: ./web
    depends_on:
      - db
    # 检测 db:3306 就绪后,执行启动命令
    command: ["/wait-for-it.sh", "db:3306", "--", "python", "app.py"]
  1. 数据库自带健康检查(配合 depends_on 条件)
    Docker Compose 3.8+ 支持 depends_on 的 condition 条件,可结合数据库的 healthcheck 实现 "等待健康状态"。
    示例:
yaml 复制代码
version: '3.8'  # 注意版本需 3.8+
services:
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 5s  # 每 5 秒检查一次
      timeout: 5s   # 检查超时时间
      retries: 5    # 重试 5 次失败则视为不健康

  web:
    build: ./web
    depends_on:
      db:
        condition: service_healthy  # 等待 db 处于 healthy 状态才启动
    command: python app.py

healthcheck.test 中,mysqladmin ping 用于检测 MySQL 是否就绪(需提供正确的用户名和密码)。

只有当 db 的健康检查通过(service_healthy),web 才会启动。

总结
  • 简单场景:用 depends_on + 端口检测脚本(如 wait-for-it)。
  • 精准场景:结合数据库的 healthcheck + depends_on: service_healthy(需 Compose 3.8+)。

核心目标是等待数据库 "可连接",而非仅等待容器启动,避免 web 服务因连接失败而崩溃。

总结

Docker Compose 作为多容器应用的编排工具,完美解决了复杂服务集群的部署与管理难题。通过一个 docker-compose.yml 文件,我们可以统一定义应用所需的所有服务(如 Web 应用、数据库、缓存等),并通过简单的命令实现一键启动、停止、重建等操作,极大简化了多容器环境的运维成本。

本文从 Docker Compose 的核心作用出发,介绍了其安装方式(Linux 与 Mac 环境)、核心配置(数据卷 volumes、网络 networks、依赖 depends_on 等),并通过 Flask + MySQL 的实战案例,展示了如何通过配置文件协调多服务协作。特别针对 "服务依赖顺序" 这一关键问题,详细说明了如何通过就绪检测脚本第三方工具健康检查机制,确保 Web 服务在数据库完全就绪后再启动,避免因连接失败导致的应用崩溃。

掌握 Docker Compose 的核心价值在于:

  1. 简化配置:用一份 YAML 文件管理所有服务的参数,避免零散的命令行操作;

  2. 服务协同:通过网络和依赖配置,让容器间高效通信且有序启动;

  3. 数据持久化:利用数据卷确保容器重启后数据不丢失,兼顾开发与生产环境需求。

无论是开发环境的快速搭建,还是生产环境的稳定部署,Docker Compose 都是简化多容器管理的利器,帮助开发者聚焦于应用逻辑而非环境配置,真正实现 "一次配置,处处运行"。

参考

相关推荐
再吃一根胡萝卜1 小时前
如何查看本地所有 Podman 镜像
docker
yunyi4 小时前
使用acme.sh来实现自动化申请和续订TLS证书
linux·nginx·docker
包达叔4 小时前
docker国内镜像源
运维·docker·容器
半路程序员6 小时前
Mac安装docker,启动elasticsearch
elasticsearch·docker·容器
-L716 小时前
进入docker中mysql容器的方法
运维·mysql·docker·容器
明月与玄武17 小时前
Docker化性能监控平台搭建:JMeter+InfluxDB+Grafana全攻略
jmeter·docker·grafana
df007df19 小时前
【RAGFlow代码详解-29】Docker 部署
运维·docker·容器
Monly2121 小时前
Docker:部署Java后端
java·docker·容器
zjjuejin21 小时前
Docker实战指南:安装、配置与部署
docker