🍂Dockerfile自定义构建镜像+Docker插件实现远程部署springboot应用

发布于:2024-04-29 ⋅ 阅读:(23) ⋅ 点赞:(0)

Dockerfile构建镜像

Dockerfile构建镜像的流程

  • 首先,docker为CS架构(客户端-服务端),在虚拟机使用docker build, docker引擎会将Dockerfile的上下文目录(即Dockerfile所在的目录)的所有数据打包发送给docker服务端。
  • 接着,服务端开始运行dockerfile的内容,每执行dockerfile的一行代码,就会生成一个中间镜像层,当执行下一行代码时,就会生成一个在上一层基础上进行修改的中间镜像层,每一层都是在上一层的基础上进行修改而生成的,这也是为什么构建过程有"层叠"的概念。
  • 最后,当执行到最后一行,最后一次创建的中间镜像层就会成为最终镜像。它代表了 Dockerfile 中所有指令的执行结果和镜像的最终状态。
  • 注意:这些产生的中间镜像层(包括最终镜像)会被缓存到Docker本地镜像仓库里,如果不想要这些缓存,比如说想构建一个同名但是全新(可以理解dockerfile的代码发生变化)的镜像,就要在dockerbuild后加一个参数-no-cache,加了会忽略本地镜像缓存。

Dockerfile命令

FROM

  • Dockerfile的第一条指令必须为From,如果创建多个镜像在同一个dockerfile,就可以用多个FROM,一个FROM代表一个镜像。
  • 语法格式:
FROM 镜像名称
# 或者
FROM 镜像名称:版本号

MAINTAINER

  • 用于指定维护者信息,也可以叫作者信息
  • 语法格式:
MAINTAINER 维护者信息(eg:yourName  yourQQ@qq.com)

RUN

  • RUN 指令将在当前镜像基础上执行指定命令,并提交为新的中间镜像层,当命令较长时可以使用 \ 来换行
  • 语法格式:
RUN 执行的命令
#举例
RUN  echo 'Asia/Shanghai' >/etc/timezone

VOLUME

  • 基于镜像创建的容器添加数据卷,通过挂载将外部的目录或者其他容器的数据卷映射到该路径上,从而实现对数据的持久化
  • 语法格式:
VOLUME 外部路径:容器路径
#举例
VOLUME /tmp  
  • 举例中只写了一个路径的话就代表容器路径,会创建一个匿名卷挂载到容器的tmp目录,这样,容器中对 /tmp 目录的读写操作将直接映射到匿名卷上。
  • 默认情况下,Docker 会将匿名卷存储在位于宿主机的 /var/lib/docker/volumes/ 目录下。每个匿名卷都会以一个随机生成的唯一名称来标识,并在该目录下创建对应的子目录。

ADD

  • 将dockerfile所在目录中指定的文件复制到镜像的指定目录中
  • 同时可以识别远程URL,会自动下载URL对应的压缩包(不推荐使用)
  • 如果指定的文件是压缩包(如 .tar, .gz, .zip 等),会自动解压缩文件复制到镜像的指定目录中(单纯复制压缩包使用COPY指令)
  • 语法格式:
#格式1
ADD 外部文件路径  容器路径
#格式2(复制压缩包并重命名)
ADD 压缩包名字  重命名压缩包名字
#格式3(会自动解压缩)
ADD 压缩包名字  容器路径
#举例复制并重命名
ADD target/pms-boot.jar app.jar
#举例解压缩的情况
ADD my.zip  /data
  • 如果容器路径是一个具体的文件名而非目录名,那么外部文件会复制到镜像并重命名为该具体的文件名
  • 就是pms-boot.jar 复制过去后会重命名为app.jar ,该app.jar在镜像根目录。

COPY

  • 将dockerfile所在目录中指定文件复制到镜像的指定目录中
  • 语法格式
#shell格式
COPY 源路径 目标路径

ENTRYPOINT

  • 指定容器启动时执行的命令
  • 与CMD类似
  • 不会被docker run的命令覆盖,但是docker run后面加 --entrypoint参数就可以被覆盖
  • docker run后面有参数的话会传给entrypoint
  • 可以是Shell格式,也可以是exec格式
  • 语法格式
ENTRYPOINT 命令
#举例shell格式
ENTRYPOINT java -jar /app.jar
#举例exec格式
ENTRYPOINT ["java","-jar","/app.jar"]
#举例docker run 传参
ENTRYPOINT echo "hello"
docker run 镜像:版本 "world"
最后容器会执行 echo "hello" "world" 输出是"hello world"

CMD

  • 指定容器启动后默认执行的命令和参数
  • CMD 在 Dockerfile 中可以有多个,但只有最后一个 CMD 会生效。多个ENTRYPOINT的话每个都会执行的。
  • docker run后面如果有命令会覆盖dockerfile中CMD的命令
  • 语法格式
#shell格式(不能传参)
CMD  命令
#exec格式(有两种)
CMD ["可执行文件","参数1","参数2",...]
CMD ["参数1","参数2"](作为ENTRYPOINT的默认参数)
  • 可以与ENTRYPOINT结合使用:
    • 如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略(是结合的情况下会被忽略,如果cmd有可执行文件的话还是会执行)。
    • 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式,CMD指定的内容会被追加到ENTRYPOINT末尾当参数。
#举例1
ENTRYPOINT ["echo","hello"]
CMD ["world"]
最终会输出"hello world"
#举例2(当cmd的可执行文件跟entrypoint一样时就会传参,不一样就各自执行)
ENTRYPOINT["echo","hello"]
CMD ["echo","world"]
最终会输出"hello world"
#举例3
ENTRYPOINT["echo","hello"]
CMD ["world"]
dokcer run 镜像:版本 "china"
最终会输出"hello china"

