一、环境准备

配置项 最低要求 推荐配置
操作系统 CentOS 7.x CentOS 7.9
CPU 2核 4核
内存 8GB 16GB
磁盘 50GB 100GB(SSD)
网络 能访问互联网(拉取镜像) -
1. 安装Docker和Docker Compose
# 1. 安装Docker(复制粘贴整条命令)
yum install -y yum-utils device-mapper-persistent-data lvm2 && yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && yum install -y docker-ce-20.10.18 docker-ce-cli-20.10.18 containerd.io && systemctl start docker.service && systemctl enable docker.service

# 2. 验证Docker(出现版本号即为成功)
docker --version

# 3. 安装Docker Compose
1. 需要先配置镜像加速器
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://hub-mirror.c.163.com",
    "https://mirror.ccs.tencentyun.com"
  ]
}
EOF

sudo curl -L "https://github.com/docker/compose/releases/download/2.26.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose

# 4. 验证Docker Compose(尽量使用高版本)
docker-compose --version
2. 创建项目目录结构
# 一键创建所有目录
mkdir -p /opt/compose_projectX/{mysql,redis,java,nginx,es,kibana,fluentd}/{conf,data,logs} && mkdir -p /opt/compose_projectX/nginx/html

# 确认目录创建成功
ls -l /opt/compose_projectX/

二、核心配置文件

1. 主配置文件(docker-compose.yml)

创建文件:vim /opt/compose_projectX/docker-compose.yml

version: '3'

networks:
  compose_projectX-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.16.0.0/24
          gateway: 172.16.0.1

services:
  mysql:
    container_name: compose_projectX-mysql
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/mysql/data:/var/lib/mysql
      - /opt/compose_projectX/mysql/logs:/var/log/mysql
      - /opt/compose_projectX/mysql/conf:/etc/mysql/conf.d
      - ./yl_app.sql:/docker-entrypoint-initdb.d/yl_app.sql
    ports:
      - "3306:3306"
    networks:
      compose_projectX-network:
        ipv4_address: 172.16.0.100

  redis:
    container_name: compose_projectX-redis
    image: redis:5.0
    restart: always
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/redis/data:/data
      - /opt/compose_projectX/redis/conf/redis.conf:/etc/redis/redis.conf
    ports:
      - "6379:6379"
    networks:
      compose_projectX-network:
        ipv4_address: 172.16.0.12
    command: redis-server /etc/redis/redis.conf

  java_app:
    container_name: compose_projectX-java_app
    build:
      context: ./java
      dockerfile: Dockerfile
    restart: always
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/java/logs:/opt/logs
    ports:
      - "8090:8090"
    depends_on:
      - mysql
      - redis
    networks:
      - compose_projectX-network

  nginx:
    container_name: compose_projectX-nginx
    image: nginx:1.20
    restart: always
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/nginx/conf:/etc/nginx/conf.d
      - /opt/compose_projectX/nginx/html:/usr/share/nginx/html
      - /opt/compose_projectX/nginx/logs:/var/log/nginx
    ports:
      - "80:80"
    depends_on:
      - java_app
    networks:
      - compose_projectX-network

  es:
    container_name: compose_projectX-es
    image: elasticsearch:6.6.1
    restart: always
    environment:
      TZ: "Asia/Shanghai"
      discovery.type: single-node
      ES_JAVA_OPTS: -Xms512m -Xmx1g
    volumes:
      - /opt/compose_projectX/es/data:/usr/share/elasticsearch/data
      - /opt/compose_projectX/es/logs:/usr/share/elasticsearch/logs
    ports:
      - "9200:9200"
      - "9300:9300"
    networks:
      - compose_projectX-network

  fluentd:
    container_name: compose_projectX-fluentd
    build:
      context: ./fluentd
      dockerfile: Dockerfile
    restart: always
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/fluentd/conf:/fluentd/etc
      - /opt/compose_projectX/fluentd/logs:/fluentd/log
      - /opt/compose_projectX/mysql/logs:/var/log/mysql
      - /opt/compose_projectX/nginx/logs:/var/log/nginx
      - /opt/compose_projectX/java/logs:/var/log/java
    depends_on:
      - es
    networks:
      - compose_projectX-network

  kibana:
    container_name: compose_projectX-kibana
    image: kibana:6.6.1
    restart: always
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - /opt/compose_projectX/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml
    ports:
      - "5601:5601"
    depends_on:
      - es
    networks:
      - compose_projectX-network
