轻量级 CI/CD 实战(三):Kafka消费者Docker容器化部署

轻量级 CI/CD 实战(三): Kafka 消费者容器化部署

目录

背景与目标

在日志分析系统中,Nginx 日志通过 Filebeat 发送到 Kafka 集群,需部署一个长期运行的消费者程序,将日志解析后写入 MySQL 并缓存到 Redis。

为提升部署效率、避免环境依赖冲突,采用 Docker 容器化方案,实现:

  • 服务开机自启(--restart=always
  • 网络直连宿主机(--network host
  • 代码更新后快速重建

项目结构

项目存放于 /opt/log_consumer/,目录结构如下:

bash 复制代码
/opt/log_consumer/
├── consumer.py          # 主程序:Kafka消费 + MySQL写入 + Redis缓存
├── requirements.txt     # Python依赖列表
└── Dockerfile           # Docker镜像构建定义

关键配置文件

Dockerfile

使用官方 python:3.9-slim 镜像,轻量且兼容性好:

bash 复制代码
# 使用轻量 Python 镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY requirements.txt .

# 安装 Python 依赖(禁用缓存确保干净构建)
RUN pip install --no-cache-dir -r requirements.txt

# 复制主程序
COPY consumer.py .

# 启动命令
CMD ["python", "consumer.py"]

requirements.txt

bash 复制代码
kafka-python==2.0.2
PyMySQL==1.1.0
redis==5.0.1

consumer.py 注意事项

Kafka 消费者初始化时,必须使用集群主机名,不可用 localhost 或 127.0.0.1:

bash 复制代码
consumer = KafkaConsumer(
    'nginx-logs',
    bootstrap_servers=["kafka1:9092", "kafka2:9092", "kafka3:9092"],  # ← 关键!
    auto_offset_reset='latest',
    enable_auto_commit=True,
    group_id='log-consumer-group'
)

同时确保:

所有依赖库已正确导入

每行参数末尾加英文逗号 ,(避免 SyntaxError)

异常处理完善(防止进程意外退出)

部署流程

清理旧容器

容器名称冲突是常见错误,务必先删除旧容器

bash 复制代码
docker stop log-consumer 2>/dev/null && docker rm log-consumer 2>/dev/null

即使容器已停止,仍占用名称,必须 rm

语法预检

避免因语法错误导致容器无限重启

bash 复制代码
cd /opt/log_consumer
python3 -m py_compile consumer.py

无输出即表示语法正确。

构建镜像

bash 复制代码
docker build -t log-consumer .

构建成功后,可通过 docker images 查看镜像

启动容器

使用 host 网络模式直连 Kafka,开启自启:

bash 复制代码
docker run -d \
  --network host \
  --name log-consumer \
  --restart=always \
  log-consumer

--network host:容器共享宿主机网络,可直接访问 kafka1:9092

验证运行状态

查看实时日志:

bash 复制代码
docker logs -f log-consumer

成功标志(你的程序应输出类似内容):

bash 复制代码
OK MySQL连接成功
OK Redis连接成功
OK Kafka消费者创建成功
TARGET 开始监听日志...

常见问题排查

容器不断重启

现象:docker ps 显示容器状态为 Restarting

原因:程序启动后立即退出(如语法错误、连接失败)

解决:

bash 复制代码
停止容器:docker stop log-consumer
前台运行查看错误:docker run -it --network host --rm log-consumer
根据报错修复代码

Kafka 连接失败(NoBrokersAvailable)

现象:日志报 kafka.errors.NoBrokersAvailable

原因:

bootstrap_servers 写成 localhost:9092(这里检查kafka配置文件)

Kafka 未监听外网 IP

防火墙阻断 9092 端口

解决:

bash 复制代码
使用 kafka1:9092 等主机名(需 DNS 或 hosts 解析)
在宿主机测试:telnet kafka1 9092

Python 语法错误

现象:SyntaxError: invalid syntax,报错行看似正常

原因:

上一行缺少逗号(最常见!)

中文标点混入

文件含 BOM 头或 CRLF 换行符

kafka3:9092末尾要加上逗号,否则系统将这一行和下一行当作同一行处理就报错了

解决:

bash 复制代码
用 cat -A 检查隐藏字符
用 python3 -m py_compile 提前校验
重写可疑行(手动输入英文标点)

一键重启脚本

bash 复制代码
#!/bin/bash
cd /opt/log_consumer

# 停旧容器
docker stop log-consumer 2>/dev/null
docker rm log-consumer 2>/dev/null

# 构建新镜像
docker build -t log-consumer .

# 启动
docker run -d --network host --name log-consumer --restart=always log-consumer

echo "✅ 消费者已启动,查看日志:docker logs -f log-consumer"

总结

通过容器化 Kafka 消费者,我们实现了:

环境隔离:依赖不污染宿主机

快速部署:6 条命令完成上线

高可用:崩溃自动重启

标准化:任何人拿到代码均可一键运行


作者:subencai

环境:CentOS 7 + Docker 24.0 + Kafka 3.3

最后更新:2025年11月

相关推荐
闪电悠米9 小时前
黑马点评-Redis 消息队列-03_stream_consumer_group
开发语言·数据库·redis·分布式·缓存·junit·lua
正经教主11 小时前
【docker基础】第五课:Docker网络详解
运维·docker·容器
折哥的程序人生 · 物流技术专研11 小时前
《Java 100 天进阶之路》第95篇:消息队列基础(RocketMQ/Kafka)(2026版)
java·面试·kafka·rocketmq·java-rocketmq·求职招聘
鹤鸣的日常12 小时前
前端运行时动态环境变量方案
前端·react.js·docker·前端框架·vue·gitlab
z落落13 小时前
C# 事件(Event)+自定义带参数事件例子
开发语言·分布式·c#
彼岸星光ぐ>13 小时前
Windows系统下Kafka KRaft模式配置与启动教程
kafka
我是一颗柠檬14 小时前
【Java项目技术亮点】分库分表+数据路由策略:单表5000万后的架构升级方案
java·开发语言·分布式·架构
半夜修仙15 小时前
RabbitMQ中如何保证消息的可靠性传输
java·分布式·中间件·rabbitmq·github·java-rabbitmq
我是谁??15 小时前
ubuntu22.04 通过docker部署vLLM(Qwen3-0.6B)大模型+New API+OpenWebUI
docker·容器·vllm
运维瓦工16 小时前
DevOps 生态介绍(十):Docker Compose 核心 YAML 配置详解与常用命令大全
spring cloud·docker·容器