Marco's Java【Docker入门(四) 之 Dockerfile容器数据卷详解】

前言

咱们上节已经接触过Dockerfile并使用Dockerfile创建容器数据卷,但是Dockerfile的作用远远不止如此!
因此本节会更深入的了解Dockerfile以及它的诸多使用方式, “料” 也是相当足哦!

什么是Dockerfile

简单来讲Dockerfile是用来构建Docker镜像的构建文件,是由一系列的命令和参数构成的脚本。玩过游戏的朋友对武器卷轴应该不陌生吧?
我上学那会儿,特别喜欢玩DNF(地下城),里边就有武器卷轴,有了卷轴之后,只需要根据卷轴的要求收集原材料,最终可以根据需求合成一件本职业可以使用的武器。Dockerfile在Docker中就等同于武器卷轴的存在!而我们合成武器所需要的原材料,比方说centos合成需要centos和linux kenel(共享),tomcat合成需要tomcat、jdk和linux kenel(共享),收集完成这些材料之后,卷轴图纸就会发光,只差点击 “合成” 按钮!此时的卷轴就等同于一个镜像,根据镜像将原材料炼制成武器,那么这把 “开光神器” 就是Docker容器!
在这里插入图片描述

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态。

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

Dockerfile:Dockerfile定义了进程需要的一切东西。它里面涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等
Docker镜像:在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
Docker容器:直接提供服务

Dockerfile体系结构

在了解Dockerfile体系结构之前,先介绍一下编写Dockerfile的基础知识

Dockerfile基础知识
1,每条保留字(关键字)指令都必须为大写字母后面要跟随至少一个参数
2,指令从上到下顺序执行
3,#表示注释
4,每条指令都会创建一个新的镜像层,并对镜像进行提交

大家可以参我上节编写的Dockerfile,结合下面的关键字列表,稍加理解一下以下内容的大致意思。