2. MySQL配置

创建文件:vim /opt/compose_projectX/mysql/conf/my.cnf

# docker官方镜像不需要设置密码策略
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
symbolic-links=0
lower_case_table_names=1  # 表名不区分大小写
character-set-server=utf8
collation-server=utf8_general_ci
log-error=/var/log/mysql/mysql_error.log
pid-file=/var/run/mysqld/mysqld.pid

# ------------------- 慢查询日志配置 -------------------
# 开启慢查询日志(1=开启,0=关闭)
slow_query_log = 1
# 慢查询日志文件路径(需与Fluentd挂载路径对应)
slow_query_log_file = /var/log/mysql/mysql_slow.log
# 定义“慢查询”阈值(单位:秒,这里设1秒,可根据需求调整)
long_query_time = 1
# 记录未使用索引的查询(1=记录,0=不记录,建议开启以便优化)
log_queries_not_using_indexes = 1
# 批量插入等操作即使未达阈值也记录(可选,根据业务需求开启)
log_throttle_queries_not_using_indexes = 10
# 记录管理员执行的慢查询(如ALTER TABLE等,可选开启)
log_slow_admin_statements = 1
3. Redis配置

创建文件:vim /opt/compose_projectX/redis/conf/redis.conf

bind 0.0.0.0
protected-mode no
port 6379
daemonize no  # 禁止后台运行(容器内必须前台运行)
appendonly yes
logfile ""
maxmemory 512mb
maxmemory-policy allkeys-lru
4. Nginx配置

创建文件:vim /opt/compose_projectX/nginx/conf/default.conf

