docker编译Dockerfile自动化部署springboot项目的jar包

文章目录

  • docker file学习
    • 什么是Dockerfile
    • Dockerfile语法解析
      • FROM
      • LABEL
      • ENV
      • RUN
      • COPY
      • ENTRYPOINT
      • EXPOSE
      • STOPSIGNAL
      • CMD
    • dockerfile案例
      • 构造一个springboot的jar包
      • 创建一个目录,新增dockerfile
      • Dockerfile内容
      • 打包命令docker build
      • 自定义命令脚本
      • jdk安装
      • maven安装
      • 重启脚本解读 restart.sh
      • Dockerfile

docker file学习

我一直觉得学习程序最快的方式就是:「首先自学一些基本概念,然后去看看大牛是怎么写代码的,通过模仿大牛的写法然后领悟,是学习编程最快的方法」。可能有的朋友会说:哪有那么多大牛的代码给你看啊,请去github上面有很多的开源组织官方代码。我们学习Dockerfile也不例外,尽量使用官方资源去学习,看看人家是怎么写的,此文就和大家一起逐行解析nginx官方的镜像构建文件Dockerfile。

什么是Dockerfile

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

Dockerfile语法解析

我们在学习一门语言或文档语法的时候,最快的学习方式就是看别人是怎么写的。这里这个“「别人」”是谁就很重要,跟着臭棋篓子下棋越下越臭。所以学习Dockerfile语法,我们有必要找一个模范:大家可以去Dockerhub看一下那些开源软件官方提供的镜像,都可以找到对应的Dockerfile,看看别人是怎么写的。我们就以上文中的nginx:1.20.2版本docker镜像的Dockerfile( 官方提供的),我们来逐行解析它的语法及构建过程。本文中涉及的脚本都可以在github:docker-nginx官方渠道获取。

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 <key>=<value> <key>=<value> <key>=<value> ...
也可以定义多行,如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.2
ENV NJS_VERSION 0.7.0
ENV PKG_RELEASE 1~bullseye

RUN

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

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

COPY

COPY指令的作用是将本地文件(执行镜像构建所在的服务器),拷贝到镜像文件中。语法是:COPY <本地文件路径>:<镜像文件路径>,镜像文件路径也是容器运行时文件系统的路径。

COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
如果本地文件路径只有文件名,就是表示文件和Dockerfile在同一个目录下(相对路径语法)。即:下面的这些文件在同一个目录,这些文件在我上文给出的nginx官方Dockerfile连接中都可以看到。

另外可以使用WORKDIR 指令为 Dockerfile 中跟随它的任何 RUN、CMD、ENTRYPOINT、COPY、ADD 指令设置本地工作目录。这样上文提到的相对路径,就是相对WORKDIR指定路径的相对路径。「但是通常情况下,不建议使用WORKDIR,因为很难保证执行构建的开发者工作主机的工作路径和Dockerfile编写者的工作路径都是一致。」

WORKDIR  /root

ENTRYPOINT

一个Dockerfile中如果定义多个ENTRYPOINT,只有最后一条ENTRYPOINT生效,并且每次启动docker容器,都会执行ENTRYPOINT指定的脚本。对于nginx:1.20.2而言,"/docker-entrypoint.sh"脚本中定义了nginx配置检查及nginx服务的启动指令。所以通常情况下「ENTRYPOINT指定的脚本通常都是镜像内核心服务的启动脚本」。

ENTRYPOINT ["/docker-entrypoint.sh"]
这个脚本中最后执行了nginx服务启动,需要配合CMD命令完成,参考下文的CMD命令。

EXPOSE

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

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

EXPOSE 80/tcp
EXPOSE 80/udp

STOPSIGNAL

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

STOPSIGNAL SIGQUIT

CMD

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

CMD指令是在执行docker run指令时被执行,也就是创建容器时执行;而RUN指令实在镜像构建的时候执行,即docker bulid时候执行。
也正因为指令的执行期不同,RUN命名执行的写入操作被写入到镜像层。CMD指令执行结果包含写入操作,被写入到容器层。(可以参考我之前文章《镜像分层原理》学习理解)。
所以CMD和ENTRYPOINT 指令有点相似,都是在创建容器时运行。需要注意的是:「一旦Dockerfile中包含ENTRYPOINT指令,CMD指令就作为ENTRYPOINT指定的脚本的参数存在」。参考下文格式语法。
CMD包含三种格式:

第一种为ENTRYPOINT指定的脚本传参,上文中的ENTRYPOINT脚本最后一行的exec "$@"就是在执行CMD传递的命令及参数。来完成nginx服务的启动。**这种用法是各官方Dockerfile常用的做法(如:nginx、redis)**,就是在ENTRYPOINT指定的脚本中做一些配置准备工作,然后在ENTRYPOINT脚本的最后一行通过exec "$@"调用CMD命令进行容器服务的启动。
CMD ["nginx", "-g", "daemon off;"]
第二种 执行一个命令或shell脚本,可以传参,注意是双引号。与第一种格式语法是一样的,只是没有ENTRYPOINT指定脚本,所以不作为ENTRYPOINT指定脚本的参数存在。
CMD ["executable","param1","param2"]
第三种为普通的执行shell脚本的语法,如执行echo "This is a test." | wc -cshell命令行。笔者说:「在Dockerfile中这种方法不要用,没必要知道为什么」。
CMD echo "This is a test." | wc -c