WORKDIR

  • 指定容器工作目录,容器内没有指定的路径时会创建该路径
  • 语法格式
WORKDIR 容器路径
  • 直接看个例子就明白了
WORKDIR /app
RUN touch file1.txt
WORKDIR subdir
RUN touch file2.txt
WORKDIR /data
RUN touch file3.txt
  • 首先设置了工作目录为 /app,然后在 /app 目录下创建了一个文件 file1.txt。
  • 接着 WORKDIR subdir 命令将当前的工作目录更改为 /app/subdir,然后在该目录下创建了文件 file2.txt。
  • 最后,WORKDIR /data 将工作目录更改为 /data,并在该目录下创建了文件 file3.txt。

USER

  • 指定镜像会以什么样的用户去运行,不指定默认容器会使用root用户来运行。
  • 注意:如果使用不存在的 用户或用户id,Docker 构建过程将会报错。
  • 语法格式
USER 用户名/用户id

ENV

  • 设置环境变量,这个环境变量在构建过程中和运行过程中都是有效的。比如说配置JDK环境
  • 语法格式
#格式1
ENV key=value
#格式2
ENV key value
#格式3(允许在多行上设置环境变量。使用 \ 进行换行)
ENV <key>=<value>  \
<key>=<value> \

#举例
ENV JAVA_HOME /usr/local/jdk1.8.0_121

ONBUILD

  • 在构建镜像的过程中设置一个触发器。这个触发器将在其他镜像继承(通过 FROM)当前镜像并构建新镜像时触发。
  • 语法格式
ONBUILD 命令
#举例
ONBUILD COPY . /app
ONBUILD RUN make /app
    • 这个例子ONBUILD 指令设置了两个触发器。当其他镜像继承(通过 FROM)当前镜像并构建新镜像时,将会按顺序执行这两个触发器。
    • 在继承当前镜像的新镜像的构建过程中,首先会复制当前工作目录中的所有文件到新镜像的 /app 目录中,然后通过 make 命令在 /app 目录中运行构建。

EXPOSE

  • 声明(暴露的意思)运行时容器提供服务端口,仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。,它并不会实际上打开或监听端口。
  • 要容器内的服务可以让外部访问,您需要将容器内部的端口映射到主机上。这可以通过 Docker 命令行的 -p 或者 -P 参数来实现。
  • 语法格式:
EXPOSE 端口1 端口2 ...

实战dockerfile自定义镜像

定义dockefile

FROM openjdk:8-jre
MAINTAINER whisper yourQQ@qq.com

RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

# /tmp 目录作为容器数据卷目录,SpringBoot内嵌Tomcat容器默认使用/tmp作为工作目录,任何向 /tmp 中写入的信息不会记录进容器存储层,从而保证容器存储层的无状态化
# 在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录
VOLUME /tmp
#app.jar是自己命名的
ADD target/whisper-gateway.jar app.jar

ENTRYPOINT ["java","-Xmx128m","-Djava.security.egd=file:/dev/./urandom","-Dcsp.sentinel.app.type=1","-jar","/app.jar"]

EXPOSE 9999
  • 基础镜像选openjdk:8-jre(如果您的项目需要进行编译和打包操作,建议选择jdk。如果您只需运行已编译好的 Java 代码,可以选择jre)
  • 容器建立时运行cp指令,设置容器时区为当前时区
    • /usr/share/zoneinfo/Asia/Shanghai:操作系统中自带的时区文件
    • /etc/localtime :是容器自带的文件,/etc/localtime 文件是随着容器启动在容器内部创建的,它是通过复制来自主机操作系统的对应时区文件来初始化的。
  • 创建一个匿名卷挂载到容器的tmp目录,这样容器中对 /tmp 目录的读写操作将直接映射到匿名卷上。
  • 复制jar到镜像并重命名为app.jar
  • ENTRYPOINT
    • java:运行 Java 程序
    • -Xmx128m:设置 Java 虚拟机的最大堆内存为 128MB
    • -Djava.security.egd=file:/dev/./urandom:设置随机数生成器的算法为 /dev/./urandom,以提高随机性和性能
    • -Dcsp.sentinel.app.type=1:设置 Sentinel 应用程序的类型为 1。
    • -jar:指定要运行的 JAR 文件
    • /app.jar:指定要运行的 JAR 文件的路径。
  • 暴露端口9999

应用部署

下载Docker插件

配置pom.xml文件
  • 添加 spring-boot-maven-plugin 依赖
  • 指定 finalName 不带版本号的话,打包出的 jar 包名称就没有版本号
<build>
   <finalName>${project.artifactId}</finalName>
   <plugins>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
         <version>${spring-boot.version}</version>

         <configuration>

            <excludes>
               <!-- 打包忽略lombok(作用于编译阶段)-->
               <exclude>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
               </exclude>
            </excludes>

         </configuration>
      </plugin>
   </plugins>
</build>
Run/Debug Configurations 配置

  • Name:填写容器名
  • Server:选择你的docker容器(点击右边三个点)

  • Dockerfile:你的dockerfile文件路径
  • image tag:镜像名字:版本
  • container name:容器名字,当你用docker start 后面的容器名就是这个
  • Run option: 类似docker run 后面加的参数.
  • Before launch:程序执行前执行脚本

启动


网站公告

今日签到

点亮在社区的每一天
去签到