Ubuntu 24 环境,使用 Docker Compose 启动 Nginx, Web (Python), 和轻量级消息队列服务的 docker-compose.yml 文件,以及相关的配置和说明。
文件结构:
为了组织清晰,建议创建如下目录结构:
your_project_root/
├── docker-compose.yml
├── nginx/
│ └── nginx.conf
└── web/
├── app.py
└── requirements.txt
- docker-compose.yml 文件:
version: '3.8'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- web
web:
build: ./web
ports:
- "5000:5000" # 可选,方便本地调试,生产环境可移除
environment:
- REDIS_HOST=message_queue # 使用 service name 作为 hostname
- REDIS_PORT=6379
depends_on:
- message_queue
message_queue:
image: redis:latest # 使用 Redis 作为轻量级消息队列
ports:
- "6379:6379" # 可选,方便本地连接 Redis Client 工具,生产环境可移除
解释:
version: '3.8': 指定 Docker Compose 文件版本。
services:: 定义要启动的服务。
**nginx 服务:**
image: nginx:latest: 使用官方最新版本的 Nginx 镜像。
ports: - "80:80": 将宿主机的 80 端口映射到容器的 80 端口,用于外部访问。
volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf: 将宿主机 nginx/nginx.conf 文件挂载到容器的 Nginx 配置目录,用于自定义 Nginx 配置。
depends_on: - web: 确保 nginx 服务在 web 服务启动之后再启动,因为 Nginx 需要转发请求到 web 服务。
**web 服务:**
build: ./web: 使用当前目录下的 web 文件夹中的 Dockerfile 构建镜像。
ports: - "5000:5000": 可选,仅用于本地调试。将宿主机的 5000 端口映射到容器的 5000 端口。在生产环境中,Nginx 会作为入口,不需要直接暴露 web 服务的端口。
environment:: 设置环境变量传递给 web 服务容器。
REDIS_HOST=message_queue: 设置 Redis 主机名为 message_queue,这是 Docker Compose 服务名,容器内部可以通过服务名直接访问。
REDIS_PORT=6379: 设置 Redis 端口为 6379。
depends_on: - message_queue: 确保 web 服务在 message_queue 服务启动之后再启动,因为 web 服务需要连接消息队列。
**message_queue 服务:**
image: redis:latest: 使用官方最新版本的 Redis 镜像作为轻量级消息队列。Redis 具有高性能、易用性,适合作为轻量级消息队列使用。
ports: - "6379:6379": 可选,仅用于本地调试。将宿主机的 6379 端口映射到容器的 6379 端口,方便本地使用 Redis 客户端工具连接容器内的 Redis 服务进行调试和管理。在生产环境中,如果不需要外部直接访问 Redis,可以移除此端口映射。
- nginx/nginx.conf 文件 (Nginx 配置文件):
server {
listen 80;
server_name localhost; # 或者你的域名
location / {
proxy_pass http://web:5000; # 转发到 web 服务,使用 service name 'web' 和端口 5000
proxy_set_header Host host;
proxy_set_header X-Real-IPremote_addr;
proxy_set_header X-Forwarded-For proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protoscheme;
}
}
解释:
listen 80;: Nginx 监听 80 端口。
server_name localhost;: 设置服务器名称,这里使用 localhost,可以根据实际情况修改为你的域名。
location / { ... }: 配置根路径 / 的请求处理。
proxy_pass http://web:5000;: 将所有请求转发到 web 服务,web 是 Docker Compose 中 web 服务的服务名,Docker DNS 解析会将 web 解析为 web 服务容器的 IP 地址。5000 是 web 服务容器内部监听的端口 (在 web/app.py 中定义)。
proxy_set_header ...: 设置一些常用的 HTTP 头信息,传递客户端的 Host, IP 等信息给后端 web 服务。
- web/Dockerfile 文件 (Web 服务 Dockerfile):
FROM python:3.9-slim-buster # 或者选择其他 Python 3 版本
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY app.py app.py
CMD ["python", "app.py"]
解释:
FROM python:3.9-slim-buster: 基于官方 Python 3.9 slim-buster 镜像构建。选择 slim-buster 版本可以减小镜像体积。
WORKDIR /app: 设置工作目录为 /app。
COPY requirements.txt requirements.txt: 复制 requirements.txt 文件到容器的 /app 目录。
RUN pip install -r requirements.txt: 安装 requirements.txt 中列出的 Python 依赖包。
COPY app.py app.py: 复制 app.py 文件到容器的 /app 目录。
CMD ["python", "app.py"]: 定义容器启动时执行的命令,运行 app.py 文件。
- web/requirements.txt 文件 (Web 服务 Python 依赖):
flask
redis
解释:
flask: 用于构建 Web 服务的 Python Flask 框架。
redis: 用于连接 Redis 消息队列的 Python Redis 客户端库。
- web/app.py 文件 (Web 服务 Python 程序示例):
from flask import Flask, request, jsonify
import redis
import os
app = Flask(__name__)
# 从环境变量中获取 Redis 配置,Docker Compose 会自动设置这些环境变量
redis_host = os.environ.get('REDIS_HOST')
redis_port = int(os.environ.get('REDIS_PORT', 6379)) # 默认端口 6379
redis_client = redis.StrictRedis(host=redis_host, port=redis_port, db=0)
@app.route('/messages', methods=['POST', 'GET'])
def messages():
if request.method == 'POST':
# 接收 POST 请求,将消息添加到消息队列
message_data = request.get_json()
if not message_data or 'message' not in message_data:
return jsonify({"status": "error", "message": "Missing 'message' in request body"}), 400
message = message_data['message']
try:
redis_client.lpush('messages', message) # 使用 Redis List 作为队列
return jsonify({"status": "success", "message": "Message added to queue"})
except redis.exceptions.ConnectionError as e:
return jsonify({"status": "error", "message": f"Failed to connect to Redis: {e}"}), 500
elif request.method == 'GET':
# 接收 GET 请求,从消息队列中读取消息
try:
messages = redis_client.lrange('messages', 0, -1) # 获取队列中所有消息
decoded_messages = [msg.decode('utf-8') for msg in messages] # 解码 bytes 为 string
return jsonify({"status": "success", "messages": decoded_messages})
except redis.exceptions.ConnectionError as e:
return jsonify({"status": "error", "message": f"Failed to connect to Redis: {e}"}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True) # 监听 5000 端口,方便 Nginx 转发
解释:
导入库: 导入 Flask, redis, os 库。
Flask 应用初始化: app = Flask(name) 创建 Flask 应用实例。
Redis 连接配置:
从环境变量 REDIS_HOST 和 REDIS_PORT 中获取 Redis 主机和端口,这些环境变量由 docker-compose.yml 文件设置。
使用 redis.StrictRedis 创建 Redis 客户端连接。
/messages 路由:
POST 方法:
接收 JSON 格式的请求,从请求体中获取 message 字段。
使用 redis_client.lpush('messages', message) 将消息添加到 Redis List 队列中 (这里使用 Redis List 简单模拟队列,更复杂的场景可以使用 Redis Streams 或专业的队列服务如 RabbitMQ)。
返回 JSON 格式的成功响应。
处理 Redis 连接错误。
GET 方法:
使用 redis_client.lrange('messages', 0, -1) 从 Redis List 队列中获取所有消息。
将获取到的 bytes 类型消息解码为 UTF-8 字符串。
返回 JSON 格式的成功响应,包含消息列表。
处理 Redis 连接错误。
if __name__ == '__main__':: 当直接运行 app.py 文件时,启动 Flask 开发服务器,监听 0.0.0.0:5000。
使用方法:
安装 Docker 和 Docker Compose: 确保你的 Ubuntu 24 环境已经安装了 Docker 和 Docker Compose。
创建项目目录和文件: 按照上面描述的文件结构创建目录和文件,并将代码复制到对应的文件中。
构建和启动服务: 在 docker-compose.yml 文件所在的目录中,打开终端,运行以下命令:
docker-compose up --build
--build 参数会在首次启动时构建 web 服务的 Docker 镜像。
访问服务:
Nginx (Web 服务入口): 在浏览器中访问 http://localhost (或者你的服务器 IP 地址)。Nginx 会将请求转发到 web 服务。
测试消息队列 (通过 Web 服务):
发送消息 (POST 请求):
使用 curl 或 Postman 等工具发送 POST 请求到 http://localhost/messages,请求体为 JSON 格式:
curl -X POST -H "Content-Type: application/json" -d '{"message": "Hello from curl!"}' http://localhost/messages
获取消息 (GET 请求):
使用 curl 或浏览器访问 http://localhost/messages,获取消息队列中的消息列表。
curl http://localhost/messages
停止服务: 在终端中按下 Ctrl+C 停止服务,或者在终端中运行以下命令停止并移除容器:
docker-compose down
注意事项:
生产环境配置: 这份 docker-compose.yml 文件和示例代码主要用于演示和开发。在生产环境中,你需要考虑以下方面:
Nginx 配置: 配置 HTTPS, 域名, 缓存, 安全设置等。
Web 服务: 完善错误处理, 日志记录, 性能优化, 安全加固等。
Redis: 配置持久化, 密码认证, 集群 (如果需要高可用和扩展性)。
监控和日志: 集成监控系统和日志收集系统。
资源限制: 根据实际需求配置 Docker 容器的资源限制 (CPU, 内存)。
消息队列选择: Redis List 适合简单的消息队列场景。对于更复杂的消息队列需求,例如消息持久化、消息确认、路由、优先级等,可以考虑使用 RabbitMQ, Kafka 等更专业的消息队列服务。
端口映射: 生产环境中,可以移除 web 和 message_queue 服务的端口映射,只保留 nginx 的 80 端口映射,以提高安全性。
镜像版本: 在生产环境中,建议使用具体的镜像版本号,而不是 latest,以避免版本更新带来的不兼容性问题。
希望这份 docker-compose.yml 文件和说明能够帮助你在 Ubuntu 24 环境下快速搭建起包含 Nginx, Web (Python), 和轻量级消息队列的 Docker 应用。
docker 启动web 消息队列服务