Docker基础实战教程三:Dockerfile

镜像是分层存储的,其制作过程实际上是对每一层需要添加的配置、文件等进行定制。Dockerfile本质上就是一个制作镜像的脚本,将每一层的修改、安装、构建、操作等命令都在这个脚本中进行清晰透明的定义。
本实训将详细介绍Dockerfile制作镜像的语法及命令,以及其制作流程。通过本实训,学习者应基本掌握基于Dockerfile的镜像制作。

初识Dockerfile

#创建一个空文件夹,并进入其中
mkdir newdir1
cd newdir1
#创建一个Dockerfile文件
touch Dockerfile
#假设我的Dockerfile文件为
#FROM ubuntu
#RUN mkdir dir1
#可以这么写:
# echo 'FROM ubuntu' > Dockerfile
# echo 'RUN mkdir dir1'>> Dockerfile
#输入Dockerfile文件内容
#********** Begin *********#
#以busybox为基础镜像

#在基础镜像的基础上,创建一个hello.txt文件
echo 'FROM busybox' > Dockerfile
echo 'RUN touch hello.txt' >>  Dockerfile
#********** End **********#
#使用Dockerfile创建一个新镜像,镜像名为busybox:v1
docker build -t busybox:v1 .

docker build、COPY和ADD

#创建一个空文件夹,并进入其中
mkdir newdir2
cd newdir2
#创建一个文件夹dir1,将其压缩,然后删除dir1
mkdir dir1 && tar -cvf dir1.tar dir1 && rmdir dir1
#创建一个Dockerfile文件
touch Dockerfile
#假设我的Dockerfile文件为
#FROM ubuntu
#RUN mkdir dir1
#可以这么写:
# echo 'FROM ubuntu' > Dockerfile
# echo 'RUN mkdir dir1'>> Dockerfile
#输入Dockerfile文件内容
#********** Begin *********#
echo 'FROM busybox' > Dockerfile
#并将上下文目录下的dir1.tar“解压提取后”,拷贝到busybox:v3的/
echo 'ADD dir1.tar /' >>  Dockerfile
#********** End **********#

#文件内容完毕,在当前文件夹中执行
#********** Begin *********#
#以该Dockerfile构建一个名为busybox:v3的镜像
docker build -t busybox:v3 .
#********** End **********#

:CMD和ENTRYPOINT指令

#创建一个空文件夹,并进入其中
mkdir newdir3
cd newdir3
#创建一个Dockerfile文件
touch Dockerfile
#假设我的Dockerfile文件为
#FROM ubuntu
#RUN mkdir dir1
#可以这么写:
# echo 'FROM ubuntu' > Dockerfile
# echo 'RUN mkdir dir1'>> Dockerfile
#输入Dockerfile文件内容
#********** Begin *********#
#以busybox为基础镜像
echo 'FROM busybox' > Dockerfile
echo 'ENTRYPOINT ["df"]'>> Dockerfile
echo 'CMD ["-Th"]'>> Dockerfile
#********** End **********#

#文件内容完毕,在当前文件夹中执行
#********** Begin *********#
#以该Dockerfile构建一个名为mydisk:latest的镜像
docker build -t mydisk:latest .
#********** End **********#

ENV、EXPOSE、WORKDIR、ARG指令

#创建一个空文件夹,并进入其中
mkdir newdir4
cd newdir4
#创建一个Dockerfile文件
touch Dockerfile
#假设我的Dockerfile文件为
#FROM ubuntu
#RUN mkdir dir1
#可以这么写:
# echo 'FROM ubuntu' > Dockerfile
# echo 'RUN mkdir dir1'>> Dockerfile
#输入Dockerfile文件内容
#********** Begin *********#
#以busybox为基础镜像
echo 'FROM busybox' > Dockerfile
#声明暴露3000端口
echo 'EXPOSE 3000' >>Dockerfile
#将变量var1=test设置为环境变量
echo 'ENV var1=test '>>Dockerfile
#设置工作目录为/tmp
echo 'WORKDIR /tmp'>>Dockerfile
#在工作目录下创建一个1.txt文件
echo "RUN touch 1.txt" >> Dockerfile
#********** End **********#
#文件内容完毕,在当前文件夹中执行
#********** Begin *********#
#以该Dockerfile构建一个名为testimage:v1的镜像
docker build -t testimage:v1 .
#********** End **********#

ONBUILD和VOLUME指令

#无论任何输入都会认为正确,本关的目的是学习ONBUILD和VOLUME指令
ONBUILD指令
●ONBUILD添加一个将来执行的触发器(trigger);
格式: ONBUILD <其它指令>;

ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如RUN, COPY等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

ONBUILD指令的具体执行步骤
(1)在构建过程中,ONBUILD指令会添加到触发器指令镜像元数据中,这些触发器指令并不会在当前构建过程中执行。
(2)在构建过程后,触发器指令会被存储在镜像详情中,其主键是OnBuild,可以使用docker inspect命令查看。
(3)在之后该镜像可能作为其他Dockerfile中FROM指令的参数。在构建过程中,FROM指令会查找ONBUILD触发器指令,并且会以它们注册的顺序执行。若有触发器指令执行失败,则FROM指令被中止,并返回失败;若所有触发器指令执行成功,则FROM指令完成并继续执行下面的指令。在镜像构建完成后,触发器指令会被清除,不会被子孙镜像继承。

ONBUILD指令的实例
1.首先编写一个Dockerfile文件,内容如下所示:

FROM busybox
ONBUILD RUN touch 1.txt
2.利用上面的Dockerfile文件构建一个新镜像:docker build -t image1 .。执行docker run image1 cat 1.txt,提示:cat: can't open '1.txt': No such file or directory。可以知道基于image1镜像构建的容器中不存在1.txt文件。我们通过inspect image1,在里面可以找到。

"OnBuild":[
    "RUN touch 1.txt"
],
3.编写一个新的Dockerfile文件,内容如下所示:

FROM image1
RUN echo 'hello'
4.利用第三步创建的的Dockerfile文件构建一个新镜像:docker build -t image2 .。如下所示:在执行完FROM指令后,首先执行的是触发器,也就是# Executing 1 build trigger...,该指令创建了一个1.txt文件。然后才执行RUN echo 'hello'。执行docker run image2 cat 1.txt,执行成功!!

[root@localhost dir1]# docker build -t image2 .
Sending build context to Docker daemon 2.048 kB
Step 1/2 : FROM image1
# Executing 1 build trigger...
Step 1/1 : RUN touch 1.txt
 ---> Running in 5c9b99ef7801
 ---> 4c5b719176b8
Removing intermediate container 5c9b99ef7801
Step 2/2 : RUN echo 'hello'
 ---> Running in 8a2598e90e1f
hello
 ---> f5642bb4a975
Removing intermediate container 8a2598e90e1f
Successfully built f5642bb4a975
[root@localhost dir1]# docker run image2 cat 1.txt`
[root@localhost dir1]#
VOLUME指令
●VOLUME定义匿名卷;
格式:VOLUME ["<路径1>", "<路径2>"...]或VOLUME <路径>;

之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于数据卷(volume)中,后面的章节我们会进一步介绍Docker数据卷的概念。

你可能感兴趣的:(Docker基础实战教程三:Dockerfile)