构建服务镜像和容器化部署
- 一、构建服务镜像
- 
- 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>
							
																								
						
