一、docker不建议用户通过commit方式构建镜像原因如下:
1.这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱,比如要在Debian bash 镜像中也加入vi,害的重复前面的所有步骤
2.更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计存在安全隐患
二、用dockerfile构建镜像
底层也docker commit —后一层构建新镜像的. docker commit能够帮助我们更加深 入的理解构建过程和镜像分层结构
1.创建镜像
①创建文件夹
mkdir /test
②写入安装程序
vim Dockerfile
FROM c37ecc006544 (镜像id)
RUN yum install -y vim (yum安装)
③执行创建
docker build -t mytcentos:vm1 (镜像名字)
2.查看镜像分层结构
centos-yum是通过在base镜像的顶部添加一个新的镜像层而得到。
docker history 会显示镜像的构建历史,也就是dockerfile的执行过程
docker history centos:latest
二、镜像的缓存特性
docker 会缓存已有镜像的镜像层,构建新镜像层已经存在,就直接使用,无需重新创建
如果我们希望在构建镜像时不使用缓存,可以在docker build命令中上 --no-cache 参数。dockerfile中的每一个指令都会创建一个镜像层,上层是依赖于下层的,无论什么时候,只要某一层发生变化,其上面所有的层的缓存都会失效。也就是说,如果我们改变dockerfile指令的执行顺序,或者修改或添加指令,都会使缓存失效。
docker build -t mytest-yum:vm2 . --no-cache
三、dockerfile命令
1.from
功能为指定基础镜像,并且必须是第一条指令。如果不以任何镜像为基础,那么写法为:FROM scratch 同时以为着接下来所写的指令
FROM <images>
FROM <images>:<tag>
FROM <image>:<digest>
三种写法,其中<tag>和<digest>是可选项,那么默认值为latest
2.RUN
功能是为了运行指定的命令 run命令格式有两种
1.RUN
2.RUN ['exectable','param1','param2']第一种后边直接跟shell,在Linux操作系统上默认/bin/sh -c 在window操作系统上默认cmd /S/C 第二种累死与函数调用。可将exectable理解成为执行文件,后面就是两个参数
RUN /bin/bash-c'source $HOME/.bashrc; echo $HOME
RUN [”/bin/bash”,“-c”,“echo hello”]
注意:多行命令不要写多个RUN, 原因是Docker file中每一个指令都会建立一层.多少个RUN就构建了多少层镜像, 会
造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。RUN书写时的换行符是\
3.CMD
功能为容器启动时需要运行的命令,语法有三种:
CDM ["executable","param1","param2"]
CMD ["param1","param2"]
CMD commamd param1 param2
举例语句
FROM centos
CMD ["ls","/"]
CMD ls /root
补充细节:这里边包括参数的一定要用双引号,就是”,不能是单引号。千万不能写成单引号,
原因是参数传递后, docker解析的是一个JSON array
缺点:
1.如果后边存在参数 只执行最后参数 前边写入的CMD不执行
2.登录时写入参数,则执行登录时参数 不执行CMD写入参数
4.LABEL
功能是为镜像指定标签
label com.test.version="1.0"
label com.test.description="this is testapp"
语法如下:
说明:LABEL会继承基础镜像种的LABEL, 如遇到key相同, 则值要覆盖
5.MAINTAINER
指定作者:
MAINTAINER wangjianye
6.EXPOSE
功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会vim使容器访问主机的端口,如果想使得容器与主机的端口有映
关系,必须在容器启动的时候加上 -p 参数
7.ENV
功能是为设置环境变量:语法有两种:
1.ENV
2.ENV=.....
两者的区别就是第一种是一次只能设置一个,第二种是一次设置多个
例子:
ENV test1="123"
设置变量 不需要进入文件配置文件中添加
8.ADD
一个复制命令,把文件复制到镜像中,如果把虚拟机与容器想想成两台Linux服务器的话,那么这就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用,语法如下:
1.ADD
2.ADD ["....."] 路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径可以是本地文件或者是一个本地压缩文件,还可以是一个url,那么add就类似于wget命令
ADD test.txt /tmp (直接复制到/tmp下)
ADD nginx-1.17.10.tar.gz /tmp (复制并可以解压到/tmp)
ADD http://nginx.org/download/nginx-1.17.10.tar.gz /tmp (可以直接下载到/tmp下)
9.COPY
看名字就是复制命令 语法如下:
1.COPY ...
2.COPY ["......"]
举例:
COPY nginx-1.17.10.tar.gz /tmp
add 可以进行下载 解包
copy 只能进行复制
10.ENTRYPOINT
功能是启动时的默认,语法如下:
1.ENTRYPOINT["executable",param1","param2"]
2.ENTRYPOINT command param1 param2
第二种就是写shell 第一种就是可执行文件加参数 与cmd比较说明(两条命令都是执行程序,还可以配合使用):
1.相同点: 只能写一条,如果写了多条,那么只有最后一条生效,容器启动时才运行,运行时机相同
2.不同点: ENTRYPOMINT 不会被运行的command覆盖,而cmd则会被覆盖,如果我们在dockerfile同时写了ENTRYPOINT和cmd ,并且 cmd指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数
举例:
FROM centos
ENTRYPOINT ls
CMD hello (当cmd和entrypoint 相遇 entrypoint 会覆盖掉cmd)
ENTRYPOINT ["ls"] (这种方式 在启动时可以输入文件夹 )
如果ENTRYPOINT和CMD同时写入,但是CMD是完整命令则 执行CMD命令
11.VOLUME
可实现挂载功能,可以将内地文件夹或者其他容器种的文件夹挂载到这个容器
语法为: VOLUME["/data"]
例如:
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log/ /var/db
例子:
VOLUME /wang (挂载的文件夹)
12. USER
设置启动容器的用户,可以是用户名或UID,所以,只有下面两种写法是正确的
USER Ddaemo
USER UID
注意:如果设置了容器以daemon用户去运行, 那么RUN, CMD和ENTRYPOINT都会以这个用户去运行
例子:
RUN useradd wang
USER wang
结果:
13.WORKDIR
语法:
WORKDIR /path/to/workdir
设置工作目录,对RUN CMD ENTRYPOINT,COPY,ADD生效,如果不存在则会创建,也可以设置多次
例子:
WORKDIR /jian
WORKDIR ye
WORKDIR shi
RUN pwd
结果:
14.ARG
语法:ARG [=] 设置变量命令, ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg=来指定参数,
如果用户在build镜像时指定了一个参数没有定义在dockerfile中,那么将有一个warming提示如下:
例子:
ARG test1="hello"
RUN echo $test1
结果:
AGR只会在构建时候才会显示,而ENV只在运行容器时候产生的环境变量
15.ONBUILD
语法:
ONBUILD [INSTRUCTION] (这个命令只对当前镜像的子镜像生效)
例子:
FROM centos
ONBUILD RUN touch hello.txt
然后 docker build -t mytetst 他不会生效
再一次构建 他就会生效
FROM mytest
构建:
docker build -t mytetst:aa
结果:
16.STOPSIGNAL
语法:
STOPSIGNAL signal (STOPSIGNAL命令的作用是当容器退出时给系统发送什么样的指令)
17HEALTHCHECK
容器健康状况检查命令 语法有两种:
1.HEALTHCHECK [OPTIONS] CMD command
2.HEALTHCHECK NONE
第一个的功能是在容器内部运行一个命令来检查容器的健康状况
第二个的功能是在基础的镜像中取消健康检查命令
[OPTIONS] 的选项支持以下三种选项:
--interval=DURATION两次检查默认的时间间隔为30秒
--timeout=DURATION健康检查命令运行超时时长, 默认30秒
--retries=N当连续失败指定次数后, 则容器被认为是不健康的, 状态为unhealthy, 默认次数是 3
注意:HEALTHCHECK命令只能出现一次, 如果出现了多次, 只有最后一个生效。
CMD后边的命令的返回值决定了这次健康检查是否成功,具体返回值如下:
O:success-表示容器是健康的
1:unhealthy-表示容器已经不能工作了
2:reserved-保留值
例子:
HEALTHCHECK --interval=1m \
--timeout=3s \
--retries=3 \
CMD curl curl -f http:// localhost/ || exit 1
四、dockerfile总结:
1.RUN在building时运行,可以写多条
2.CMD和ENTRYPOINT在运行container时运行,只能写一条,如果写多条,最后一条生效。
3.CMD在run时可以被COMMAND覆盖,ENTRYPOINT不会被COMMAND覆盖,但可以指定--entrypoint覆盖。
4.如果在Dockerfile里需要往镜像内导入文件,则,此文件必须在Dockerfile所在目录或子目录下。