别再折腾环境了!用Docker Compose一键部署JeecgBoot单体项目(附完整配置文件)
告别手动部署:用Docker Compose高效构建JeecgBoot单体应用
在当今快节奏的开发环境中,时间就是最宝贵的资源。想象一下这样的场景:你刚刚完成了一个基于JeecgBoot的单体应用开发,正准备部署到服务器上。按照传统方式,你需要手动安装MySQL、Redis、Nginx,配置各种环境变量,处理服务间的网络连接,还要确保数据持久化不会丢失。这个过程不仅耗时耗力,而且容易出错,一旦需要迁移服务器,所有工作又得重来一遍。
这就是为什么越来越多的开发者转向Docker Compose的原因。它不仅仅是一个工具,更是一种工程化的思维方式——将部署流程代码化、版本化、自动化。通过一个简单的YAML文件,你就能定义整个应用的拓扑结构、服务依赖和资源配置,实现一键部署和可重复的构建过程。
1. 为什么选择Docker Compose部署JeecgBoot
传统手动部署JeecgBoot项目通常需要经历以下繁琐步骤:
- 在服务器上安装并配置MySQL数据库
- 安装Redis并设置密码和持久化
- 配置Nginx作为反向代理和静态资源服务器
- 部署后端Java应用并确保它能连接到数据库和Redis
- 处理各种环境变量和配置文件
- 设置数据备份和持久化方案
这种方式的痛点显而易见:
- 环境不一致:开发、测试、生产环境配置差异导致"在我机器上能运行"的问题
- 部署效率低:每次部署都需要重复相同的操作,无法自动化
- 维护困难:服务间依赖关系不明确,故障排查困难
- 可移植性差:迁移到新服务器需要重新配置所有服务
相比之下,Docker Compose方案具有显著优势:
| 对比维度 | 传统部署 | Docker Compose部署 |
|---|---|---|
| 部署时间 | 1-2小时 | 5-10分钟 |
| 环境一致性 | 低 | 高 |
| 配置管理 | 分散在各处 | 集中在一个文件 |
| 可重复性 | 依赖人工操作 | 完全自动化 |
| 扩展性 | 困难 | 轻松扩展服务实例 |
技术选型考量:对于JeecgBoot这样的单体应用,Docker Compose提供了恰到好处的抽象层级——比纯Docker更结构化,又比Kubernetes更轻量。它特别适合中小型项目、开发测试环境以及需要快速迭代的场景。
2. 项目结构与Docker Compose设计
一个典型的JeecgBoot单体应用包含以下核心组件:
- 前端:基于Vue.js的Web界面,通常打包为静态文件
- 后端:Spring Boot应用,提供RESTful API
- 数据库:MySQL,存储业务数据
- 缓存:Redis,用于会话管理和缓存
- Web服务器:Nginx,作为反向代理和静态文件服务器
我们的Docker Compose设计需要解决几个关键问题:
- 服务依赖:确保服务按正确顺序启动(数据库→Redis→后端→前端)
- 网络通信:让容器间能相互访问,同时对外暴露必要端口
- 数据持久化:确保数据库和Redis数据不会随容器销毁而丢失
- 配置管理:集中管理环境变量和配置文件
- 资源限制:合理分配CPU和内存资源
推荐的项目目录结构如下:
jeecgboot-docker/
├── docker-compose.yml # Compose主配置文件
├── backend/
│ ├── Dockerfile # 后端应用Dockerfile
│ └── application.yml # 应用配置文件
├── mysql/
│ ├── conf/ # MySQL自定义配置
│ └── data/ # 数据库数据目录
├── redis/
│ ├── redis.conf # Redis配置文件
│ └── data/ # Redis数据目录
└── nginx/
├── nginx.conf # Nginx主配置
└── html/ # 前端静态文件
这种结构将所有Docker相关配置与源代码分离,既保持了项目整洁,又便于版本控制和管理。
3. 编写docker-compose.yml文件
下面是一个完整的docker-compose.yml示例,我们分段解析关键配置:
version: '3.8'
services:
mysql:
image: mysql:5.7
container_name: jeecg-mysql
environment:
MYSQL_ROOT_PASSWORD: jeecg123456
MYSQL_DATABASE: jeecg_boot
TZ: Asia/Shanghai
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
ports:
- "3306:3306"
networks:
- jeecg-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 3
restart: unless-stopped
redis:
image: redis:6.2-alpine
container_name: jeecg-redis
command: redis-server --requirepass jeecg123456 --appendonly yes
volumes:
- ./redis/data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
ports:
- "6379:6379"
networks:
- jeecg-network
restart: unless-stopped
backend:
build: ./backend
container_name: jeecg-backend
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
environment:
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
volumes:
- ./backend/application.yml:/app/config/application.yml
ports:
- "8080:8080"
networks:
- jeecg-network
restart: unless-stopped
nginx:
image: nginx:1.21-alpine
container_name: jeecg-nginx
depends_on:
- backend
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/html:/usr/share/nginx/html
ports:
- "80:80"
- "443:443"
networks:
- jeecg-network
restart: unless-stopped
networks:
jeecg-network:
driver: bridge
关键配置解析:
- 版本声明:使用较新的
3.8版本以获得最新功能 - 网络配置:
- 创建专用网络
jeecg-network确保容器间安全通信 - 避免使用默认的
host网络模式,提高安全性
- 创建专用网络
- 健康检查:
- MySQL服务添加健康检查,确保后端应用只在数据库就绪后启动
- 使用
depends_on条件控制服务启动顺序
- 数据持久化:
- MySQL数据目录映射到宿主机
./mysql/data - Redis启用AOF持久化并映射数据目录
- MySQL数据目录映射到宿主机
- 资源配置:
- 为生产环境设置时区(
Asia/Shanghai) - 使用
restart: unless-stopped确保服务异常退出后自动重启
- 为生产环境设置时区(
提示:对于生产环境,建议在MySQL和Redis配置中添加资源限制(如
mem_limit),避免单个服务占用过多系统资源。
4. 服务配置与优化技巧
4.1 MySQL优化配置
在mysql/conf/my.cnf中添加以下优化配置:
[mysqld]
lower_case_table_names=1
innodb_buffer_pool_size=256M
max_connections=200
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
default-time-zone='+8:00'
参数说明:
lower_case_table_names=1:解决Linux下MySQL表名大小写敏感问题innodb_buffer_pool_size:根据服务器内存调整,通常设为物理内存的50-70%max_connections:根据应用需求设置合理连接数
4.2 Redis生产级配置
redis/redis.conf关键配置:
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
always-show-logo no
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
4.3 Nginx高性能配置
nginx/nginx.conf优化建议:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /jeecg-boot {
proxy_pass http://backend:8080/jeecg-boot;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
4.4 后端应用Dockerfile
backend/Dockerfile最佳实践:
# 使用多阶段构建减小镜像体积
FROM eclipse-temurin:17-jdk-jammy as builder
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
RUN ./mvnw package -DskipTests
# 生产阶段
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
COPY ./config/application.yml ./config/application.yml
# 设置JVM参数
ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2 -XX:+HeapDumpOnOutOfMemoryError"
# 创建非root用户运行
RUN useradd -m myuser && chown -R myuser:myuser /app
USER myuser
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app/app.jar --spring.config.location=/app/config/application.yml"]
优化要点:
- 使用多阶段构建减少最终镜像体积
- 采用非root用户运行增强安全性
- 配置合理的JVM参数优化性能
- 将配置文件外挂便于修改
5. 部署流程与日常运维
5.1 一键部署与启动
准备好所有配置文件后,部署变得极其简单:
# 克隆项目(如果尚未克隆)
git clone https://gitee.com/jeecg/jeecg-boot.git
cd jeecg-boot
# 构建并启动所有服务
docker-compose up -d --build
# 查看服务状态
docker-compose ps
# 查看实时日志
docker-compose logs -f backend
5.2 常用运维命令
服务管理:
# 停止所有服务
docker-compose down
# 重启特定服务(如后端)
docker-compose restart backend
# 更新代码后重新构建
docker-compose up -d --build backend
数据备份:
# 备份MySQL数据
docker exec jeecg-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > backup.sql
# 备份Redis数据
docker cp jeecg-redis:/data/. ./redis-backup
日志查看:
# 查看后端最近100行日志
docker-compose logs --tail=100 backend
# 跟踪Nginx访问日志
docker-compose logs -f nginx | grep "GET"
5.3 监控与调优
基础监控命令:
# 查看容器资源使用情况
docker stats
# 检查服务健康状态
docker inspect --format='{{json .State.Health}}' jeecg-mysql
性能调优建议:
-
数据库优化:
- 定期执行
ANALYZE TABLE更新统计信息 - 监控慢查询日志并优化相应SQL
- 考虑添加适当的索引
- 定期执行
-
JVM调优:
- 根据实际负载调整
-Xms和-Xmx参数 - 使用G1垃圾收集器平衡吞吐量和延迟
- 启用GC日志分析性能瓶颈
- 根据实际负载调整
-
前端优化:
- 配置Nginx启用Brotli压缩
- 设置合理的缓存头减少重复请求
- 考虑使用CDN分发静态资源
在实际项目中,我们发现最大的性能提升往往来自于合理的数据库设计和索引优化。例如,JeecgBoot的权限表关联较多,确保这些关联查询有合适的索引可以显著提高系统响应速度。
更多推荐
所有评论(0)