JeecgBoot单体项目Docker化部署实战:从本地开发到云服务器的一站式迁移
对于许多Java开发者来说,JeecgBoot已经成为一个高效的企业级开发框架选择。但当本地开发完成后,如何将项目顺利迁移到生产环境却常常令人头疼。本文将带你从零开始,完成JeecgBoot项目从本地开发环境到云服务器的全容器化部署,涵盖MySQL、Redis、后端服务和前端资源的完整解决方案。
1. 环境准备与基础配置
在开始部署前,我们需要确保服务器环境满足基本要求。推荐使用Ubuntu 20.04 LTS或CentOS 8作为基础操作系统,这些发行版对Docker的支持较为完善。
1.1 服务器基础环境配置
首先更新系统并安装必要工具:
# Ubuntu/Debian sudo apt update && sudo apt upgrade -y sudo apt install -y curl git vim # CentOS/RHEL sudo yum update -y sudo yum install -y curl git vim接下来安装Docker引擎,这是整个部署过程的核心:
# 安装Docker官方GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 添加Docker稳定版仓库 echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker引擎 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 验证安装 sudo docker run hello-world提示:生产环境中建议配置Docker守护进程的日志轮转和存储限制,避免日志文件占用过多磁盘空间。
1.2 网络与存储规划
合理的网络和存储规划能避免后续的许多问题。我们建议采用以下目录结构:
/opt/jeecg/ ├── mysql/ │ ├── conf/ │ ├── data/ │ └── logs/ ├── redis/ │ ├── conf/ │ └── data/ ├── backend/ │ └── Dockerfile └── frontend/ ├── dist/ └── nginx.conf使用以下命令创建目录结构:
sudo mkdir -p /opt/jeecg/{mysql,redis,backend,frontend}/{conf,data,logs} sudo chown -R $USER:$USER /opt/jeecg2. 数据库服务容器化
2.1 MySQL容器部署
JeecgBoot默认支持MySQL 5.7及以上版本。以下是推荐的Docker运行命令:
docker run -d \ --name jeecg-mysql \ --restart unless-stopped \ -p 3306:3306 \ -v /opt/jeecg/mysql/conf:/etc/mysql/conf.d \ -v /opt/jeecg/mysql/data:/var/lib/mysql \ -v /opt/jeecg/mysql/logs:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=YourStrongPassword123 \ -e MYSQL_DATABASE=jeecg_boot \ -e MYSQL_USER=jeecg \ -e MYSQL_PASSWORD=jeecg123456 \ mysql:5.7 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci关键参数说明:
--restart unless-stopped:确保容器意外退出后自动重启utf8mb4字符集:支持完整的Unicode字符,包括emoji- 卷挂载:实现配置、数据和日志的持久化
2.2 Redis容器部署
Redis作为缓存服务,配置相对简单:
docker run -d \ --name jeecg-redis \ --restart unless-stopped \ -p 6379:6379 \ -v /opt/jeecg/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v /opt/jeecg/redis/data:/data \ redis:6.2 \ redis-server /usr/local/etc/redis/redis.conf \ --requirepass "YourRedisPassword123" \ --appendonly yes建议的Redis配置文件(/opt/jeecg/redis/conf/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 yes3. 后端服务容器化
3.1 项目打包与Dockerfile编写
在本地开发环境,使用Maven打包项目:
mvn clean package -DskipTests -Pprod将生成的jeecg-system-start-*.jar文件上传到服务器的/opt/jeecg/backend目录。
创建Dockerfile:
# 使用官方OpenJDK镜像作为基础 FROM eclipse-temurin:17-jdk-jammy # 设置工作目录 WORKDIR /app # 复制JAR文件到容器 COPY jeecg-system-start-*.jar app.jar # 暴露端口 EXPOSE 8080 # 设置JVM参数 ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Dfile.encoding=UTF-8" # 启动命令 ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar app.jar"]3.2 构建并运行后端容器
构建Docker镜像:
cd /opt/jeecg/backend docker build -t jeecg-backend .运行容器:
docker run -d \ --name jeecg-backend \ --restart unless-stopped \ -p 8080:8080 \ -v /opt/jeecg/backend/logs:/app/logs \ --link jeecg-mysql:jeecg-boot-mysql \ --link jeecg-redis:jeecg-boot-redis \ -e SPRING_PROFILES_ACTIVE=prod \ jeecg-backend关键参数说明:
--link:建立容器间网络连接,使用服务别名SPRING_PROFILES_ACTIVE=prod:激活生产环境配置- 日志卷挂载:便于查看和分析日志
4. 前端服务与Nginx配置
4.1 前端项目构建
在本地开发环境构建前端项目:
cd jeecgboot-vue3 pnpm install pnpm run build将生成的dist目录内容上传到服务器的/opt/jeecg/frontend/dist目录。
4.2 Nginx容器配置
创建Nginx配置文件(/opt/jeecg/frontend/nginx.conf):
user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } 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 your-domain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /jeecg-boot { proxy_pass http://jeecg-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; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, no-transform"; access_log off; } } }运行Nginx容器:
docker run -d \ --name jeecg-nginx \ --restart unless-stopped \ -p 80:80 \ -p 443:443 \ -v /opt/jeecg/frontend/dist:/usr/share/nginx/html \ -v /opt/jeecg/frontend/nginx.conf:/etc/nginx/nginx.conf \ -v /opt/jeecg/frontend/ssl:/etc/nginx/ssl \ --link jeecg-backend:jeecg-backend \ nginx:1.235. 使用Docker Compose编排服务
为了简化管理,我们可以使用Docker Compose编排所有服务。创建docker-compose.yml文件:
version: '3.8' services: mysql: image: mysql:5.7 container_name: jeecg-mysql restart: unless-stopped ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: YourStrongPassword123 MYSQL_DATABASE: jeecg_boot MYSQL_USER: jeecg MYSQL_PASSWORD: jeecg123456 volumes: - /opt/jeecg/mysql/conf:/etc/mysql/conf.d - /opt/jeecg/mysql/data:/var/lib/mysql - /opt/jeecg/mysql/logs:/var/log/mysql command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci redis: image: redis:6.2 container_name: jeecg-redis restart: unless-stopped ports: - "6379:6379" volumes: - /opt/jeecg/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf - /opt/jeecg/redis/data:/data command: redis-server /usr/local/etc/redis/redis.conf --requirepass "YourRedisPassword123" --appendonly yes backend: build: ./backend container_name: jeecg-backend restart: unless-stopped ports: - "8080:8080" volumes: - /opt/jeecg/backend/logs:/app/logs environment: SPRING_PROFILES_ACTIVE: prod depends_on: - mysql - redis nginx: image: nginx:1.23 container_name: jeecg-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - /opt/jeecg/frontend/dist:/usr/share/nginx/html - /opt/jeecg/frontend/nginx.conf:/etc/nginx/nginx.conf - /opt/jeecg/frontend/ssl:/etc/nginx/ssl depends_on: - backend networks: default: name: jeecg-network使用以下命令启动所有服务:
docker-compose up -d6. 安全加固与性能优化
6.1 安全配置建议
- MySQL安全加固:
- 修改默认root密码
- 限制root用户只能本地登录
- 删除匿名用户
- 删除测试数据库
-- 进入MySQL容器后执行 ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPassword!123'; DELETE FROM mysql.user WHERE User=''; DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); DROP DATABASE IF EXISTS test; FLUSH PRIVILEGES;- Redis安全加固:
- 使用强密码
- 重命名危险命令
- 限制绑定IP
在redis.conf中添加:
rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command CONFIG "" bind 127.0.0.16.2 性能优化建议
- JVM调优: 根据服务器资源配置调整JVM参数:
ENV JAVA_OPTS="-Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2 -Dfile.encoding=UTF-8"- Nginx优化: 调整worker进程和连接数:
worker_processes auto; worker_rlimit_nofile 100000; events { worker_connections 4000; use epoll; multi_accept on; }- MySQL优化: 在
my.cnf中添加性能相关配置:
[mysqld] innodb_buffer_pool_size = 1G innodb_log_file_size = 256M innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT innodb_file_per_table = 1 innodb_thread_concurrency = 0 innodb_read_io_threads = 4 innodb_write_io_threads = 4 query_cache_type = 0 table_open_cache = 40007. 监控与日志管理
7.1 容器监控
使用cAdvisor+Prometheus+Grafana组合监控容器资源使用情况:
# 启动cAdvisor docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --volume=/dev/disk/:/dev/disk:ro \ --publish=8081:8080 \ --detach=true \ --name=cadvisor \ --restart unless-stopped \ gcr.io/cadvisor/cadvisor:v0.47.07.2 日志收集
配置ELK栈收集和分析日志:
# 示例Elasticsearch容器 docker run -d \ --name elasticsearch \ --restart unless-stopped \ -p 9200:9200 \ -p 9300:9300 \ -e "discovery.type=single-node" \ -v /opt/jeecg/elasticsearch/data:/usr/share/elasticsearch/data \ docker.elastic.co/elasticsearch/elasticsearch:7.17.77.3 健康检查
为关键服务添加健康检查:
# 在docker-compose.yml中为backend服务添加 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/jeecg-boot/sys/health"] interval: 30s timeout: 10s retries: 3