构建服务镜像和容器化部署
- 一、构建服务镜像
-
- 1、编写Dockerfile
- 2、构建脚本
- 3、启动脚本
- 二、问题及解决办法
-
- 1、no main manifest attribute, in /chatgpt-api-1.0-SNAPSHOT.jar
- 2、如果是SpringBoot项目,应该这么做:
一、构建服务镜像
1、编写Dockerfile
- 在项目的根目录下,创建Dockerfile
- 基础写法:
FROM openjdk:8-jre-slim MAINTAINER Forrest ENV PARAMS="" TZ=PRC RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone ADD target/chatgpt-api-1.0-SNAPSHOT.jar /chatgpt-api-1.0-SNAPSHOT.jar ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /chatgpt-api-1.0-SNAPSHOT.jar $PARAMS"]
- 对上面的每一行进行详细说明:
(1)
基础镜像 【这个镜像包含了 OpenJDK 8 (Java 运行环境)和一个精简版的操作系统。】
(2)
镜像的作者
(3)
1)设置环境变量
2)PARAMS表示传给main方法的参数。这个PARAMS就相当于public static void main(String[] args) {...} 的args。
3)当运行 Docker 容器时,可以通过 -e 参数来覆盖这个环境变量的值,例如:docker run -e PARAMS=“arg1 arg2 arg3” your-image-name。这样,你的 Java 应用启动时就会接收到 “arg1 arg2 arg3” 这些参数,作为 main 方法的参数(args)来使用。
4)TZ表示时区, 设置时区为中国(People’s Republic of China,RPC)
(4)
1)这行命令主要是用于设置 Docker 容器内的系统时区。
2)ln 是 Linux 系统中用于创建符号链接(symbolic link)的命令,-s 表示创建软链接,-n 表示如果目标文件已存在,直接覆盖,-f 表示强制执行。所以,ln -snf /usr/share/zoneinfo/$TZ /etc/localtime 这条命令的意思是创建一个指向 /usr/share/zoneinfo/$TZ 的链接 /etc/localtime。
在macOS上,查看下
继续查看下
很显然,这不是中国时区,因此,为了保险起见,
echo $TZ > /etc/timezone 把/etc/timezone改为中国时区。
(5)
- 因此,这条命令是把上下文路径(一般是Dockerfile所在的根目录)的target目录下的chatgpt-api-1.0-SNAPSHOT.jar,添加到根目录下。
(6)
这个命令分解如下:
“sh”:表示使用 shell 环境。用于执行后面跟随的命令。
“-c”:这是传递给 sh 的一个选项,表示后面的字符串是一个需要被 sh 执行的命令。
相当于,在命令行,执行java -jar $JAVA_OPTS /chatgpt-api-1.0-SNAPSHOT.jar $PARAMS
2、构建脚本
IDEA支持通过可视化的方式构建镜像:
- 但用shell脚本的方式更灵活,在Dockerfile同一目录下,创建build.sh,代码为:
docker build -f ./Dockerfile -t forrest/chatgpt-api .
(1)
docker build :docker构建镜像的命令
(2)-f ./Dockerfile :选择用于构建镜像的Dockerfile文件
(3)-t forrest/chatgpt-api :镜像的名字,开头必须是小写 。
(4). : 上下文路径(一般是Dockerfile所在的根目录)
3、启动脚本
- 构建好了后,以本地容器的方式启动,启动脚本
start.sh ,代码为:
docker run -p 8080:8080 --name chatgpt-api -d forrest/chatgpt-api
二、问题及解决办法
1、no main manifest attribute, in /chatgpt-api-1.0-SNAPSHOT.jar
<build> <plugins> <plugin> <!-- Build an executable JAR --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <!-- 包含"public static void main(String[] args)"的类 --> <mainClass>com.forrest.learnChatgpt.Application</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build>
解决办法
- 局限性:如果是SpringBoot项目,上面这种做法会导致新问题,即
java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
2、如果是SpringBoot项目,应该这么做:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>