Docker Compose 部署微服务:从零搭建可复现的容器化环境

环境准备:安装与验证
在开始之前,请确保你的机器上已安装 Docker 和 Docker Compose。Docker Compose 是 Docker 官方提供的多容器编排工具,它通过一个 YAML 文件定义和运行多个容器 [来源#1]。我们首先验证安装是否成功。
docker --version
# 预期输出:Docker version 24.0.7, build afdd53b
docker compose version
# 预期输出:Docker Compose version v2.23.0
验证 Docker 和 Docker Compose 安装
如果命令未找到,请根据你的操作系统安装 Docker Desktop(Windows/Mac)或 Docker Engine(Linux)[来源#2]。安装完成后,我们创建一个项目目录来存放所有文件。
mkdir my-microservices
cd my-microservices
创建项目目录
步骤拆解:编写 docker-compose.yml
现在,我们来编写核心的 `docker-compose.yml` 文件。这个文件将定义三个服务:一个简单的 Web 应用(使用 Python Flask)、一个 PostgreSQL 数据库和一个 Redis 缓存。服务之间通过 Docker 内置的网络进行通信。
version: '3.8'
services:
webapp:
build: .
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/appdb
- REDIS_URL=redis://redis:6379/0
depends_on:
- db
- redis
networks:
- app-network
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app-network
redis:
image: redis:7-alpine
networks:
- app-network
volumes:
postgres_data:
networks:
app-network:
driver: bridge
docker-compose.yml 文件示例
这个文件定义了三个服务:`webapp`、`db` 和 `redis`。`depends_on` 确保 Web 应用在数据库和缓存启动后才启动 [来源#1]。接下来,我们为 Web 应用创建一个简单的 Flask 程序。
from flask import Flask, jsonify
import redis
import psycopg2
import os
app = Flask(__name__)
# 连接 Redis
redis_client = redis.Redis.from_url(os.environ.get('REDIS_URL', 'redis://redis:6379/0'))
# 连接 PostgreSQL
def get_db_connection():
conn = psycopg2.connect(os.environ.get('DATABASE_URL'))
return conn
@app.route('/')
def index():
# 测试 Redis
redis_client.set('test_key', 'Hello from Redis!')
redis_value = redis_client.get('test_key').decode('utf-8')
# 测试 PostgreSQL
conn = get_db_connection()
cur = conn.cursor()
cur.execute("SELECT version();")
db_version = cur.fetchone()[0]
cur.close()
conn.close()
return jsonify({
'message': 'Microservice is running!',
'redis': redis_value,
'postgres_version': db_version
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
app.py - Flask Web 应用
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
Dockerfile
Flask==2.3.3
psycopg2-binary==2.9.7
redis==5.0.1
requirements.txt
结果验证:启动与测试
一切就绪,现在启动整个环境。在 `my-microservices` 目录下执行以下命令。
docker compose up --build -d
构建并启动所有服务
这个命令会构建 Web 应用镜像,并在后台启动所有服务。预期输出会显示构建和拉取镜像的日志。启动后,使用 `docker compose ps` 查看服务状态。
docker compose ps
# 预期输出示例:
# NAME COMMAND SERVICE STATUS
# my-microservices-db_1 "docker-entrypoint.she…" db Up 2 seconds
# my-microservices-redis_1 "docker-entrypoint.she…" redis Up 2 seconds
# my-microservices-webapp_1 "python app.py" webapp Up 2 seconds
查看服务状态
现在,我们验证 Web 应用是否正常工作,并检查它是否能连接到数据库和缓存。
curl http://localhost:5000/
# 预期输出:
# {
# "message": "Microservice is running!",
# "redis": "Hello from Redis!",
# "postgres_version": "PostgreSQL 15.4 on x86_64-pc-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r4) 12.2.1 20220924, 64-bit"
# }
测试 Web 应用端点
如果看到上述 JSON 响应,说明 Web 应用、Redis 和 PostgreSQL 都已成功启动并通信。你可以通过 `docker compose logs -f webapp` 查看应用日志,或 `docker compose down` 停止所有服务。
常见错误与排查
在部署过程中,你可能会遇到一些常见问题。这里列出三个典型错误及其解决方法。
- 错误 1:端口冲突。如果 `5000` 端口已被占用,启动会失败。排查方法:使用 `netstat -tuln | grep 5000`(Linux/Mac)或 `netstat -ano | findstr :5000`(Windows)检查端口占用。解决方法:修改 `docker-compose.yml` 中的 `ports` 映射,例如改为 `"5001:5000"`。
- 错误 2:服务启动顺序问题。如果 Web 应用在数据库完全就绪前尝试连接,会报连接错误。排查方法:查看 Web 应用日志 `docker compose logs webapp`,寻找类似 `psycopg2.OperationalError` 的错误。解决方法:确保 `depends_on` 正确配置,并在应用代码中添加重试逻辑(例如使用 `time.sleep` 或连接池)。
- 错误 3:镜像构建失败。通常是因为 `Dockerfile` 中的依赖缺失或网络问题。排查方法:查看构建日志 `docker compose build --no-cache`。解决方法:检查 `requirements.txt` 是否包含所有依赖,并确保 Docker 能访问互联网拉取基础镜像。
Docker Compose 的核心价值在于用一个文件定义整个应用栈,这使得环境复现变得极其简单 [来源#2]。
通过本教程,你已经成功使用 Docker Compose 部署了一个包含 Web、数据库和缓存的微服务环境。你学会了编写 `docker-compose.yml`、管理容器生命周期以及验证服务间通信。记住,保持 `docker-compose.yml` 和相关配置文件的版本控制,是确保环境一致性的关键 [来源#1]。