文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Dockerfile中编译、打包、部署spring boot项目

2023-09-05 19:50

关注

1、Dockerfile

1.1、什么是Dockerfile

        Dockerfile是自动构建docker镜像的配置文件,将镜像构建过程通过指令的方式定义在Dockerfile中。配合docker build命令行可以实现自动化的Docker镜像的构建。

1.2、Dockerfile语法解析

        我们在学习一门语言或文档语法的时候,最快的学习方式就是看别人是怎么写的。这里这个“「别人」”是谁就很重要,跟着臭棋篓子下棋越下越臭。

        所以学习Dockerfile语法,我们有必要找一个模范:大家可以去Dockerhub看一下那些开源软件官方提供的镜像,都可以找到对应的Dockerfile,看看别人是怎么写的。我们就以上文中的nginx:1.20.2版本docker镜像的Dockerfile( 官方提供的),我们来逐行解析它的语法及构建过程。本文中涉及的脚本都可以在github:docker-nginx官方渠道获取。

1.3、Dockerfile命令

FROM

        一般我们构建镜像的都需要一个基础的linux操作系统的发行版镜像,并且在此基础上我们构建自己的镜像。
        所以FROM指令的作用就是指定基础镜像,nginx这里使用的基础linux镜像是debian:bullseye-slim。其中debian:bullseye是debian的linux发行本操作系统的一个版本,版本名称叫做bullseye。slim通常是指这个镜像是该发行版本中的最小安装版本,因为我们构建完成的镜像是要在后续的持续集成过程中,以及仓库和docker服务器之间网络传播的,所以尽可能让镜像的构建结果size最小化。「基础镜像的选择要着重考虑size的大小,满足linux基本功能及你的程序运行的前提下越小越好」

FROM debian:bullseye-slim

LABEL

        LABEL用于给当前镜像添加一些描述、解释性信息,如:当前镜像的维护人及联系方式等信息。用键值对的方式自定义,一行可以定义多个。

LABEL = = = ...

maintainer、description

        也可以定义多行,如maintainer维护人信息,description镜像描述信息。如果描述信息一行写不下,可以用“\”换行。

LABEL maintainer="NGINX Docker Maintainers "LABEL description="This is a Docker image \for nginx 1.20.2. "

        Dockerfile语法中有一个指令叫做MAINTAINER,用于描述该镜像的维护人信息,但是现在已经不建议使用了,统一使用LABEL。

ENV

        ENV的作用是设置环境变量,该环境变量设置之后,可以在shell脚本中使用。

        使用方法如:${NGINX_VERSION}。学过JAVA的同学想想你的JAVA_HOME环境变量怎么设置的以及怎么使用的?ENV是同样的道理。只不过放到docker这里语法发生了变化而已,语法格式:ENV 环境变量KEY 环境变量Value。

ENV NGINX_VERSION 1.20.2ENV NJS_VERSION 0.7.0ENV PKG_RELEASE 1~bullseye

RUN

        RUN指令的作用就是执行linux的shell脚本,通过下图可以看到在shell脚本中可以使用通过ENV定义的环境变量。
        对于nginx镜像而言,RUN指令的作用就是执行一系列shell命令行来(脚本)完成nginx的安装。所以说要想掌握RUN指令的重点不在于RUN指令本身,关键在于:

        如果上面三个问题的答案都是肯定的,用RUN指令即可执行shell脚本完成软件的安装。这也是Dockerfile编写内容的核心所在,linux shell并不是本文要为大家说明的内容。


COPY

        COPY指令的作用是:将本地文件(执行镜像构建所在的服务器),拷贝到镜像文件中。

        语法是:COPY <本地文件路径>:<镜像文件路径>,镜像文件路径也是容器运行时文件系统的路径。

COPY docker-entrypoint.sh /COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.dCOPY 20-envsubst-on-templates.sh /docker-entrypoint.dCOPY 30-tune-worker-processes.sh /docker-entrypoint.d

        如果本地文件路径只有文件名,就是表示文件和Dockerfile在同一个目录下(相对路径语法)。即:下面的这些文件在同一个目录,这些文件在我上文给出的nginx官方Dockerfile连接中都可以看到。

        注意:如果<本地文件路径>是目录,则只是拷贝目录内部文件到镜像中,而不是拷贝目录。

