告别手敲 docker run
N 遍!😫 Docker Compose 保姆级教程,一键编排应用全家桶!✨
标签: Docker Compose, Docker, 容器编排, 微服务, 后端, DevOps, 新手入门, 优快云博客, 小
阅读时长: 约 13 分钟
哈喽各位 优快云 的小伙伴们!👋 上一篇我们一起探索了 Docker 的奇妙世界(还没看的赶紧去补课!),是不是感觉打开了新世界的大门?用 docker run
跑单个容器,比如 Nginx、Redis 什么的,确实方便快捷。
但是!灵魂拷问来了:
- 如果你的应用需要同时跑一个 Web 服务、一个数据库、一个缓存服务呢?难道要手动敲三遍
docker run
,还得自己处理网络连接、依赖关系?想想都头大!🤯 - 每次启动/停止这一整套服务,都要分别操作好几个容器?这效率也太低了吧!😩
- 想把这套复杂的环境分享给团队其他小伙伴?难道是发给他们一长串
docker run
命令和注意事项?很容易出错的好嘛!❌ - 管理这些容器的配置(端口、数据卷、环境变量等)是不是感觉有点散乱?😵💫
盆友们,答应我,不要再这么“手工作坊”了!🙅♀️ 今天的主角——Docker Compose,就是来优雅解决这些问题的!它是 Docker 官方的多容器应用编排工具,让你用一个文件定义和管理一整套应用服务!这篇宝藏教程,绝对诚意满满,带你从零掌握 Docker Compose,轻松驾驭复杂应用!快快收藏起来!🔥
🤔 Docker Compose 是什么神仙搭档?为啥要用它?
还记得我们上一篇说的 Docker 镜像(Image)和容器(Container)吗?Docker Compose 就是帮我们把多个相关的容器(比如你的 Web 应用容器、MySQL 数据库容器、Redis 缓存容器)组合 (Compose) 在一起,作为一个整体的应用单元来管理。
你可以把它想象成一个应用套餐的配置单和启动器。你只需要在一份叫做 docker-compose.yml
的配置文件里,写清楚这个“套餐”里包含哪些“菜品”(服务/容器),每个“菜品”需要什么“配料”(镜像、端口、数据卷、环境变量等),以及它们之间的“上菜顺序”(依赖关系)。
然后,只需要一个简单的命令,Docker Compose 就能根据这份“配置单”,帮你一键启动、停止、重建整个应用所需的所有容器!是不是超级方便?!😎
为什么要用 Docker Compose?(划重点!✨)
- ✅ 一键管理应用全家桶: 只需
docker-compose up
和docker-compose down
两个核心命令,就能启动和停止整个应用的所有服务(容器),告别繁琐的手动操作!省时省力!⏱️ - ✅ 配置集中化,清晰明了: 所有服务的配置(镜像、端口映射、数据卷、环境变量、网络、依赖等)都集中在
docker-compose.yml
这一个文件里,结构清晰,一目了然,维护和修改都超级方便!📝 - ✅ 环境一致性 Pro Max: 只需要分享
docker-compose.yml
文件(可能还有自定义的 Dockerfile),团队成员就能在各自机器上快速拉起一套完全相同的开发/测试环境!真正实现环境的轻松复制和迁移!🌍 - ✅ 自动处理容器网络: Compose 会自动创建一个默认的网络,让定义在同一个
docker-compose.yml
文件里的所有服务(容器)可以方便地互相访问(使用服务名作为 hostname),不用手动配置link
或复杂的网络命令!🌐 - ✅ 非常适合本地开发和测试: 对于需要多个服务协作的应用(比如大多数 Web 应用),Compose 是搭建本地开发环境的不二之选!💯
简单来说,如果 Docker 是解决了单个应用的打包和运行问题,那么 Docker Compose 就解决了管理多个相互关联的应用容器的编排问题。 它是从“能跑起来”到“跑得舒服、跑得高效”的关键一步!
🛠️ Docker Compose 实战:从零编写你的第一个 docker-compose.yml
理论讲完了,是时候上干货了!我们来一步步学习如何使用 Docker Compose,并编写属于你的第一个编排文件!
第一步:安装 Docker Compose
好消息!如果你是通过 Docker Desktop (for Mac/Windows) 安装的 Docker,那么 Docker Compose 通常已经自带了,无需额外安装!🎉
如果你是 Linux 用户,或者没有自带,可以根据官方文档进行安装:Install Docker Compose
安装完成后,打开终端,输入以下命令验证:
# V2 (新版,集成到 docker 命令中)
docker compose version
# V1 (旧版,独立命令)
# docker-compose --version
看到版本号输出就表示 OK 啦!(推荐使用 V2 语法 docker compose ...
)
第二步:理解核心配置文件 docker-compose.yml
这是 Docker Compose 的灵魂!它使用 YAML 格式来定义应用的服务。YAML 是一种简洁、易读的标记语言,特别注意:YAML 对缩进非常敏感! 通常使用 2 个空格进行缩进,层级关系靠缩进来体现。
一个基本的 docker-compose.yml
文件结构如下:
# 版本号 (推荐使用较新的版本,如 '3.8')
version: '3.8'
# 定义服务 (应用包含的各个组件/容器)
services:
# 服务 1: 比如你的 Web 应用
webapp:
# 构建指令: 如果需要基于 Dockerfile 构建镜像
build:
context: ./app # Dockerfile 所在的目录
dockerfile: Dockerfile # Dockerfile 的文件名 (如果就叫 Dockerfile 可省略)
# 或者直接使用镜像
# image: your-custom-image:tag
container_name: my_web_app # 指定容器名 (可选)
ports:
- "5000:5000" # 端口映射 "宿主机端口:容器端口"
volumes:
- ./app:/app # 挂载代码目录 (方便开发时热更新)
- webapp_data:/data # 挂载命名数据卷 (持久化数据)
environment:
- REDIS_HOST=cache # 环境变量,可以直接用服务名连接
- DB_PASSWORD=${DB_PASSWORD} # 可以引用 .env 文件中的变量
depends_on: # 定义依赖关系
- cache
- db
networks: # (可选) 指定网络
- app_network
# 服务 2: 比如 Redis 缓存
cache:
image: redis:alpine # 使用官方 Redis 镜像
container_name: my_redis_cache
volumes:
- redis_data:/data # Redis 数据持久化
networks:
- app_network
# 服务 3: 比如 PostgreSQL 数据库
db:
image: postgres:14-alpine
container_name: my_postgres_db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: ${DB_PASSWORD} # 引用 .env 变量
POSTGRES_DB: mydatabase
volumes:
- postgres_data:/var/lib/postgresql/data # 数据库数据持久化
ports: # (可选) 如果需要从宿主机直接访问数据库
- "5432:5432"
networks:
- app_network
# (可选) 定义顶层的数据卷 (推荐使用命名卷)
volumes:
webapp_data:
redis_data:
postgres_data:
# (可选) 定义网络
networks:
app_network:
driver: bridge # 使用桥接网络
关键配置项解读 (小白必看!✨):
version
: 指定 Compose 文件格式的版本,建议用新版如 ‘3.8’。services
: 核心!在这里定义你的应用包含的每一个服务(对应一个或多个容器)。webapp
,cache
,db
: 这些是你给服务起的名字,非常重要!在同一个 Compose 文件里,这些服务名可以作为 hostname 被其他服务访问(比如webapp
可以通过http://cache:6379
访问 Redis)。image: <image_name>:<tag>
: 指定服务使用的 Docker 镜像,可以来自 Docker Hub 或私有仓库。这是最常用的方式。build
: 如果你的服务需要基于本地的Dockerfile
构建镜像(比如你的 Web 应用),就用build
指令。context
: 指定Dockerfile
所在的目录路径。dockerfile
: 指定Dockerfile
的文件名(如果不是默认的Dockerfile
)。
container_name
: 给这个服务启动的容器指定一个固定的名字(可选,不指定 Compose 会自动生成)。ports
: 定义端口映射,格式是"宿主机端口:容器端口"
(字符串形式)。把容器内部的端口暴露给宿主机或其他外部网络。volumes
: 超级重要! 用于数据持久化和文件共享。- 命名卷 (Named Volumes):
redis_data:/data
。推荐方式!Compose 会自动创建和管理名为redis_data
的卷,并将它挂载到容器的/data
目录。即使容器被删除,卷里的数据依然保留。需要在顶层的volumes:
下声明这个命名卷。 - 绑定挂载 (Bind Mounts):
./app:/app
。将宿主机的./app
目录直接挂载到容器的/app
目录。适合挂载代码,你在宿主机修改代码,容器内立刻就能看到,方便开发调试。注意: 路径需要根据你的项目结构调整。
- 命名卷 (Named Volumes):
environment
: 设置环境变量。可以直接写KEY=VALUE
,也可以引用宿主机环境变量或.env
文件中的变量 (如${DB_PASSWORD}
)。非常适合传递配置信息(如数据库密码、API Keys 等)。depends_on
: 定义服务间的启动依赖关系。比如webapp
depends_on: [cache, db]
表示cache
和db
服务会先于webapp
启动。注意: 这只保证启动顺序,不保证服务内部的应用完全准备好。networks
: (可选)指定服务连接的网络。默认情况下,Compose 会创建一个 default 网络,所有服务都在里面。如果需要更复杂的网络拓扑,可以自定义网络并在顶层networks:
中定义。
volumes
: (顶层)声明在services
中使用的命名卷。networks
: (顶层)声明在services
中使用的自定义网络。
第三步:实战演练 - 跑一个简单的 Web 应用 + Redis 计数器
假设我们有这样一个项目结构:
my_compose_app/
├── docker-compose.yml <-- 我们的主角!
├── app/ <-- 存放 Web 应用代码
│ ├── Dockerfile <-- Web 应用的 Dockerfile
│ └── server.py <-- 一个简单的 Python Flask 应用
└── .env <-- (可选) 存放敏感配置,如密码
-
编写
app/server.py
(一个简单的 Flask 应用,访问一次 Redis 计数器加一):# app/server.py from flask import Flask from redis import Redis import os app = Flask(__name__) # 使用服务名 'cache' 连接 Redis,端口默认 6379 # 从环境变量获取 Redis 主机名,提供默认值 'cache' redis_host = os.environ.get('REDIS_HOST', 'cache') redis = Redis(host=redis_host, port=6379, decode_responses=True) @app.route('/') def hello(): count = redis.incr('hits') return f'Hello from Docker Compose! This page has been viewed {count} times.' if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)
-
编写
app/Dockerfile
(用于构建 Web 应用镜像):# app/Dockerfile # 使用官方 Python 镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 暴露端口 EXPOSE 5000 # 启动命令 CMD [ "python", "./server.py" ]
(需要创建一个简单的
app/requirements.txt
文件,内容为Flask
和redis
) -
编写
docker-compose.yml
(核心文件):# docker-compose.yml version: '3.8' services: # Web 应用服务 webapp: build: ./app # 指定构建上下文为 ./app 目录 container_name: flask_counter_app ports: - "5000:5000" # 映射宿主机 5000 到容器 5000 volumes: - ./app:/app # 挂载代码,方便开发调试 environment: - FLASK_ENV=development - REDIS_HOST=cache # 告诉应用 Redis 服务的主机名是 cache depends_on: - cache # 依赖于 cache 服务 networks: - counter_net # Redis 缓存服务 cache: image: redis:alpine # 使用官方 Redis 镜像 container_name: redis_cache volumes: - redis_data:/data # 数据持久化到命名卷 redis_data networks: - counter_net # 定义命名卷 volumes: redis_data: # 定义网络 networks: counter_net: driver: bridge
第四步:运行!核心 Compose 命令
在 my_compose_app
目录下(也就是 docker-compose.yml
文件所在的目录)打开终端,执行:
# 1. 构建镜像 (如果需要 build) 并启动所有服务 (-d 表示后台运行)
docker compose up -d --build
# 如果镜像已存在或不需要重新构建,可以直接 up
# docker compose up -d
# 2. 查看所有正在运行的服务 (类似 docker ps)
docker compose ps
# 3. 查看某个服务的日志 (-f 表示持续跟踪日志)
docker compose logs -f webapp
# docker compose logs cache
# 4. 停止并移除由 Compose 创建的容器、网络、(默认)卷
docker compose down
# 如果只想停止服务,但不移除
# docker compose stop
# 如果想重新启动已停止的服务
# docker compose start
# 强制重新构建服务的镜像
# docker compose build webapp
现在,执行 docker compose up -d --build
后,等待片刻。然后访问 http://localhost:5000
,你应该能看到 “Hello from Docker Compose! …” 的消息,每次刷新页面,计数器都会增加!🎉
当你不再需要这个应用时,执行 docker compose down
,所有相关的容器和网络都会被清理干净,非常方便!
✨ 为什么要这样配置和使用?
docker-compose.yml
的意义: 它将原本需要多个docker run
命令以及手动配置网络、卷的操作,声明式地定义在一个文件里。这使得应用的结构一目了然,配置可版本化(可以和代码一起提交到 Git),部署和分享变得极其简单。- 服务名即主机名: Compose 自动处理网络,让
webapp
可以直接通过服务名cache
访问 Redis,无需关心 IP 地址,解耦了服务间的依赖。 - 数据持久化 (
volumes
): 使用命名卷 (redis_data
) 保证了即使 Redis 容器被删除重建,计数器的值(存储在 Redis 数据里)也不会丢失。这对于数据库等需要持久化数据的服务至关重要! - 代码热更新 (
bind mounts
): 通过./app:/app
挂载,你在本地修改server.py
后,通常只需重启 Flask 进程(或者有些框架支持热加载)就能看到效果,无需重新构建镜像和重启容器,大大提高了开发效率。 - 依赖管理 (
depends_on
): 确保了数据库或缓存服务在你的应用启动之前就已经启动,避免了应用启动时连接失败的问题。
📝 总结 & 进阶小 Tips
恭喜你!已经掌握了 Docker Compose 的基本使用方法!回顾一下:
- Docker Compose 是什么: 多容器应用编排工具,用 YAML 文件定义和管理应用服务。
- 为什么用它: 简化多容器管理、配置集中化、环境一致性、自动网络处理。
- 怎么用它:
- 编写
docker-compose.yml
文件,定义services
,ports
,volumes
,environment
,depends_on
等。 - 使用核心命令
docker compose up -d
启动,docker compose down
关闭清理,docker compose ps
查看状态,docker compose logs
查看日志。
- 编写
给萌新们的贴心 Tips:
- YAML 缩进是魔鬼! 一定要注意对齐,否则会报错。推荐使用支持 YAML 语法高亮的编辑器(如 VS Code)。
- 从简单开始: 先尝试编排两个简单的服务,比如 Nginx + 一个静态网页容器。
- 理解数据卷! 区分命名卷和绑定挂载的应用场景,确保数据持久化。
- 善用
.env
文件: 把密码、API Key 等敏感信息放在.env
文件中(记得把它加入.gitignore
),然后在docker-compose.yml
里通过${VARIABLE_NAME}
引用,更安全。 - 阅读官方文档: Compose 的配置项非常丰富,遇到不确定的地方,查阅 Docker Compose官方文档 是最佳途径。
Docker Compose 是现代 Web 开发和 DevOps 实践中不可或缺的一环。掌握它,你的开发部署效率将大大提升!🚀
如果这篇教程对你有帮助,请不要吝啬你的点赞👍、收藏🌟和关注哦!这对我继续创作是莫大的鼓励! ❤️ 关于 Docker Compose,你还有哪些疑问?或者想了解更深入的应用(如多环境配置、网络高级用法、与 Swarm/K8s 的关系等)?欢迎在评论区告诉我!我们下期再见!👋