Docker Compose 命令速查表:从入门到实战(附场景示例)
Docker Compose 是管理多容器应用的利器,但命令较多易混淆。本文先带你深入了解 Docker Compose 是什么、能解决什么问题,再对比其与同类工具的优劣,最后整理高频使用的 Compose 命令,按场景分类并附实战示例,帮你快速上手~
一、初识 Docker Compose:多容器应用的“管家”
1. 什么是 Docker Compose?
Docker Compose 是 Docker 官方推出的一款用于定义和运行多容器 Docker 应用的工具。它允许你通过一个 YAML 文件(docker-compose.yml)来配置应用所需的所有服务,然后使用单一命令即可创建并启动所有服务,无需逐个操作每个容器。
简单来说,如果你需要同时运行数据库、缓存、后端服务、前端服务等多个容器来组成一个完整的应用,Docker Compose 可以帮你统一管理这些容器的启动顺序、网络连接、数据挂载等依赖关系,大幅简化多容器应用的部署和维护流程。
2. Docker Compose 的核心价值
-
简化配置:用一个 YAML 文件集中管理所有服务配置,替代多个分散的 docker run 命令,易读易维护。
-
一键启停:通过单一命令(docker compose up/down)即可启动或停止整个应用集群,无需逐个操作容器。
-
环境一致性:确保开发、测试、生产环境的配置一致,避免“开发环境能跑,生产环境报错”的问题。
-
服务依赖管理:自动处理服务间的启动顺序(如先启动数据库,再启动依赖数据库的应用),无需手动控制。
-
隔离性:为每个应用集群创建独立的网络和数据卷,避免不同应用间的资源冲突。
二、Docker Compose 与同类工具对比
在多容器管理领域,除了 Docker Compose,还有 Kubernetes(K8s)、Docker Swarm 等主流工具。不同工具的定位、优势和适用场景各有差异,下面通过表格清晰对比:
| 工具 | 定位 | 核心优势 | 劣势 | 适用场景 |
|---|---|---|---|---|
| Docker Compose | 单机多容器应用编排工具 | 1. 配置简单,学习成本低;2. 命令简洁,一键操作;3. 与 Docker 生态无缝集成;4. 适合快速验证和开发环境 | 1. 仅支持单机部署,不支持集群扩展;2. 缺乏高级运维功能(如自动扩缩容、滚动更新);3. 生产环境稳定性和可靠性较弱 | 1. 开发/测试环境;2. 小型单机应用部署;3. 快速原型验证;4. 本地多容器应用调试 |
| Kubernetes(K8s) | 企业级容器编排平台(支持集群) | 1. 强大的集群管理和扩展能力;2. 支持自动扩缩容、滚动更新、自愈能力;3. 丰富的生态系统和插件;4. 适合大规模生产环境 | 1. 配置复杂,学习成本高;2. 部署和维护门槛高;3. 轻量级应用使用成本过高 | 1. 大规模生产环境;2. 分布式应用部署;3. 需要高可用性、高扩展性的业务;4. 企业级复杂应用 |
| Docker Swarm | Docker 官方集群编排工具(与 Docker 引擎集成) | 1. 与 Docker 原生集成,学习成本较低;2. 配置相对简单,兼容 Docker Compose 语法;3. 适合已有 Docker 生态的团队 | 1. 功能相对简单,高级特性不足;2. 生态不如 K8s 丰富;3. 社区活跃度和更新频率较低 | 1. 中小型集群部署;2. 对 Docker 生态依赖较高的团队;3. 不需要复杂高级功能的集群场景 |
总结:如何选择合适的工具?
-
如果是 开发/测试环境 或 小型单机应用,优先选 Docker Compose,高效便捷;
-
如果是 大规模生产环境 或 分布式应用,需要高可用、高扩展,选 Kubernetes;
-
如果已有 Docker 生态,且需要简单的集群能力,可考虑 Docker Swarm,但目前社区活跃度下降,长期建议向 K8s 迁移。
三、基础启停:服务的“开关”操作
这是日常使用频率最高的命令,覆盖服务的启动、停止、重启等核心操作。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose up -d | 后台启动所有服务 | 启动当前目录下 docker-compose.yml 定义的所有服务:docker compose up -d |
docker compose up -d [服务名] | 仅启动指定服务 | 只启动 elasticsearch 服务(不启动其他依赖):docker compose up -d elasticsearch |
docker compose stop | 停止所有运行中的服务(保留容器) | 暂停所有服务但不删除容器:docker compose stop |
docker compose stop [服务名] | 停止指定服务 | 单独停止 kibana 服务:docker compose stop kibana |
docker compose restart [服务名] | 重启指定服务 | 重启 postgres 数据库服务:docker compose restart postgres |
docker compose down | 停止并删除容器/网络(保留镜像/数据卷) | 清理当前服务的容器和网络:docker compose down |
docker compose down -v | 停止并删除容器/网络/数据卷 | 彻底清理(含数据卷,谨慎使用):docker compose down -v |
四、状态与日志:排查问题的“眼睛”
服务运行异常时,这些命令能帮你快速定位问题。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose ps | 查看运行中的服务状态 | 查看当前活跃的服务列表:docker compose ps |
docker compose ps -a | 查看所有服务(含已停止) | 查看所有服务的生命周期状态:docker compose ps -a |
docker compose logs -f | 实时跟踪所有服务日志 | 实时监控所有服务的输出:docker compose logs -f |
docker compose logs -f [服务名] | 实时跟踪指定服务日志 | 单独查看 elasticsearch 的日志(排查启动失败):docker compose logs -f elasticsearch |
docker compose top | 查看服务的进程与资源占用 | 查看各服务的 CPU/内存消耗:docker compose top |
五、容器内部:深入服务的“操作间”
需要进入容器执行命令(比如调试、修改配置)时,用这些命令。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose exec [服务名] bash | 进入容器终端(适用于带 bash 的镜像) | 进入 redis 容器执行命令:docker compose exec redis bash |
docker compose exec [服务名] sh | 进入轻量级容器(如 alpine 镜像) | 进入基于 alpine 的 redis 容器:docker compose exec redis sh |
docker compose exec -u root [服务名] bash | 以 root 身份进入容器(解决权限问题) | 权限不足时进入 elasticsearch 容器:docker compose exec -u root elasticsearch bash |
六、镜像与构建:自定义服务的“基石”
如果服务使用自定义 Dockerfile,这些命令用于构建和更新镜像。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose build | 构建 docker-compose.yml 中定义的所有镜像 | 构建项目中所有自定义镜像:docker compose build |
docker compose build --no-cache [服务名] | 强制重建指定服务镜像(忽略缓存) | 重新构建 app 服务镜像(更新依赖时用):docker compose build --no-cache app |
docker compose pull [服务名] | 拉取指定服务的最新镜像 | 拉取 kibana 的官方最新镜像:docker compose pull kibana |
七、配置与调试:验证服务的“工具包”
用于检查配置、查看端口映射等调试场景。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose config | 验证并格式化输出 docker-compose.yml 配置 | 检查配置文件是否有语法错误:docker compose config |
docker compose images | 查看服务关联的镜像列表 | 列出当前项目使用的所有镜像:docker compose images |
docker compose port [服务名] [容器端口] | 查看服务的端口映射关系 | 查看 postgres 容器 5432 端口对应的宿主机端口:docker compose port postgres 5432 |
八、进阶操作:应对复杂场景
处理特殊需求(比如强制重建、暂停服务)时的命令。
| 命令 | 作用 | 实战示例 |
|---|---|---|
docker compose up -d --force-recreate [服务名] | 强制重建并启动指定服务 | 重建 elasticsearch 服务(解决配置不生效问题):docker compose up -d --force-recreate elasticsearch |
docker compose pause [服务名] | 暂停指定服务 | 临时暂停 redis 服务:docker compose pause redis |
docker compose unpause [服务名] | 恢复暂停的服务 | 恢复 redis 服务的运行:docker compose unpause redis |
九、简单应用示例:用Docker Compose部署Web+数据库应用
下面通过一个“NginxWeb服务+MySQL数据库”的简单场景,完整演示Docker Compose的使用流程,包括YAML配置编写、服务启停、日志查看等核心操作。
1. 场景说明
部署两个服务:① Nginx服务(提供Web页面访问);② MySQL服务(数据存储),两个服务通过Docker Compose管理网络连接,确保彼此可通信。
2. 新增.env环境变量文件(优化配置安全性)
在实际开发中,数据库密码、密钥等敏感信息不建议直接写在docker-compose.yml中。我们可以通过.env文件存储这些变量,再在YAML中引用,提升配置安全性和可维护性。
在项目目录下创建.env文件,内容如下(存储MySQL相关敏感配置):
# .env 文件:存储环境变量(key=value格式,无需引号)
# MySQL root用户密码
MYSQL_ROOT_PWD=123456
# 初始数据库名称
MYSQL_INIT_DB=test_db
# 自定义用户名
MYSQL_USER=test_user
# 自定义用户密码
MYSQL_USER_PWD=test_pass
# 容器端口(可选,统一管理端口配置)
MYSQL_PORT=3306
NGINX_PORT=80
3. 编写docker-compose.yml配置文件(引用.env变量)
修改docker-compose.yml,通过${变量名}引用.env文件中的配置,内容如下(注释说明引用逻辑):
# 版本声明(Docker Compose V2+可省略,此处为兼容旧版本保留)
version: '3.8'
# 定义所有服务
services:
# 1. Nginx服务,服务名:nginx-web
nginx-web:
# 使用官方Nginx镜像(指定具体版本,避免使用latest导致版本不可控)
image: nginx:1.25.4-alpine
# 容器名(可选,默认是“项目名_服务名_1”)
container_name: my-nginx
# 端口映射:引用.env中的NGINX_PORT变量(宿主机端口 → 容器80端口)
ports:
- "${NGINX_PORT}:80"
# 数据挂载:将宿主机的./nginx/html目录挂载到容器的/usr/share/nginx/html(用于放置自定义Web页面)
volumes:
- ./nginx/html:/usr/share/nginx/html
- ./nginx/conf.d:/etc/nginx/conf.d # 挂载自定义配置,便于维护
# 依赖关系:先启动mysql服务再启动当前服务(仅保证启动顺序,不等待服务就绪)
depends_on:
mysql-db:
condition: service_healthy # 等待mysql服务健康检查通过后再启动
# 网络配置:加入自定义网络my-app-network
networks:
- my-app-network
# 重启策略:容器退出时自动重启(最佳实践:生产环境建议设置为unless-stopped)
restart: unless-stopped
# 健康检查:验证Nginx服务是否正常可用
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost"]
interval: 10s # 检查间隔
timeout: 5s # 检查超时时间
retries: 3 # 失败重试次数
start_period: 30s # 容器启动后等待多久开始健康检查
# 2. MySQL服务,服务名:mysql-db
mysql-db:
# 使用官方MySQL 8.0镜像(指定具体版本,避免版本漂移)
image: mysql:8.0.36
container_name: my-mysql
# 端口映射:引用.env中的MYSQL_PORT变量(宿主机端口 → 容器3306端口)
ports:
- "${MYSQL_PORT}:3306"
# 环境变量:引用.env中的MySQL相关变量(替代直接写死的敏感信息)
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PWD} # 引用.env中的root密码
MYSQL_DATABASE: ${MYSQL_INIT_DB} # 引用.env中的初始数据库名
MYSQL_USER: ${MYSQL_USER} # 引用.env中的自定义用户
MYSQL_PASSWORD: ${MYSQL_USER_PWD} # 引用.env中的自定义用户密码
MYSQL_INITDB_SKIP_TZINFO: "1" # 跳过时区设置,避免启动报错
# 数据挂载:将宿主机的./mysql/data目录挂载到容器的/var/lib/mysql(持久化MySQL数据)
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/init-scripts:/docker-entrypoint-initdb.d # 挂载初始化脚本,启动时自动执行
# 网络配置:加入自定义网络my-app-network
networks:
- my-app-network
# 额外配置:解决MySQL 8.0默认认证插件问题(兼容旧客户端)
command: --default-authentication-plugin=mysql_native_password
# 重启策略:生产环境建议设置为unless-stopped
restart: unless-stopped
# 健康检查:验证MySQL服务是否正常可用
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u${MYSQL_USER}", "-p${MYSQL_USER_PWD}"]
interval: 15s
timeout: 10s
retries: 3
start_period: 60s # MySQL启动较慢,延长启动等待时间
# 定义自定义网络(隔离当前应用的网络环境,最佳实践:避免使用默认网络)
networks:
my-app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16 # 指定子网,避免网络冲突
# 定义数据卷(最佳实践:使用命名卷,便于管理和备份)
volumes:
mysql-data: # 命名卷,替代宿主机绑定挂载,更适合生产环境
driver: local
4. .env文件核心说明
-
命名规范:文件名必须是
.env(首字符为点,无后缀),默认放在docker-compose.yml同目录下,Compose会自动加载;若放在其他目录,需通过docker compose --env-file 路径/.env up -d指定加载路径。 -
语法规则:变量格式为
KEY=VALUE,等号两侧无空格;注释以#开头,仅支持行注释;无需给字符串值加引号(加引号会被当作值的一部分)。 -
安全建议:.env文件包含敏感信息,务必加入
.gitignore(Git忽略文件),避免提交到代码仓库泄露信息。
在项目目录下创建docker-compose.yml文件,内容如下(注释已详细说明各配置项含义):
# 版本声明(Docker Compose V2+可省略,此处为兼容旧版本保留)
version: '3.8'
# 定义所有服务
services:
# 1. Nginx服务,服务名:nginx-web
nginx-web:
# 使用官方Nginx镜像
image: nginx:latest
# 容器名(可选,默认是“项目名_服务名_1”)
container_name: my-nginx
# 端口映射:宿主机80端口 → 容器80端口
ports:
- "80:80"
# 数据挂载:将宿主机的./nginx/html目录挂载到容器的/usr/share/nginx/html(用于放置自定义Web页面)
volumes:
- ./nginx/html:/usr/share/nginx/html
# 依赖关系:先启动mysql服务再启动当前服务
depends_on:
- mysql-db
# 网络配置:加入自定义网络my-app-network
networks:
- my-app-network
# 2. MySQL服务,服务名:mysql-db
mysql-db:
# 使用官方MySQL 8.0镜像
image: mysql:8.0
container_name: my-mysql
# 端口映射:宿主机3306端口 → 容器3306端口
ports:
- "3306:3306"
# 环境变量:配置MySQLroot密码、初始数据库名
environment:
MYSQL_ROOT_PASSWORD: 123456 # root用户密码
MYSQL_DATABASE: test_db # 启动时自动创建的数据库
MYSQL_USER: test_user # 自定义用户
MYSQL_PASSWORD: test_pass # 自定义用户密码
# 数据挂载:将宿主机的./mysql/data目录挂载到容器的/var/lib/mysql(持久化MySQL数据)
volumes:
- ./mysql/data:/var/lib/mysql
# 网络配置:加入自定义网络my-app-network
networks:
- my-app-network
# 额外配置:解决MySQL 8.0默认认证插件问题(兼容旧客户端)
command: --default-authentication-plugin=mysql_native_password
# 定义自定义网络(隔离当前应用的网络环境)
networks:
my-app-network:
driver: bridge
3. 准备自定义Web页面(可选)
为了验证Nginx服务正常运行,在项目目录下创建自定义Web页面目录并编写简单HTML:
# 1. 创建挂载目录
mkdir -p ./nginx/html
# 2. 编写index.html页面
echo "<h1>Docker Compose 示例应用</h1><p>Nginx + MySQL 服务已正常启动!</p>" > ./nginx/html/index.html
4. 相关命令使用流程
(1)启动所有服务
在docker-compose.yml所在目录执行以下命令,后台启动Nginx和MySQL服务:
docker compose up -d
执行后输出类似如下内容,说明服务启动成功:
Creating network "my-app-my-app-network" with driver "bridge"
Creating my-mysql ... done
Creating my-nginx ... done
(2)查看服务状态
检查两个服务的运行状态,确认是否正常启动:
docker compose ps
正常输出如下(状态为Up表示运行中):
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
my-mysql mysql:8.0 "docker-entrypoint.s…" mysql-db 2 minutes ago Up 2 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp
my-nginx nginx:latest "/docker-entrypoint.…" nginx-web 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp
(3)验证服务可用性
-
验证Nginx服务:打开浏览器访问
http://localhost(或宿主机IP),可看到之前编写的自定义Web页面,说明Nginx服务正常。 -
验证MySQL服务:通过
docker compose exec命令进入MySQL容器,测试数据库连接:
# 进入MySQL容器终端
docker compose exec mysql-db bash
# 登录MySQL(使用配置中的root密码123456)
mysql -u root -p
# 登录成功后,可查看已创建的test_db数据库
show databases;
输出中包含test_db,说明MySQL服务配置生效。
(4)查看服务日志
查看Nginx服务的实时日志(排查Web访问问题):
docker compose logs -f nginx-web
查看MySQL服务的日志(排查数据库启动问题):
docker compose logs -f mysql-db
(5)停止与清理服务
① 临时停止服务(保留容器和数据):
docker compose stop
② 重新启动服务:
docker compose restart
③ 停止并删除容器、网络(保留数据卷,即MySQL数据):
docker compose down
④ 彻底清理(删除容器、网络、数据卷,谨慎使用,会丢失MySQL数据):
docker compose down -v
5. 示例总结
通过以上示例可发现,Docker Compose只需一个YAML文件即可定义多服务依赖关系,配合简单命令就能完成整套应用的启停、调试。核心优势在于:无需手动创建网络、配置端口映射,服务间自动可通过服务名通信(如Nginx服务可通过mysql-db访问MySQL服务),大幅简化了多容器应用的部署流程。
而引入.env环境变量后,进一步优化了配置管理:① 敏感信息与配置文件分离,提升安全性;② 统一管理可配置项(如端口、密码),后续修改无需改动docker-compose.yml,直接修改.env即可;③ 便于多环境适配(开发/测试/生产可使用不同.env文件)。后续结合最佳实践中的健康检查、重启策略、命名卷等配置,可进一步提升应用的稳定性和可维护性。
通过以上示例可发现,Docker Compose只需一个YAML文件即可定义多服务依赖关系,配合简单命令就能完成整套应用的启停、调试。核心优势在于:无需手动创建网络、配置端口映射,服务间自动可通过服务名通信(如Nginx服务可通过mysql-db访问MySQL服务),大幅简化了多容器应用的部署流程。
十、Docker Compose 最佳实践
掌握基础用法后,遵循最佳实践能大幅提升应用的稳定性、安全性和可维护性。以下是生产环境中常用的 Docker Compose 最佳实践总结:
1. 配置文件相关
-
指定镜像具体版本,避免使用 latest:latest 标签会自动拉取最新版本,可能导致不同环境版本不一致(“版本漂移”)。建议指定具体版本,如
nginx:1.25.4-alpine、mysql:8.0.36,确保开发、测试、生产环境镜像版本统一。 -
使用 .env 文件管理敏感信息和可配置项:将数据库密码、密钥、端口等信息放入 .env 文件,避免直接写在 docker-compose.yml 中。同时,务必将 .env 文件加入 .gitignore,防止敏感信息泄露到代码仓库。
-
拆分配置文件,适配多环境:针对开发、测试、生产环境,可创建多个配置文件(如 docker-compose.yml、docker-compose.dev.yml、docker-compose.prod.yml)。基础配置放在 docker-compose.yml,环境特定配置放在对应文件,启动时通过
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d合并加载。 -
使用注释和规范命名:为关键配置添加注释,服务名、容器名、网络名、数据卷名遵循统一命名规范(如 项目名-服务名),提升可读性和可维护性。
2. 服务配置相关
-
设置合理的重启策略:生产环境建议将 restart 设为
unless-stopped(除非手动停止,否则容器退出时自动重启),避免因服务异常退出导致应用中断。避免使用always(即使手动停止也会重启),不利于维护。 -
添加健康检查,确保服务就绪:通过 healthcheck 配置验证服务是否正常提供服务,避免因服务未完全启动(如 MySQL 启动慢)导致依赖服务启动失败。同时,结合
depends_on + condition: service_healthy控制服务启动顺序,确保依赖服务就绪后再启动当前服务。 -
限制资源使用,避免资源争抢:为每个服务设置资源限制,防止单个服务占用过多 CPU、内存,影响其他服务运行。示例:`services:
nginx-web:… 其他配置
deploy:
resources:
limits:
cpus: ‘0.5’ # 限制最大使用 0.5 个 CPU 核心
memory: 512M # 限制最大内存使用 512MB
reservations:
cpus: ‘0.2’ # 预留 0.2 个 CPU 核心
memory: 256M # 预留 256MB 内存` -
使用非 root 用户运行容器:默认情况下,容器内进程以 root 身份运行,存在安全风险。建议在 Dockerfile 中创建普通用户,或在 docker-compose.yml 中通过
user: "1000:1000"指定运行用户(1000 为宿主机普通用户的 UID 和 GID),降低安全风险。
3. 网络与数据卷相关
-
使用自定义网络,避免网络冲突:不使用默认网络,为每个项目创建独立的自定义网络,并指定子网(如 172.20.0.0/16),避免不同项目间网络地址冲突。服务间可通过服务名直接通信,无需暴露端口到宿主机。
-
优先使用命名卷,替代宿主机绑定挂载:命名卷(volumes)由 Docker 统一管理,比宿主机绑定挂载(- ./mysql/data:/var/lib/mysql)更稳定,且便于备份、迁移和跨环境使用。生产环境建议使用命名卷存储关键数据(如数据库数据)。
-
避免不必要的端口暴露:仅暴露应用必需的端口到宿主机,服务间通信通过自定义网络内部实现,无需暴露端口。例如,MySQL 服务仅需供内部 Web 服务访问,无需将 3306 端口暴露到宿主机。
4. 部署与维护相关
-
定期备份数据卷:对于命名卷中的关键数据(如数据库数据),定期通过
docker run --rm -v 数据卷名:/source -v 宿主机备份目录:/dest alpine cp -r /source /dest命令备份数据,防止数据丢失。 -
使用 .dockerignore 文件减少镜像体积:如果服务使用自定义 Dockerfile,创建 .dockerignore 文件排除不必要的文件(如 node_modules、日志文件、编译产物),减少镜像构建时间和体积。
-
避免在容器内存储状态数据:容器应遵循“无状态”原则,状态数据(如用户上传文件、数据库数据)应存储在数据卷中,避免容器删除后数据丢失。
-
定期更新镜像和 Docker 版本:及时更新镜像和 Docker 引擎版本,修复安全漏洞。更新前需在测试环境验证,避免版本更新导致应用兼容性问题。
5. 安全相关
-
限制容器权限:通过
cap_drop: [ALL]丢弃容器不必要的 Linux 能力,仅保留必需的能力(如 NET_BIND_SERVICE),降低容器被攻击后的影响范围。 -
避免使用特权容器:除非特殊需求,否则不使用
privileged: true,特权容器拥有宿主机的所有权限,存在极大安全风险。 -
敏感信息加密存储:对于核心敏感信息(如数据库 root 密码、API 密钥),不建议仅使用 .env 文件存储。生产环境可结合 Docker Secrets(Swarm 模式)、Vault 等工具进行加密管理。
十一、总结:高频命令口诀
-
启停用:
up -d启动、stop暂停、restart重启、down清理; -
排查用:
ps -a看状态、logs -f看日志、exec进容器; -
构建用:
build打包镜像、pull更新镜像; -
注意:
down -v会删除数据卷,务必确认数据无需保留再执行。
&spm=1001.2101.3001.5002&articleId=156080856&d=1&t=3&u=95ae3859815f4598a33d2784f2d0d131)
1万+

被折叠的 条评论
为什么被折叠?