WORKDIR

        另外可以使用WORKDIR 指令为 Dockerfile 中跟随它的任何 RUN、CMD、ENTRYPOINT、COPY、ADD 指令设置本地工作目录。

        这样上文提到的相对路径,就是相对WORKDIR指定路径的相对路径。「但是通常情况下,不建议使用WORKDIR,因为很难保证执行构建的开发者工作主机的工作路径和Dockerfile编写者的工作路径都是一致。」

WORKDIR  /root

EXPOSE

Docker 容器在运行时暴漏指定的网络端口,可用于容器端口映射,默认协议是 TCP。格式如下:

EXPOSE <端口号>EXPOSE <端口号>/<协议>

        将容器端口暴露出去后,可以与宿主机的端口建立映射关系,这样可以通过访问宿主机的端口来访问容器内部的服务。比如同时在 TCP、UDP 上暴露容器的80端口。

EXPOSE 80/tcpEXPOSE 80/udp

STOPSIGNAL

        这个指令笔者也并不常用,我查询了docker-nginx在github上的issues里面给出的答案是,之所以加上STOPSIGNAL信号的目的是:避免docker容器停止后,nginx服务不能正确终止造成僵尸进程的存在。

STOPSIGNAL SIGQUIT

CMD

        CMD指令也是用来执行linux命令或脚本,这一点和RUN指令是一致的。二者的区别在于:

  1. RUN指令实在镜像构建的时候执行,即docker bulid时候执行
  2. CMD指令是在执行docker run指令时被执行,也就是在创建容器时执行

        也正因为指令的执行期不同,RUN命名执行的写入操作被写入到镜像层。CMD指令执行结果包含写入操作,被写入到容器层。(可以参考我之前文章《镜像分层原理》学习理解)。
        所以CMD和ENTRYPOINT 指令有点相似,都是在创建容器时运行。

        需要注意的是:「一旦Dockerfile中包含ENTRYPOINT指令,CMD指令就作为ENTRYPOINT指定的脚本的参数存在」。

参考下文格式语法。

CMD包含三种格式:

CMD ["nginx", "-g", "daemon off;"]

CMD ["executable","param1","param2"]

CMD echo "This is a test." | wc -c
 

ENTRYPOINT

        一个Dockerfile中如果定义多个ENTRYPOINT,只有最后一条ENTRYPOINT生效,并且每次启动docker容器,都会执行ENTRYPOINT指定的脚本。

        对于nginx:1.20.2而言,"/docker-entrypoint.sh"脚本中定义了nginx配置检查及nginx服务的启动指令。所以通常情况下「ENTRYPOINT指定的脚本通常都是镜像内核心服务的启动脚本」。

ENTRYPOINT ["/docker-entrypoint.sh"]

        这个脚本中最后执行了nginx服务启动,需要配合CMD命令完成,参考下文的CMD命令。

1.4、docker操作

具体可以参考:3-docker基础操作命令 · linux运维 · 看云


1.生成镜像

# docker build -t springboot-docker .
# docker build -f ./Dockerfile -t springboot-docker  .
# docker build -f ./Dockerfile -t springboot-docker:0.1  .

[root@ip-100 dockerfile]# docker images
REPOSITORY          TAG       IMAGE ID       CREATED              SIZE
springboot-docker   0.1       54dcc83613d7   About a minute ago   682MB
springboot-docker   latest    54dcc83613d7   About a minute ago   682MB


# 注意:
#    1,命令是在 Dockerfile 所在目录执行;
#    2,一定不能忘了后面的. 此处的 springboot-docker 是实际生成的镜像名

参考: https://www.runoob.com/docker/docker-build-command.html

2.运行镜像

最后一个字段为镜像名称

# docker run --name springboot-docker01 -d -p 8080:8080 springboot-docker

[root@ip-100 dockerfile]# docker ps 
CONTAINER ID   IMAGE  COMMAND   CREATED  STATUS   PORTS    NAMES
65bb62a54e55   springboot-docker   "java -Djava.securit…"   33 seconds ago   Up 31 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   springboot-docker01

宿主机浏览器: http://192.168.192.128:8080/getIpAndPort


3.查看启动日志

