目录
[1.Docker Compose 简介](#1.Docker Compose 简介)
[2.Docker Compose 安装](#2.Docker Compose 安装)
[windows PC](#windows PC)
[3.Docker Compose 使用](#3.Docker Compose 使用)
[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: 给镜像打标签 |
✅
image与build通常二选一。
🌐 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: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s |
健康检查配置 |
🌱 5. 环境与安全
| 指令 | 示例 | 说明 |
|---|---|---|
environment |
environment: RACK_ENV: development 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: nofile: { soft: 20000, hard: 40000 } nproc: 65535 |
覆盖资源限制 |
cgroup_parent |
cgroup_parent: m-executor-abcd |
指定父 cgroup(继承资源限制) |
🔗 6. 依赖与编排
| 指令 | 示例 | 说明 |
|---|---|---|
depends_on |
depends_on: [db, redis] |
控制启动/停止顺序 ⚠️ 不等待服务就绪,仅控制容器创建顺序 |
✅ 若需"等待服务可用",请在应用中实现重试逻辑,或使用
wait-for-it.sh、dockerize等工具。
🚀 7. 部署(Swarm 模式专用)
仅在
docker stack deploy时生效,docker-compose up会忽略
表格
| 指令 | 示例 | 说明 |
|---|---|---|
deploy |
deploy: mode: replicated replicas: 3 resources: limits: { cpus: '0.5', memory: 50M } restart_policy: { condition: on-failure, delay: 5s } update_config: { parallelism: 2, delay: 10s } |
集群部署配置 - mode: replicated / global - replicas: 副本数 - resources: 资源限制 - restart_policy: 重启策略 - update_config: 滚动更新策略 - rollback_config: 回滚策略 |
📝 8. 日志与监控
| 指令 | 示例 | 说明 |
|---|---|---|
logging |
logging: driver: json-file options: max-size: "200k" max-file: "10" |
日志驱动配置 支持 json-file, syslog, none 可限制日志大小和数量 |
🔐 9. 敏感数据(Secrets)
| 指令 | 示例 | 说明 |
|---|---|---|
secrets |
secrets: [my_secret] (顶层) secrets: 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.我现在在本地构建好了我的项目镜像,上传到服务器上面部署,并且服务器上面有我的全部项目代码(服务器构建镜像过程中拉去前后端包失败,无法访问包的网络),那我可以通过修改服务器代码直接重构我的镜像吗
我的意思是修改服务器上的代码之后,可不可以直接使用已有的镜像为基础重构代码,这样就不用重新安装环境了
✅ 推荐方案:基于已有镜像 + 本地代码,构建新镜像(无需联网)
你不需要重新安装环境,因为基础镜像已经包含了所有依赖。你只需要:
- 写一个简单的
Dockerfile - 把服务器上的新代码 COPY 进去
- 构建新镜像 ------ 全程不联网!
🔧 具体操作步骤(在服务器上执行)
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