【docker】--4.Docker Compose

目录

[1.Docker Compose 简介](#1.Docker Compose 简介)

[2.Docker Compose 安装](#2.Docker Compose 安装)

Linux

macOS

[windows PC](#windows PC)

[3.Docker Compose 使用](#3.Docker Compose 使用)

3.1.准备

[3.2.创建 Dockerfile 文件](#3.2.创建 Dockerfile 文件)

[3.3.创建 docker-compose.yml](#3.3.创建 docker-compose.yml)

[3.4.使用 Compose 命令构建应用](#3.4.使用 Compose 命令构建应用)

[4.Docker Compose 指令](#4.Docker Compose 指令)

[4.1.顶级结构(Top-level Keys)](#4.1.顶级结构(Top-level Keys))

[4.2.services 下常用指令详解](#4.2.services 下常用指令详解)

[🔧 1. 镜像与构建](#🔧 1. 镜像与构建)

[🌐 2. 网络与通信](#🌐 2. 网络与通信)

[💾 3. 存储与挂载](#💾 3. 存储与挂载)

[⚙️ 4. 运行控制](#⚙️ 4. 运行控制)

[🌱 5. 环境与安全](#🌱 5. 环境与安全)

[🔗 6. 依赖与编排](#🔗 6. 依赖与编排)

[🚀 7. 部署(Swarm 模式专用)](#🚀 7. 部署(Swarm 模式专用))

[📝 8. 日志与监控](#📝 8. 日志与监控)

[🔐 9. 敏感数据(Secrets)](#🔐 9. 敏感数据(Secrets))


1.Docker Compose 简介

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。

  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。

  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

docker-compose.yml 的配置案例如下(配置参数参考下文):

bash 复制代码
# 这是一个 Docker Compose 的 yaml 配置文件示例

version: '3'  # 定义版本,这里使用的是 3 版本的格式,适用于 Docker Compose

services:  # 定义服务集合

  web:  # 定义名为 web 的服务
    build: .  # 指定构建上下文为当前目录下的 Dockerfile
    ports:  # 映射端口,将主机的 5000 端口映射到容器的 5000 端口
    - "5000:5000"
    volumes:  # 挂载卷,使主机上的目录与容器内的目录同步
    - .:/code  # 将当前目录挂载到容器的 /code 路径下
    - logvolume01:/var/log  # 挂载一个名为 logvolume01 的数据卷到容器的 /var/log 目录
    links:  # 链接到另一个服务(redis),便于服务间通信
    - redis  # 表示 web 服务将会链接到 redis 服务

  redis:  # 定义名为 redis 的服务
    image: redis  # 使用 Docker Hub 上官方的 redis 镜像

volumes:  # 定义在顶层的数据卷,可以在多个服务之间共享或重用
  logvolume01: {}  # 声明一个名为 logvolume01 的数据卷,{} 表示使用默认设置

2.Docker Compose 安装

Linux

Linux 上我们可以从 Github 上下载它的二进制包来使用,最新发行的版本地址:https://github.com/docker/compose/releases

运行以下命令以下载 Docker Compose 的当前稳定版本:

bash 复制代码
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

要安装其他版本的 Compose,请替换 1.24.1。

将可执行权限应用于二进制文件:

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

创建软链:

复制代码
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 

测试是否安装成功:

bash 复制代码
$ docker-compose --version
cker-compose version 1.24.1, build 4667896b 

注意: 对于 alpine,需要以下依赖包: py-pip,python-dev,libffi-dev,openssl-dev,gcc,libc-dev,和 make。

macOS

Mac 的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此 Mac 用户不需要单独安装 Compose。Docker 安装说明可以参阅 MacOS Docker 安装

windows PC

Windows 的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此 Windows 用户不需要单独安装 Compose。Docker 安装说明可以参阅Windows Docker 安装

3.Docker Compose 使用

3.1.准备

bash 复制代码
$ mkdir composetest
$ cd composetest 

在测试目录中创建一个名为 app.py 的文件,并复制粘贴以下内容:

composetest/app.py 文件代码

python 复制代码
# 导入所需模块
import time          # 用于实现重试时的延时
import redis         # 用于连接和操作 Redis 缓存数据库
from flask import Flask  # Flask Web 框架

# 创建 Flask 应用实例
app = Flask(__name__)

# 连接到 Redis 服务器(假设 Redis 容器名为 'redis',端口为默认 6379)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    """尝试从 Redis 中获取并递增访问计数,最多重试 5 次"""
    retries = 5  # 最大重试次数

    while True:
        try:
            # 使用 Redis 的 incr 命令对 'hits' 键进行原子自增,并返回当前值
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            # 如果连接失败且重试次数已用完,则抛出异常
            if retries == 0:
                raise exc
            # 否则减少重试次数,等待 0.5 秒后重试
            retries -= 1
            time.sleep(0.5)

# 定义根路径的路由
@app.route('/')
def hello():
    """处理首页请求,返回包含访问次数的欢迎信息"""
    count = get_hit_count()  # 获取当前访问次数
    return 'Hello World! I have been seen {} times.\n'.format(count)

在此示例中,redis 是应用程序网络上的 redis 容器的主机名,该主机使用的端口为 6379。

在 composetest 目录中创建另一个名为 requirements.txt 的文件,内容如下:

python 复制代码
flask
redis 

3.2.创建 Dockerfile 文件

在 composetest 目录中,创建一个名为的文件 Dockerfile,内容如下:

python 复制代码
# 使用轻量级的 Python 3.7 Alpine 镜像作为基础
FROM python:3.7-alpine

# 设置工作目录为 /code
WORKDIR /code

# 设置环境变量:指定 Flask 入口文件
ENV FLASK_APP app.py
# 设置环境变量:允许容器外部访问(0.0.0.0 代表所有网络接口)
ENV FLASK_RUN_HOST 0.0.0.0

# 安装系统级依赖(编译器和头文件),用于编译 Python 包中的 C 代码;--no-cache 避免缓存占用空间
RUN apk add --no-cache gcc musl-dev linux-headers

# 将本地的 requirements.txt 复制到容器中(利用 Docker 缓存机制:只有当文件变化时才重新安装依赖)
COPY requirements.txt requirements.txt

# 安装 Python 依赖包
RUN pip install -r requirements.txt

# 将当前目录下的所有文件复制到容器的 /code 目录
COPY . .

# 容器启动时运行的命令:使用 Flask 自带的开发服务器
CMD ["flask", "run"]

3.3.创建 docker-compose.yml

在测试目录中创建一个名为 docker-compose.yml 的文件,然后粘贴以下内容:

python 复制代码
# yaml 配置

version: '3'

services:

  web:

    build: .

    ports:

      - "5000:5000"

  redis:

    image: "redis:alpine"

该 Compose 文件定义了两个服务:web 和 redis。

  • web:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。
  • redis:该 redis 服务使用 Docker Hub 的公共 Redis 映像。

3.4.使用 Compose 命令构建应用

在测试目录中,执行以下命令来启动应用程序:

复制代码
docker-compose up 

如果你想在后台执行该服务可以加上 -d 参数:

复制代码
docker-compose up -d 

4.Docker Compose 指令

顶级命令:

python 复制代码
services:     # 必填:定义所有服务(容器)
volumes:      # 可选:声明命名卷(named volumes)
networks:     # 可选:声明自定义网络

4.1.version

指定本 yml 依从的 compose 哪个版本制定的。

⚠️ 注意:从 Docker Compose v2.0+ 开始,version 字段已被弃用(你之前看到的警告就是这个原因),可安全删除。

4.2.services

指令是整个 Compose 配置的核心部分,用于定义应用所依赖的各个服务容器(如 Web 应用、数据库、缓存等)。每个服务对应一个 Docker 容器。也就是依赖镜像

4.1.顶级结构(Top-level Keys)

指令 必填 说明
services ✅ 是 定义所有服务(每个服务对应一个容器)
volumes 声明命名卷(named volumes)
networks 声明自定义网络
secrets 声明敏感数据(v3.1+)
configs 声明配置文件(Swarm 模式)

4.2.services 下常用指令详解

🔧 1. 镜像与构建

指令 类型 示例 说明
image string image: redis:alpine 使用现有镜像(可带 tag 或 digest)
build string / object build: ./dir build:   context: ./app   dockerfile: Dockerfile.prod   args: { buildno: 1 }   target: prod   labels: ["key=value"] 构建上下文 - context: 构建目录 - dockerfile: 指定 Dockerfile 名 - args: 构建参数(仅构建时可用) - target: 多阶段构建目标 - labels: 给镜像打标签

imagebuild 通常二选一。


🌐 2. 网络与通信

指令 示例 说明
ports - "8080:80" - "5000" 映射宿主机 ↔ 容器端口(格式:[host:]container[/protocol]
expose expose: [6379] 仅暴露端口给其他服务(不映射到宿主机)
networks networks: [frontend, backend] 加入指定网络(需在顶层定义) 支持别名: some-net: { aliases: [web1, app] }
extra_hosts - "host1:192.168.1.10" 添加 /etc/hosts 条目(类似 --add-host
dns dns: 8.8.8.8 dns: [8.8.8.8, 1.1.1.1] 自定义 DNS 服务器
dns_search dns_search: example.com 自定义 DNS 搜索域
network_mode network_mode: host network_mode: none network_mode: service:db 覆盖默认网络模式(慎用)

💾 3. 存储与挂载

指令 示例 说明
volumes - ./data:/var/lib/redis(绑定挂载) - db_vol:/var/lib/mysql(命名卷) 挂载主机目录或命名卷
tmpfs tmpfs: /tmp tmpfs: [/run, /tmp] 挂载临时内存文件系统
devices - "/dev/ttyUSB0:/dev/ttyUSB0" 映射设备到容器
bash 复制代码
volumes:
  - backend_picture_data:/app/app/data/picture
  - backend_seg_results:/app/segmentation_results
  - ./models:/models:ro

backend_seg_results:/app/segmentation_results

  • 同理,这是将容器内的 /app/segmentation_results 目录(可能存放 SAM 模型生成的分割结果)挂载到另一个命名卷 backend_seg_results

  • 数据同样会被持久化,重启服务不会丢失。


./models:/models:ro

  • 左边./models 是相对于 当前 docker-compose.yml 文件所在目录 的一个宿主机路径 (即项目中的 models/ 文件夹)。

  • 右边/models 是容器内的目标路径。

  • :ro 表示 read-only(只读),容器可以读取该目录下的文件,但不能修改或写入。

  • 作用 :将宿主机上的模型文件(如 sam_vit_l_0b3195.pth只读地共享给容器使用。这样你可以在宿主机上管理模型文件(下载、替换等),而容器始终使用最新版本,且无法意外修改模型。

左侧形式 类型 是否持久化 谁管理
./xxx/xxx~/xxx Bind Mount(绑定挂载) 是(存在你指定的位置) 你(用户)
xxx(纯名字,无 / Named Volume(命名卷) 是(存在 Docker 管理区) Docker

⚙️ 4. 运行控制

指令 示例 说明
command command: ["python", "app.py"] 覆盖容器启动命令
entrypoint entrypoint: /code/init.sh 覆盖入口点(ENTRYPOINT)
container_name container_name: my-web 指定容器名称(默认为 <project>_<service>_<index>
restart restart: unless-stopped 重启策略: no(默认) always on-failure unless-stopped
stop_signal stop_signal: SIGUSR1 自定义停止信号(默认 SIGTERM
stop_grace_period stop_grace_period: 30s 发送 SIGKILL 前等待时间(默认 10s)
healthcheck healthcheck: &nbsp;&nbsp;test: ["CMD", "curl", "-f", "http://localhost"] &nbsp;&nbsp;interval: 30s &nbsp;&nbsp;timeout: 10s &nbsp;&nbsp;retries: 3 &nbsp;&nbsp;start_period: 40s 健康检查配置

🌱 5. 环境与安全

指令 示例 说明
environment environment: &nbsp;&nbsp;RACK_ENV: development &nbsp;&nbsp;SHOW: 'true' 设置环境变量(布尔值需加引号)
env_file env_file: .env env_file: [common.env, web.env] 从文件加载环境变量
cap_add / cap_drop cap_add: [ALL] cap_drop: [SYS_PTRACE] 添加/删除 Linux 内核能力
security_opt security_opt: [label:type:unconfined_t] 修改 SELinux/AppArmor 标签
sysctls sysctls: { net.core.somaxconn: 1024 } 设置内核参数
ulimits ulimits: &nbsp;&nbsp;nofile: { soft: 20000, hard: 40000 } &nbsp;&nbsp;nproc: 65535 覆盖资源限制
cgroup_parent cgroup_parent: m-executor-abcd 指定父 cgroup(继承资源限制)

🔗 6. 依赖与编排

指令 示例 说明
depends_on depends_on: [db, redis] 控制启动/停止顺序 ⚠️ 不等待服务就绪,仅控制容器创建顺序

✅ 若需"等待服务可用",请在应用中实现重试逻辑,或使用 wait-for-it.shdockerize 等工具。


🚀 7. 部署(Swarm 模式专用)

仅在 docker stack deploy 时生效,docker-compose up 会忽略

表格

指令 示例 说明
deploy deploy: &nbsp;&nbsp;mode: replicated &nbsp;&nbsp;replicas: 3 &nbsp;&nbsp;resources: &nbsp;&nbsp;&nbsp;&nbsp;limits: { cpus: '0.5', memory: 50M } &nbsp;&nbsp;restart_policy: { condition: on-failure, delay: 5s } &nbsp;&nbsp;update_config: { parallelism: 2, delay: 10s } 集群部署配置 - mode: replicated / global - replicas: 副本数 - resources: 资源限制 - restart_policy: 重启策略 - update_config: 滚动更新策略 - rollback_config: 回滚策略

📝 8. 日志与监控

指令 示例 说明
logging logging: &nbsp;&nbsp;driver: json-file &nbsp;&nbsp;options: &nbsp;&nbsp;&nbsp;&nbsp;max-size: "200k" &nbsp;&nbsp;&nbsp;&nbsp;max-file: "10" 日志驱动配置 支持 json-file, syslog, none 可限制日志大小和数量

🔐 9. 敏感数据(Secrets)

指令 示例 说明
secrets secrets: [my_secret] (顶层) secrets: &nbsp;&nbsp;my_secret: { file: ./secret.txt } 安全传递密码、密钥等 容器内路径:/run/secrets/<name>

5.docker问题

5.1.更新了容器代码之后如何重构镜像

1. 确认容器名称或 ID

你已经知道容器名是 deploy-backend-1(从你的命令看出)。

2. 提交容器为新镜像
复制代码
docker commit deploy-backend-1 my-backend:updated
  • deploy-backend-1:当前容器名
  • my-backend:updated:新镜像名和标签(可自定义,如 backend:v2

✅ 这会把容器当前的整个文件系统状态 (包括你 cp 进去的 GWO20250630m.py、修改的 db.py 等)打包成一个新镜像。

3. 让 docker-compose 使用这个新镜像

修改你的 docker-compose.yml不再从源码构建,而是直接使用新镜像:

复制代码
1backend:
2  # 注释掉 build 部分
3  # build:
4  #   context: ../backend
5  #   dockerfile: Dockerfile
6
7  # 改为 image
8  image: my-backend:updated
9  restart: unless-stopped
10  # ... 其他配置保持不变
4. 重新创建服务
复制代码
1docker-compose up -d backend

现在,即使你删除旧容器,新启动的容器也会包含你的修改。

5.2.我现在在本地构建好了我的项目镜像,上传到服务器上面部署,并且服务器上面有我的全部项目代码(服务器构建镜像过程中拉去前后端包失败,无法访问包的网络),那我可以通过修改服务器代码直接重构我的镜像吗

我的意思是修改服务器上的代码之后,可不可以直接使用已有的镜像为基础重构代码,这样就不用重新安装环境了

✅ 推荐方案:基于已有镜像 + 本地代码,构建新镜像(无需联网)

你不需要重新安装环境,因为基础镜像已经包含了所有依赖。你只需要:

  1. 写一个简单的 Dockerfile
  2. 把服务器上的新代码 COPY 进去
  3. 构建新镜像 ------ 全程不联网!

🔧 具体操作步骤(在服务器上执行)

1. 确保服务器上有最新代码

假设你的后端代码在:

复制代码
1/home/user/project/backend/
2. 创建一个轻量级 Dockerfile.update
复制代码
# 使用你已有的、包含完整环境的镜像作为基础
FROM my-backend:latest   # ← 替换成你实际的镜像名

# 删除旧代码(可选,如果路径会冲突)
RUN rm -rf /app/app/*

# 复制服务器上的新代码进去
COPY ./backend/ /app/app/

# 设置工作目录(根据你原来的配置)
WORKDIR /app/app

# 如果需要,可以指定启动命令(通常继承自原镜像,可省略)
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

💡 这个 Dockerfile 只做一件事:用新代码覆盖旧代码,其他一切(Python、torch、系统库)都复用原镜像。

3. 构建新镜像(不联网!)
复制代码
cd /home/user/project

# 构建时指定新 Dockerfile
docker build \
  -t my-backend:updated \
  -f Dockerfile.update \
  .

✅ 因为所有依赖已在 my-backend:latest 中,这一步不会下载任何包,秒级完成!

4. 更新 docker-compose.yml(如果需要)

如果你的 docker-compose.yml 原来是用 build,现在可以改为用新镜像:

复制代码
backend:
  image: my-backend:updated   # ← 使用新镜像
  # 注释掉 build 部分(避免服务器尝试重新构建完整环境)
  # build: ...
  restart: unless-stopped
  # ... 其他配置不变
5. 重启服务
复制代码
docker-compose up -d backend
相关推荐
Scabbards_2 小时前
基于docker的LLM服务部署
运维·docker·容器
于眠牧北2 小时前
ubuntu22.04在docker中安装redis6.2.x并配置远程连接
运维·redis·docker·容器
隔壁小邓2 小时前
docker从入门到实践的全面教程
docker·容器·eureka
@PHARAOH3 小时前
HOW - 本地基于 docker 快速构建 mysql 数据库
数据库·mysql·docker
叁金Coder3 小时前
【Centos8 环境下 X86 版本 docker-29.1.3 的安装配置】
运维·docker·容器
SuniaWang3 小时前
Docker Compose 容器管理与自动化部署进阶指南
docker·容器·自动化
kaixin_啊啊4 小时前
(1)如何使用Docker部署IT-Tools并结合内网穿透实现公网访问本地工具箱服务
docker·容器·eureka
陈皮糖..4 小时前
Docker Compose 学习之多容器应用编排与运维实践 —— 基于 Nginx+MySQL+Redis 服务栈的部署与管理
运维·redis·学习·mysql·nginx·docker