构建服务镜像和容器化部署
- 一、构建服务镜像
- 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)FROM openjdk:8-jre-slim
基础镜像 【这个镜像包含了 OpenJDK 8 (Java 运行环境)和一个精简版的操作系统。】
(2)MAINTAINER Forrest
镜像的作者
(3)ENV PARAMS="" TZ=PRC
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)RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
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上,查看下/usr/share/zoneinfo/RPC
和/etc/localtime
:
继续查看下/etc/timezone
:
很显然,这不是中国时区,因此,为了保险起见,
echo $TZ > /etc/timezone
把/etc/timezone改为中国时区。
(5)ADD target/chatgpt-api-1.0-SNAPSHOT.jar /chatgpt-api-1.0-SNAPSHOT.jar
- 因此,这条命令是把上下文路径(一般是Dockerfile所在的根目录)的target目录下的chatgpt-api-1.0-SNAPSHOT.jar,添加到根目录下。
(6)ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /chatgpt-api-1.0-SNAPSHOT.jar $PARAMS"]
这个命令分解如下:
“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>