server {
    listen       80;
    server_name  localhost;
	
    charset utf-8;
    root /usr/share/nginx/html/dist;
    index index.html;

    # 反向代理到Java微服务
    location /ylApp {
        proxy_pass http://compose_projectX-java_app:8090;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}
5. Fluentd配置

创建文件:vim /opt/compose_projectX/fluentd/conf/fluent.conf

<system>
  log_level info
</system>

# 收集MySQL日志
<source>
  @type tail
  path /var/log/mysql/mysql_error.log  # 日志文件路径
  tag mysql.error                      # 标签(用于Kibana筛选)
  read_from_head true                  # 从文件开头开始读
  <parse>
    @type none                         # 不解析格式,原样存储
  </parse>
</source>

# 收集MySQL慢查询日志
<source>
  @type tail                # 以“尾部跟踪”方式读取日志(类似tail -f)
  path /var/log/mysql/mysql_slow.log  # 慢查询日志路径(与MySQL配置一致)
  tag mysql.slow            # 日志标签(Kibana筛选时用,需唯一)
  read_from_head true       # 从文件开头开始读取(首次收集全量日志)
  <parse>
    @type none              # 慢查询日志格式不规则,暂不解析(原样存储)
  </parse>
</source>

# 收集Nginx访问日志
<source>
  @type tail
  path /var/log/nginx/access.log
  tag nginx.access
  read_from_head true
  <parse>
    @type nginx                        # 自动解析Nginx日志格式
  </parse>
</source>

# 收集Nginx错误日志
<source>
  @type tail
  path /var/log/nginx/error.log
  tag nginx.error
  read_from_head true
  <parse>
    @type none
  </parse>
</source>

# 收集Java微服务日志
<source>
  @type tail
  path /var/log/java/*.log             # 所有Java日志文件
  tag java.business
  read_from_head true
  <parse>
    @type none
  </parse>
</source>

# 发送日志到Elasticsearch(和ELK类似)
<match **>
  @type elasticsearch
  hosts compose_projectX-es:9200       # 指向ES容器
  logstash_format true                 # 生成和Logstash兼容的格式
  logstash_prefix ${tag}               # 索引名前缀(用上面定义的tag)
  logstash_dateformat %Y.%m.%d         # 按日期分索引
  flush_interval 10s                   # 10秒发送一次
</match>
6. Kibana配置

创建文件:vim /opt/compose_projectX/kibana/conf/kibana.yml

server.port: 5601
server.host: "0.0.0.0"
server.name: "compose_projectX-kibana"
elasticsearch.hosts: ["http://compose_projectX-es:9200"]  # 连接ES
elasticsearch.requestTimeout: 30000
kibana.index: ".kibana"
7. Java镜像构建文件

创建文件:vim /opt/compose_projectX/java/Dockerfile

FROM openjdk:8

# 解决时区问题
RUN apt-get update && \
    apt-get install -y tzdata && \
    rm -rf /var/lib/apt/lists/*  # 清理缓存,减小镜像体积
ENV TZ Asia/Shanghai

WORKDIR /opt

# 复制微服务jar包
COPY yl_application-1.0-SNAPSHOT.jar app.jar

EXPOSE 8090

# 启动命令(与Alpine版本一致,无需修改)
ENTRYPOINT ["java", "-Xms512m", "-Xmx1g", "-jar", "app.jar"]
8. Fluentd镜像构建文件

创建文件:vim /opt/compose_projectX/fluentd/Dockerfile

FROM fluentd:v1.16-debian-1

USER root

# 清理默认源,使用国内镜像加速
RUN echo "gem: --no-document" > /etc/gemrc && \
    gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/

# 已验证的兼容版本组合 - ES 6.6.1 + Fluentd
RUN gem install elasticsearch -v 7.17.0 --no-document && \
    gem install fluent-plugin-elasticsearch -v 5.2.4 --no-document && \
    gem install fluentd -v 1.16.2 --no-document

USER fluent

三、部署前准备工作

1. 准备必要文件
# 1. 复制数据库初始化脚本(替换成你的SQL文件路径)
cp /opt/yl_app.sql /opt/compose_projectX/

# 2. 复制Java微服务jar包(替换成你的jar包路径)
cp /opt/yl_application-1.0-SNAPSHOT.jar /opt/compose_projectX/java/

# 3. 复制前端文件(替换成你的前端压缩包路径)
unzip /opt/dist.zip -d /opt/compose_projectX/nginx/html/
2. 设置目录权限(关键步骤,同之前)
# 1. Elasticsearch
# 容器内运行用户:elasticsearch(默认 UID 1000)
chown -R 1000:1000 /opt/compose_projectX/es/{conf,data,logs}  # 匹配容器内用户
chmod -R 755 /opt/compose_projectX/es/{conf,data,logs}       # 所有者可读写,其他只读

# 2. Nginx
# 容器内运行用户:nginx(默认 UID 101)
chown -R 101:101 /opt/compose_projectX/nginx/{conf,data,logs,html}  # 匹配容器内用户
chmod -R 755 /opt/compose_projectX/nginx/{conf,data,logs,html}      # 所有者可读写,其他只读

# 3. Java目录(根据容器配置二选一)
## 场景A:Java容器用默认 root 用户(未在 Dockerfile 中指定 USER)
chmod -R 755 /opt/compose_projectX/java/{conf,data,logs}  # root 拥有所有权限,755 足够

## 场景B:Java容器用自定义用户(如 Dockerfile 中添加了 "USER 1000")
# chown -R 1000:1000 /opt/compose_projectX/java/{conf,data,logs}  # 匹配自定义用户 UID
# chmod -R 755 /opt/compose_projectX/java/{conf,data,logs}        # 所有者可读写,其他只读

# 4. MySQL 
# 容器内运行用户:mysql(默认 UID 999)
chown -R 999:999 /opt/compose_projectX/mysql/{conf,data,logs}  # 匹配容器内用户
chmod -R 755 /opt/compose_projectX/mysql/{conf,data,logs}       # 所有者可读写,其他只读

# 5. Redis 
# 容器内运行用户:redis(默认 UID 999)
chown -R 999:999 /opt/compose_projectX/redis/{conf,data,logs}  # 匹配容器内用户
chmod -R 755 /opt/compose_projectX/redis/{conf,data,logs}     # 所有者可读写,其他只读

# 6. Fluentd 相关目录(conf配置、logs日志、data临时数据)
# 容器内用户:fluent(UID 999,GID 999)
chown -R 999:999 /opt/compose_projectX/fluentd/{conf,logs,data}
chmod -R 755 /opt/compose_projectX/fluentd/{conf,logs,data}

# 7. Kibana 相关目录(conf配置、logs日志、data数据)
# 容器内用户:kibana(UID 1000,GID 1000)
chown -R 1000:1000 /opt/compose_projectX/kibana/{conf,logs,data}
chmod -R 755 /opt/compose_projectX/kibana/{conf,logs,data}

四、启动服务(一键部署)

# 进入项目目录
cd /opt/compose_projectX

# 构建镜像(首次运行或修改Dockerfile后需要)
docker-compose build

# 启动所有服务(后台运行)
docker-compose up -d

# 查看启动状态(确保所有服务都是Up状态)
docker-compose ps

# 查看Java服务日志,确认连接成功(无数据库连接错误)
docker logs compose_projectX-java_app

五、验证服务可用性

  1. 访问Nginx前端:在主机浏览器输入 http://192.168.10.12(写你自己的虚拟机IP),应能看到前端页面;
  2. 测试Java接口:通过前端操作或Postman访问 http://192.168.10.12/ylApp/xxx(你的接口路径),应能正常返回数据;
  3. 验证日志收集
    1. 访问Kibana:http://192.168.10.12:5601(首次加载可能需要几分钟)
    2. 创建索引模式:
    • 点击左侧菜单 ManagementIndex Patterns
    • 输入 nginx.* 并点击 Next step
    • 时间字段选择 @timestamp,点击 Create index pattern
    1. 查看日志:
    • 点击左侧菜单 Discover
    • 顶部选择刚创建的索引模式
    • 能看到Nginx的访问日志即为成功

六、常用运维命令

操作 命令
停止所有服务 docker-compose down
重启所有服务 docker-compose restart
重启单个服务(如Java) docker-compose restart java_app
查看服务日志(如Java) docker-compose logs -f java_app
查看容器资源占用 docker stats
备份MySQL数据 tar -zcvf /opt/backup/mysql_$(date +%Y%m%d).tar.gz /opt/compose_projectX/mysql/data
查看ES是否正常 curl http://localhost:9200(返回JSON即为正常)

七、Fluentd说明(对比ELK)

特性 Fluentd(本方案) Logstash(ELK)
配置复杂度 简单(单文件配置) 较复杂(管道配置)
资源占用 低(适合中小项目) 较高
学习曲线 平缓(配置直观) 较陡
和ELK兼容性 完全兼容(可对接ES和Kibana) -
本方案优势 配置简单,和ELK用法一致,容易上手 -

八、常见问题排查

问题1:ES启动失败

  • 原因:权限不足或内存不够

  • 解决

    # 修复权限
    chown -R 1000:1000 /opt/compose_projectX/es/{conf,data,logs}  # 匹配容器内用户
    chmod -R 755 /opt/compose_projectX/es/{conf,data,logs}       # 所有者可读写,其他只读
    # 调整ES内存(编辑docker-compose.yml中的ES_JAVA_OPTS为-Xms256m -Xmx512m)
    docker-compose up -d --force-recreate es
    

问题2:Java服务连接不上MySQL或者Redis

  • 原因:docker-compose.yml自定义ip设置错误或未生效

  • 解决

    # 检查容器IP
    docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{.NetworkID}}{{end}}' compose_projectX-mysql
    docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{.NetworkID}}{{end}}' compose_projectX-redis
    # 查看Java日志找错误
    docker-compose logs -f java_app
    

问题3:Kibana看不到日志

  • 原因:Fluentd未正确收集或ES未启动

  • 解决

    # 查看Fluentd日志
    docker-compose logs -f fluentd
    # 检查日志文件是否存在
    ls /opt/compose_projectX/nginx/logs/access.log
    

九、总结

本方案通过Docker Compose实现项目的一键部署,同时用更简单的Fluentd替代Logstash实现日志收集,保留了ELK中你熟悉的Elasticsearch和Kibana用法。所有配置都经过简化,适合新手操作,只需按步骤执行命令即可完成部署。

部署完成后,你可以像使用ELK一样在Kibana中查看日志,服务间通信通过Docker自动管理,无需关心复杂的网络配置。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