docker logs xxx
docker logs -f springboot-docker01

2、Dockerfile多阶段构建

2.1、使用Dockerfile的示例1

FROM openjdk:8-jdk-alpine as buildWORKDIR /workspace/appCOPY mvnw .COPY .mvn .mvnCOPY pom.xml .COPY src srcRUN ./mvnw install -DskipTestsRUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)FROM openjdk:8-jdk-alpineVOLUME /tmpARG DEPENDENCY=/workspace/app/target/dependencyCOPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/libCOPY --from=build ${DEPENDENCY}/META-INF /app/META-INFCOPY --from=build ${DEPENDENCY}/BOOT-INF/classes /appENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

2.2、使用Dockerfile的示例2

在项目根目录创建Dockerfile:

# 拉取编译环境FROM maven:3.6.1 as builder#拷贝源码到固定的目录,注意前面有个 '.'COPY . /project# 切换到源码目录WORKDIR /project# 使用maven进行编译RUN mvn clean package -Dmaven.test.skip=true# 拉取运行环境,这个镜像打包出的镜像比较小,如需要可换成oracle的jreFROM fabric8/java-alpine-openjdk8-jre# 从编译好的镜像中将jar拷贝到运行时容器COPY --from=builder /project/target/your-jar-name.jar /# 容器启动时执行的命令,这里可加jvm参数ENTRYPOINT ["java","-jar","/mqtt-rule-engine.jar"]# 开放端口,根据自己的配置进行开放EXPOSE 8080

2.3、使用Dockerfile的示例3

# First stage: complete build environmentFROM maven:3.5.0-jdk-8-alpine AS builder# add pom.xml and source codeADD ./pom.xml pom.xmlADD ./src src/# package jarRUN mvn clean package# Second stage: minimal runtime environmentFrom openjdk:8-jre-alpine# copy jar from the first stageCOPY --from=builder target/my-app-1.0-SNAPSHOT.jar my-app-1.0-SNAPSHOT.jarEXPOSE 8080CMD ["java", "-jar", "my-app-1.0-SNAPSHOT.jar"]
FROM maven:3.6.3-openjdk-8 AS builder #  AS builder 起别名RUN mkdir /build# 创建临时文件ADD src /build/src#将 src目录复制到临时目录ADD pom.xml /build# 将 pom文件复制到临时目录RUN cd /build && mvn -B -ntp package# 打包FROM adoptopenjdk/openjdk8:alpine-jre# 获取jreCOPY --from=builder /build/target/ems-0.0.1-SNAPSHOT.jar /ems.jar#从标记点 拷贝jar包 并改名CMD ["java", "-jar", "/ems.jar"]# 声明运行方式

 在项目根目录执行下面命令

docker build -t name:tag .
 

3、插件打包

3.1、spring-boot-maven-plugin插件打包

SpringBoot自己内置了一个Docker镜像打包工具,在spring-boot-starter-parent中,我们无需多余的设置。 优点:不需要写DockerFile,Spring建议的安全、内存、性能等问题都不需要管。

3.2、jib-maven-plugin插件

来自Google的一款打包插件。 优点:不需要本地安装Docker,也不需要写DockerFileJib 可以直接推送到指定的Docker仓库。

3.3、dockerfle-maven-plugin插件

需要写DockerFile也需要本地Docker环境,但是恰恰是最好用的,最稳定的,最自由把控的。 优点:稳定,不受网络限制,DockerFile自己写,自由度很高,想怎么改怎么改,个人推荐这个。

插件打包,具体例子可参考:Java(SpringBoot)项目打包(构建)成Docker镜像的几种方式-腾讯云开发者社区-腾讯云

4、参考:

docker编译Dockerfile自动化部署springboot项目的jar包_dockerfile编译jar包_xixiyuguang的博客-CSDN博客

2021年 最新 多阶段构建dockerfile实现java源码编译打jar包并做成镜像-阿里云开发者社区

Java(SpringBoot)项目打包(构建)成Docker镜像的几种方式-腾讯云开发者社区-腾讯云

在docker中编译、打包、部署spring boot项目_docker 部署时编译_csdn_meng的博客-CSDN博客

来源地址:https://blog.csdn.net/yangyangye/article/details/132622061

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