dockerfile案例

构造一个springboot的jar包

创建一个目录,新增dockerfile

[root@ip-100 dockerfile]# pwd
/root/dockerfile
[root@ip-100 dockerfile]# ls
Dockerfile  springboot-docker.jar
[root@ip-100 dockerfile]# 

Dockerfile内容

# FROM命令定义构建镜像的基础镜像,必须是Dockerfile的首个命令
FROM java:8
 
# 用于指定持久化目录
VOLUME /temp
 
# 将本地文件添加到容器中
ADD springboot-docker.jar springboot-docker.jar
 
# 构建镜像时执行的命令
RUN bash -c 'touch /springboot-docker.jar'
 
# 配置容器,使其可执行化。配合CMD可省去"application",只使用参数
ENTRYPOINT ["java","-Djava.security.egd-file:/dev/./urandom","-jar","-Xmx128m","-Xms128m","/springboot-docker.jar"]


FROM java:8
VOLUME /temp
ADD springboot-docker.jar springboot-docker.jar
RUN bash -c 'touch /springboot-docker.jar'
ENTRYPOINT ["java","-Djava.security.egd-file:/dev/./urandom","-jar","-Xmx128m","-Xms128m","/springboot-docker.jar"]

打包命令docker build


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 是实际生成的镜像名
--tag  -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
-f :指定要使用的Dockerfile路径
参考: https://www.runoob.com/docker/docker-build-command.html



2.运行镜像
-d     : 表示容器在后台运行
--name : 为容器起一个名字
-p     : 端口映射,格式为宿主机端口:容器端口,上文中含义是将容器中的端口80映射到宿主机的端口80,对外提供访问服务。
最后一个字段为镜像名称

# 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

自定义命令脚本


# 打包命令
安装git
 yum install -y git

下载代码
 git clone https://gitee.com/pythonloser/springboot-docker.git

打包jar包
mvn clean install  

vim  restart.sh
chmod 777 restart.sh

# 更新代码及打包
cd /root/dockerfile/springboot-docker
git pull 

cd /root/dockerfile/springboot-docker
mvn clean install  
# 复制jar包
rm -rf /root/dockerfile/springboot-docker.jar
cp  /root/dockerfile/springboot-docker/target/springboot-docker.jar /root/dockerfile
 
# 删除容器再重新打包
echo 'stop'
docker stop springboot-docker01

echo 'rm'
docker rm springboot-docker01

echo 'build'
docker build -f ./Dockerfile -t springboot-docker  .

echo 'run'
docker run --name springboot-docker01 -d -p 8080:8080 springboot-docker


jdk安装

一、yum安装jdk,/usr/lib/jvm
# yum -y list java*
# yum install -y java-1.8.0-openjdk-devel.x86_64
# java -version
 
 二、从官网下载包安装jdk
 进入oracle官网,java8下载页面http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

1.下载
# wget --no-check-certificate 官网获取的下载地址

2.解压
# tar zxvf jdk1.8.0_144.tar.gz
# mv jdk1.8.0_144 /usr/java/
 
4.配置环境变量
# vim /etc/profile

JAVA_HOME=/usr/java/jdk1.8.0_144
CLASSPATH=%JAVA_HOME%/lib:%JAVA_HOME%/jre/lib
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
export PATH CLASSPATH JAVA_HOME

# source /etc/profile

5.验证安装
# java -version

maven安装

1.下载maven
# wget --no-check-certificate https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz

2.解压:
# tar -zxvf apache-maven-3.8.6-bin.tar.gz 
# mv apache-maven-3.8.6 /usr/local/

3.更换镜像 
# vim /usr/local/apache-maven-3.8.6/conf/setting.xml

<mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
       <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
</mirror>

4.配置环境变量
# vim /etc/profile

MAVEN_HOME=/usr/local/apache-maven-3.8.6
PATH=$MAVEN_HOME/bin:$PATH
export MAVEN_HOME PATH

# source /etc/profile
# mvn -v

重启脚本解读 restart.sh

echo '关闭防火墙'
systemctl stop firewalld.service

echo 'git pull 更新代码'
cd /root/dockerfile/springboot-docker
git pull 

echo 'mvn clean install  开始打包'
cd /root/dockerfile/springboot-docker
mvn clean install  
echo '更新jar包'
rm -rf /root/dockerfile/springboot-docker.jar
cp  /root/dockerfile/springboot-docker/target/springboot-docker.jar /root/dockerfile
 

echo 'stop'
docker stop springboot-docker01

echo 'rm'
docker rm springboot-docker01

echo 'build'
docker build -f ./Dockerfile -t springboot-docker  .

echo 'run'
docker run --name springboot-docker01 -d -p 8080:8080 springboot-docker

Dockerfile

FROM java:8
VOLUME /temp
ADD springboot-docker.jar springboot-docker.jar
RUN bash -c 'touch /springboot-docker.jar'
ENTRYPOINT ["java","-Djava.security.egd-file:/dev/./urandom","-jar","-Xmx128m","-Xms128m","/springboot-docker.jar"]

你可能感兴趣的:(docker,自动化,spring,boot)