FROM centos
VOLUME ["/dataContainer1","/dataContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash
关键字解释
FROM基础镜像,当前新镜像是基于哪个base镜像的
MAINTAINER镜像维护者的姓名和邮箱地址
RUN容器构建时需要运行的命令
EXPOSE当前容器对外暴露的端口
WORKDIR指定在创建容器后,终端默认登陆进来的工作目录
ENV用来在构建镜像过程中设置环境变量
ADD将宿主机目录下的文件拷贝进镜像并且ADD命令会自动处理URL和解压tar包
COPY类似ADD,拷贝文件和目录到镜像中 ,语法COPY src dest COPY [’'src",“dest”]
VOLUME容器数据卷,用于数据保存和持久化工作
CMD指定一个容器启动时要运行的命令格式
ENTEYPONT指定一个容器启动时要运行的命令,ENTRYPOINT的目地和CMD一样,都是在指定容器启动程序及参数
OBBUILD当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后触发父镜像的onbuild

补充: CMD 命令格式有三种形式
shell: CMD <命令> (如:CMD tomcat/bin/startup.sh)
exec CMD [‘可执行文件’,“参数1”,“参数2”] (如:CMD [‘tomcat/bin/startup.sh’])
DockerFile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
在这里插入图片描述


自定义CentOs镜像

之前咱们思考为什么centos镜像只有几百M的时候有提到Docker将CentOs中很多内容,包括指令都精简化了,因此当我们使用centos镜像启动容器之后,很多命令都执行不了… 诸如ifconfig(或ip addr)等命令都失效了。

[root@localhost myvolume]# docker run -it centos
[root@779f74a3802e /]# ifconfig
bash: ifconfig: command not found

那么我想在在使用centos的时候用上这些指令就需要自定义CentOs镜像了,制作镜像当然得使用上 “卷轴” 了!所以咱们第一步就需要编写Dockerfile了。
在这里插入图片描述
接着执行命令docker build -t marcentos:1.0 ./创建镜像

Step 1/9 : FROM centos
 ---> 67fa590cfc1c
Step 2/9 : MAINTAINER marco<774798947@qq.com>
 ---> Using cache
 ---> 0a688508ae47
Step 3/9 : ENV MYPATH /usr/local
 ---> Running in 24e21af29412
 ---> d71b4cad91bd
Removing intermediate container 24e21af29412
Step 4/9 : WORKDIR $MYPATH
 ---> f43d914a872c
Removing intermediate container 92f4ec1c8af9
Step 5/9 : RUN yum -y install net-tools
 ---> Running in 84ca38c9374e
Step 6/9 : EXPOSE 80
 ---> Running in 02a18be34ddf
 ---> 2da5ea38d0f4
Removing intermediate container 02a18be34ddf
Step 7/9 : CMD echo $MYPATH
 ---> Running in f1977f8c250e
 ---> 71fc01fca43e
Removing intermediate container f1977f8c250e
Step 8/9 : CMD echo "finished,---------success"
 ---> Running in 99a8d2b59eee
 ---> 5f2d42dfb328
Removing intermediate container 99a8d2b59eee
Step 9/9 : CMD /bin/bash
 ---> Running in c30f6761995d
 ---> 30f62220a946
Removing intermediate container c30f6761995d
Successfully built 30f62220a946
[root@localhost myvolume]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
marcentos               1.0                 30f62220a946        3 minutes ago       314 MB

接着运行docker run -it marcentos:1.0 /bin/bash让我们自定义的镜像跑起来,我们再来测试看看ifconfig指令是否可以被执行。
在这里插入图片描述
经测试发现,咱们的自定义centos是可以运行ifconfig的!


自定义tomcat镜像

咱们再玩点稍有难度的!自己来做一个tomcat镜像,不知道大家还记不记得我们在Docker系列博文的第一节分析过tomcat镜像的结构(如下),是一层包着一层的俄罗斯套娃结构,tomcat镜像依赖于JDK,而JDK依赖于Linux的内核。
在这里插入图片描述
所以要自定义一个tomcat镜像,我们得准备原材料(jdk和tomcat的jar包)吧!
在这里插入图片描述
其实自定义一个镜像跟炒菜一个道理,Dockerfile就是菜谱,jdk-8u181-linux-x64.tar.gzapache-tomcat-8.5.38.tar.gz就是食材,想要做出一道美味佳肴,那么选择食材、添加辅料得先后顺序… 等都是需要考虑在内的,特别是食材和调料放入锅中的先后顺序,这一点尤为重要,制作镜像也是同样的道理,比方说咱们制作tomcat镜像,那么肯定是要依赖jdk的,因此jdk一定要放在tomcat之前。
好啦,说了这么多,咱们就来试着自己做一道 “菜” 吧!

首先,咱们来编写菜谱Dockerfile

##继承父镜像
FROM centos
##指定作者邮箱
MAINTAINER marco<774798947@qq.com>
##解压jdk和tomcat,把jdk和tomcat放到容器中
ADD  jdk-8u181-linux-x64.tar.gz /usr/local
ADD apache-tomcat-8.5.38.tar.gz /usr/local 
##声明环境变量
ENV MYPATH /usr/local
##设置进入容器的默认路径
WORKDIR $MYPATH
##修改tomcat和jdk的文件夹名称
RUN mv jdk1.8.0_181 jdk
RUN mv apache-tomcat-8.5.38 tomcat
##列出当前文件夹中所有的文件夹名称
RUN ls
##配置tomcat和jdk的环境变量
ENV JAVA_HOME /usr/local/jdk
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:CATALINA_HOME/bin

## 对外暴露的端口,只起到mark的作用
EXPOSE 8080
## 启动tomcat
CMD tomcat/bin/startup.sh && tail -F tomcat/logs/catalina.out

使用docker build -t martomcat:1.0 .指令将我们写的 “菜谱” 编辑成册!(类似于出版发行的意思) 注意最后的.不能省略哦,表示在当前路径(myvolume)下创建。

docker build -t martomcat:1.0 . #创建martomcat镜像
Sending build context to Docker daemon 195.3 MB
Step 1/15 : FROM centos #
 ---> 67fa590cfc1c
Step 2/15 : MAINTAINER marco<774798947@qq.com>
 ---> Using cache
 ---> 0a688508ae47
Step 3/15 : ADD jdk-8u181-linux-x64.tar.gz /usr/local
 ---> Using cache
 ---> 7b8a14bc1f6d
Step 4/15 : ADD apache-tomcat-8.5.38.tar.gz /usr/local
 ---> b1084509b38b
Removing intermediate container a2d8389e486d
Step 5/15 : ENV MYPATH /usr/local
 ---> Running in d94b62008ac2
 ---> d3dddd2faf49
Removing intermediate container d94b62008ac2
Step 6/15 : WORKDIR $MYPATH
 ---> 115118b1697f
Removing intermediate container 761e3b4786e4
Step 7/15 : RUN mv jdk1.8.0_181 jdk
 ---> Running in a8a1f88a3f0f

 ---> ed850b17e9de
Removing intermediate container a8a1f88a3f0f
Step 8/15 : RUN mv apache-tomcat-8.5.38 tomcat
 ---> Running in 9ea41d5cf9b5

 ---> e03a614ef5c6
Removing intermediate container 9ea41d5cf9b5
Step 9/15 : RUN ls
 ---> Running in 9dc8e10299d1

bin
etc
games
include
jdk
lib
lib64
libexec
sbin
share
src
tomcat
 ---> 840be59f0edb
Removing intermediate container 9dc8e10299d1
Step 10/15 : ENV JAVA_HOME /usr/local/jdk
 ---> Running in 375582cfe62a
 ---> 27671b1871c7
Removing intermediate container 375582cfe62a
Step 11/15 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in b061c156db65
 ---> 2b04c0c84e6a
Removing intermediate container b061c156db65
Step 12/15 : ENV CATALINA_HOME /usr/local/tomcat
 ---> Running in 40fdc7caaa03
 ---> 3a334150e28b
Removing intermediate container 40fdc7caaa03
Step 13/15 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:CATALINA_HOME/bin
 ---> Running in 3d17476838e3
 ---> d21bddc285a3
Removing intermediate container 3d17476838e3
Step 14/15 : EXPOSE 8080
 ---> Running in 474b7eac9da3
 ---> 05bcf9c4b73e
Removing intermediate container 474b7eac9da3
Step 15/15 : CMD tomcat/bin/startup.sh && tail -F tomcat/logs/catalina.out
 ---> Running in 7061060b8d2e
 ---> 2507182e790d
Removing intermediate container 7061060b8d2e
Successfully built 2507182e790d

有了 “菜谱” 咱们就开始炒菜啦!使用docker ps查看到咱们 “自创” 的tomcat镜像已经运行成功啦!

#启动martomcat镜像创建容器
[root@localhost myvolume]# docker run -it -d -p 8888:8080 martomcat:1.0 
9b09c16d20b8c17530b6e0f73229ec7c28174b2cbba7307a50ad3b0143396236
[root@localhost myvolume]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
9b09c16d20b8        martomcat:1.0       "/bin/sh -c 'tomca..."   24 seconds ago      Up 23 seconds       0.0.0.0:8888->8080/tcp   cocky_engelbart

接下来访问http://192.168.144.137:8888/就可以访问到自定义得tomcat啦!


创建jar包镜像

上面制作的两个镜像都只是玩具,在实际开发中,我们更多的是使用Dockerfile将要上线的项目打包,然后使用Docker让项目跑起来,所以,以下两种打包的方式是必须要掌握的!
第一步:准备工作
创建一个springboot项目并打jar包,在UserController中自定了一个方法loadAllUser,模拟获取后台的数据,并以json字符串的形式将数据传到页面上。
在这里插入图片描述
接着修改jar包的名称为app.jar(这个操作不是必要的,只是为了好记),然后将jar包丢进和Dockerfile同级的目录/myvolume
在这里插入图片描述
第二步:下载openjdk的依赖镜像
因为普通项目(非Web项目)运行时,是需要依赖JDK运行环境的,因此需要下载JDK镜像openjdk
在这里插入图片描述
第三步:编写Dockerfile
注意,这里我使用的是ENTRYPOINT替代了CMD,这两者的作用是一样的,唯一的区别就是使用了ENTRYPOINT之后,在执行docker run命令时,在命令的最后是可以追加其他的命令的,而使用CMD的话,假如指令docker run命令的结尾加上了其他的命令,则会将java -jar app.jar命令覆盖掉,结果会导致咱们的项目编译失败!
在这里插入图片描述
第四步:创建镜像并运行生成容器

#创建myapp镜像
[root@localhost myvolume]# docker build -t myapp:1.0 .
#运行myapp镜像,生成docker容器
[root@localhost myvolume]# docker run -it -d --name 'myapp' -p 8080:8080 myapp:1.0
b26f809d482dff52eae5e15cfce1a806c2b8c462a3cd4b1b8ee5059a8a1ba31e

测试结果如下,说明咱们的自定义镜像没有问题!
在这里插入图片描述


创建war包镜像

将war包做成镜像和上面将jar包做成镜像还是有很大区别的,主要在于存放的路径以及解压的方式不一样。
第一步:准备工作
步骤跟上面的一样,还是先准备一个项目并打成war包,接着将war包丢进和Dockerfile同级的myvolume目录。
在这里插入图片描述
第二步:修改Dockerfile
和普通的项目不同的是Web项目必须要在Web服务器中才能启动,因此需要将war包放入tomcat的webapps目录中,需要注意是war包解压需要用到unzip而不能使用ADD的方式解压,将解压的文件置入ROOT目录中主要是为了访问项目的时候不用加上项目名称。
在这里插入图片描述
第三步:将项目生成镜像
接下来的步骤跟上面一样,先将项目build成镜像,然后使用docker run -it -d --name 'mypro' -p 8888:8080 myapp:1.0生成容器
在这里插入图片描述
发现项目同样是可以访问到的!
在这里插入图片描述


Docker番外之本地镜像推送到阿里云

本节的末尾教大家一招,如何将本地镜像推送到阿里云,就以刚才编辑好的war包镜像为例吧!操作也非常简单!
首先登陆 阿里开发平台 ,接着打开 容器镜像服务,然后咱们创建一个镜像仓库
在这里插入图片描述
创建成功之后,镜像仓库列表会多出一条数据
在这里插入图片描述
接着点击列表数据最右边的管理,找到基本信息中的操作指南
在这里插入图片描述
然后按里面的操作来就行啦,首先上传war镜像到aliyun镜像仓库
$ sudo docker login --username=xxxx registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/marco_space/mywar:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/marco_space/mywar:[镜像版本号]
在这里插入图片描述
接着尝试从aliyun镜像仓库中拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/laolei/mywar:[镜像版本号]
在这里插入图片描述
拉取成功之后,查看镜像会多出一条registry.cn-hangzhou.aliyuncs.com/marco_space/mywar
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值