引言:从单个容器到应用“全家桶”
在上一篇教程中,我们领略了用 docker run
命令快速启动单个服务(如PostgreSQL)的便捷。但在真实的Web应用开发中,一个应用通常由多个相互关联的服务组成。
一个典型的例子就是:
- 一个 Web服务器 (如 Nginx 或 Apache) 用于托管前端静态文件。
- 一个 后端应用 (如 Node.js, Python, Java) 提供API。
- 一个 数据库 (如 PostgreSQL 或 MySQL) 用于存储数据。
如果还用 docker run
来一个一个地启动和管理它们,你需要处理:
- 多个长长的
docker run
命令。 - 手动创建Docker网络,让容器之间可以相互通信。
- 复杂的启动和关闭顺序。
这正是 Docker Compose 大显身手的舞台。它是一个用于定义和运行多容器Docker应用的工具。你只需使用一个 docker-compose.yml
的YAML文件来配置你的应用服务栈,然后用一条命令,就能根据你的配置创建并启动所有服务。
案例:Nginx + PostgreSQL
为了简化,我们将构建一个由两个服务组成的经典组合:
db
: 一个PostgreSQL数据库服务。web
: 一个Nginx Web服务器,它将显示一个简单的欢迎页面。
步骤1:创建项目文件夹结构
首先,创建一个项目文件夹,并在其中组织好我们的文件。
my-web-app/
├── docker-compose.yml <-- Docker Compose的配置文件
└── nginx/
└── index.html <-- Nginx要显示的网页内容
nginx/index.html
的内容可以很简单:<!DOCTYPE html> <html> <head> <title>Welcome to My App!</title> </head> <body> <h1>Hello from Nginx, running in Docker Compose!</h1> <p>My database is running in another container.</p> </body> </html>
步骤2:编写 docker-compose.yml
这是我们的核心。在 my-web-app
根目录下创建 docker-compose.yml
文件,并写入以下内容:
version: '3.8' # 指定compose文件版本
services: # 定义一组服务
db: # 服务名称1:数据库
image: postgres:13 # 使用的镜像
container_name: my_postgres_compose # 容器名
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: myappdb
volumes:
- postgres_data:/var/lib/postgresql/data # 数据卷挂载
networks:
- app_network # 加入网络
web: # 服务名称2:Web服务器
image: nginx:latest # 使用的镜像
container_name: my_nginx_compose # 容器名
ports:
- "8080:80" # 端口映射:宿主机8080 -> 容器80
volumes:
- ./nginx:/usr/share/nginx/html # 挂载本地nginx文件夹到容器中
depends_on:
- db # 声明依赖关系,先启动db
networks:
- app_network # 加入网络
volumes: # 定义数据卷
postgres_data:
networks: # 定义网络
app_network:
driver: bridge
关键配置解读:
services
: 定义了我们应用的两个核心部分db
和web
。environment
: 和docker run -e
一样,用于设置环境变量。这里我们为PostgreSQL设置了用户名、密码和默认数据库名。volumes
: 这是实现数据持久化的关键。postgres_data:/var/lib/postgresql/data
: 将一个名为postgres_data
的**具名卷(named volume)**挂载到容器内存储PostgreSQL数据的目录。这样做的好处是,即使我们删除了db
容器,这个数据卷依然存在,下次启动时数据不会丢失。./nginx:/usr/share/nginx/html
: 将我们本地的./nginx
文件夹,直接映射到Nginx容器存放网页的目录。这样,我们修改本地的index.html
,网页会立刻更新,无需重建容器。
networks
: 我们创建了一个名为app_network
的自定义桥接网络。所有加入这个网络的服务,都可以通过服务名作为主机名直接相互访问。例如,web
服务里的程序可以直接通过db
这个主机名连接到PostgreSQL,而无需关心它的IP地址。depends_on
: 声明了web
服务依赖于db
服务。这让Compose知道应该先启动数据库,再启动Web服务器。
步骤3:一键启动!
现在,在 my-web-app
文件夹的根目录(即 docker-compose.yml
所在的目录)下,打开终端,运行:
docker-compose up -d
up
: 启动服务。-d
: 同样是在后台分离模式下运行。
Compose会读取 docker-compose.yml
文件,自动创建网络、数据卷,并按顺序拉取镜像、启动 db
和 web
两个容器。
步骤4:验证
- 访问网页:打开浏览器,访问
http://localhost:8080
。你应该能看到我们编写的index.html
的内容。 - 查看容器:运行
docker ps
,你会看到my_postgres_compose
和my_nginx_compose
两个容器正在愉快地运行。
管理你的应用栈
-
一键关闭并删除容器: 在
docker-compose.yml
所在目录运行:docker-compose down
这条命令会优雅地停止并删除由
up
命令创建的所有容器和网络。但我们定义的postgres_data
数据卷默认不会被删除,以防数据丢失。
总结
Docker Compose是 docker run
命令的自然演进,是管理现代微服务应用的必备工具。它通过一个声明式的YAML文件,将复杂的应用环境配置“代码化”,让应用的启动、销毁和共享变得前所未有的简单。
现在,你已经掌握了用Compose编排多容器应用的核心思想。在你的下一个项目中,尝试用 docker-compose.yml
来定义你的开发环境吧!
...