docker 部署 java 项目详解
在平常的开发工作中,我们经常需要部署项目,开发测试完成后,最关键的一步就是部署。今天我们以若依项目为例,总结下部署项目的整体流程。简单来说,第一步:安装项目所需的中间件;第二步:将项目打包成 jar 包;第三步:编写 Dockerfile 文件,构建镜像;第四步:编写 docker-compose.yml 文件;第五步:编写 nginx.conf 文件;第六步:启动项目,进行测试。
1:安装项目所需中间件
项目部署依赖的中间件,如数据库 mysql 、缓存 redis、负载均衡 nginx 等,这些中间件的安装就不在这儿一 一赘述了。如果有不清楚的小伙伴,可以看我之前写的几篇博客,如下:
安装 mysql:docker 安装 mysql 详解-CSDN博客
安装 redis:docker 安装 redis 详解-CSDN博客
安装 nginx:docker 安装 nginx 详解-CSDN博客
2:将项目打成 jar 包
部署不同的环境,需要选择不同的配置文件,部署测试环境一般选择 application-test.yml 文件打包,部署生产环境一般选择 application-prod.yml 文件。打 jar 包时一定注意本地修改不需要提交的配置,先回滚,然后拉取最新的代码,点击 maven clean,然后点击 package 打包,打包完后在 target 目录。将 jar 包上传到服务器指定的目录。
注意:比如在服务器上新建一个 /docker/ruoyi/ 的目录,那么 jar 包放在这个目录下,在这个目录下再新建 Dockerfile 文件 和 docker-compose.yml 文件,如下所示:
3:编写 Dockerfile 文件,构建镜像
Dockerfile文件示例:
# 使用OpenJDK 17基础镜像
FROM openjdk:17
# 创建一个名为/ruoyi/logs的目录
RUN mkdir -p /ruoyi/logs
# 切换工作目录
WORKDIR /ruoyi
# 配置环境变量
ENV SERVER_PORT=8008 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8
# 暴露应用端口
EXPOSE 8008
# 添加应用Jar包到容器中
ADD ruoyi-admin.jar ./app.jar
# 设置启动命令
ENTRYPOINT ["java", \
"-Dserver.port=${SERVER_PORT}", \
"-Xlog:gc*:time,tags,level", \
"-XX:+UseZGC", \
"-jar", "app.jar"]
Dockerfile文件内容释义:
1):FROM openjdk:17: 使用OpenJDK 17基础镜像
2):RUN mkdir -p /ruoyi/logs:创建一个名为/ruoyi/logs的目录,即日志目录
3):WORKDIR /ruoyi:切换工作目录
4):ENV SERVER_PORT=8008 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8
配置环境变量,Docker 镜像构建时设置了三个环境变量,分别是服务端口和字符编码相关的环境变量,LANG=C.UTF-8 和 LC_ALL=C.UTF-8:这两个环境变量用于设置字符编码和语言环境,\ 末尾的反斜杠 \ 是行延续符,表示下一行是当前命令的延续
5):EXPOSE 8008:暴露8008端口
6):ADD ruoyi-admin.jar ./app.jar:
添加应用Jar包到容器中,ADD:这是 Dockerfile 里用于复制文件和目录的指令,ruoyi-admin.jar:这是位于宿主机上的源文件路径,./app.jar:这是目标路径,指定将源文件复制到 Docker 镜像中的位置和文件名。./ 表示镜像中的当前 # 工作目录,将源文件 ruoyi-admin.jar 复制到镜像的当前工作目录下,并命名为 app.jar
7):ENTRYPOINT ["java", \
"-Dserver.port=${SERVER_PORT}", \
"-Xlog:gc*:time,tags,level", \
"-XX:+UseZGC", \
"-jar", "app.jar"]
a:ENTRYPOINT 关键字:这是 Dockerfile 里用来定义容器启动命令的指令。
b:"java":表明要执行的是 Java 虚拟机。
c:"-Dserver.port=${SERVER_PORT}":设置 Java 虚拟机的系统属性。server.port 通常用于指定 Spring Boot 应用程序监听的端口,#${SERVER_PORT} 是一个环境变量引用,其值在之前的 ENV 指令中设置为 8008,这意味着应用程序会监听 8008 端口。
d:"-Xlog:gc*:time,tags,level":开启 Java 垃圾回收(GC)日志记录功能。gc* 表示记录所有与垃圾回# 收相关的事件,time,tags,level 表示日志中要包含时间、事件标签和日志级别等信息。
e:"-XX:+UseZGC":启用 Z Garbage Collector(ZGC),这是 Java 11 及以上版本引入的一种可扩展的低# 延迟垃圾回收器,能显著减少垃圾回收停顿时间。
f:"-jar":告诉 Java 虚拟机要执行一个 JAR 包,"app.jar":指定要执行的 JAR 包名称,这个 JAR 包是之前使用 ADD 或 COPY 指令复制到镜像中的。
编写完 Dockerfile 文件后,这个时候就可以构建镜像了,命令:docker build -t 镜像名称:镜像版本 . ,如 docker build -t ruoyi:v1.0 . 注意版本后面有个 空格 点。使用点 . :表示使用当前目录下的 Dockerfile,如果不加这个点,Docker 不会知道从哪里获取 Dockerfile。镜像构建完成后,可以使用 docker images 查看生成的镜像:
4:编写 docker-compose.yml 文件
docker-compose.yml 文件示例:
services:
ruoyi-admin:
image: ruoyi-admin:v1.0
container_name : ruoyi-admin
environment:
- SERVER_PORT=8008
# 可选,Java 启动参数
- JAVA_OPTS="-Xmx2g -Xms2g"
- TZ=Asia/Shanghai
restart: always
network_mode: "host"
docker-compose.yml 文件内容释义:
1):image: ruoyi-admin:v1.0:服务会使用ruoyi-admin:v1.0镜像来创建容器
2):container_name:容器名称
3):SERVER_PORT=8008:定义环境变量
4):- JAVA_OPTS="-Xmx2g -Xms2g":可选参数,-Xmx用来设定 JVM 堆内存的最大使用量;-Xms用于设置 JVM 堆内存的初始使用量。JAVA_OPTS="-Xmx2g -Xms2g" 把 JVM 堆内存的初始大小和最大大小都设置为 2GB。这么做可以避免在应用程序运行过程中频繁进行堆内存的扩容和缩容操作,从而提升性能。不过,设置时要依据应用程序的实际内存需求和服务器的可用内存来合理调整,防止出现内存不足或者浪费的情况。
5):- TZ=Asia/Shanghai:把容器内的时区指定为 Asia/Shanghai(即上海所在的时区,也就是中国标准时间,UTC+8)。这样容器内运行的应用程序所显示和处理的时间会UTC+8时区处理。
6):restart: always:为容器指定了一种重启策略,确保容器在各种情况下都能尽可能保持运行状态。当容器由于各种原因(如正常退出、异常崩溃、宿主机重启等)停止运行时,Docker 会依据此策略自动尝试重启容器。
除了always,还有其他几种重启策略:
no:默认策略,容器停止后不会自动重启。
on-failure:只有当容器以非零退出码退出时,Docker 才会尝试重启它。可以通过 on-failure: N 的形式指定最多重启 N 次。
unless-stopped:容器停止后,除非手动停止(如使用 docker stop 命令),否则 Docker 会在 Docker 守护进程重启或宿主机重启后自动重启容器。
7):network_mode: "host":指定容器使用宿主机的网络,即容器直接使用宿主机的网络接口,而非创建独立的 Docker 网络。
5:配置 nginx.conf
nginx.conf 文件示例:
user nginx;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 60;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
proxy_pass http://localhost:8008;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
6:启动项目,测试
1):进入 /doker/ruoyi/ 目录下,即 docker-compose.yml 文件目录,使用 docker compose up -d 命令启动容器,启动完成后可以使用 docker ps 命令查看启动的容器,信息如下:
使用 docker logs -f 容器id 查看启动日志,启动成功:
2):访问系统,nginx 配置监听 80 端口,所以访问地址为:http:ip地址:80,访问成功,页面如下:
可能会遇到的问题:项目启动成功,访问失败,可以查看项目端口是否因没开防火墙导致无法访问。如果是,解决步骤如下:
1):查看防火墙开的端口:firewall-cmd --zone=public --list-ports
2):若端口未开,则添加,比如开放 8008 端口:firewall-cmd --zone=public --add-port=8008/tcp --permanent
3):修改完成后,重启防火墙:firewall-cmd --reload
以上为 docker 部署项目的基本步骤。主要是Dockerfile文件的编写,第一次构建镜像比较慢,因为要下载依赖的基础镜像,只需耐心等待即可。Dockerfile文件有问题,会导致构建镜像失败。构建完成后,可以使用 docker images 查看构建的镜像。启动容器可以直接使用 docker run 命令后面跟启动参数启动,这样做不好的地方每次启动项目,都要输入一 长串命令,不便于使用,在docker-compose.yml文件里面编写启动命令,可以更好的管理启动命令,所以推荐使用docker-compose.yml文件方式。在项目目录使用 docker compose up -d 命令启动就可以,docker compose up -d,带上 -d 是非阻塞的,不阻塞当前的命令窗口。使用 docker logs -f 容器id 或者 容器名称 可以查看启动日志。