dockerfile命令

Dockerfile

1、第一步首先编写dockerfile(本例在~/my_docker目录下创建的dockerfile)

#version 0.0.1
FROM ubuntu
MAINTAINER lzj "leezhongjian@163.com"
RUN touch ~/hello.txt
RUN echo "hello lzj" >> ~/hello.txt
RUN cat ~/hello.txt
  • ROM指定一个已经存在的镜像,后续指令都将基于该镜像进行,称为基础镜像。在运行容器时,必须指定基于哪个容器进行构建的。
  • MAINTAINER指定镜像的作者以及联系方式
  • RUN会在当前镜像中运行指定命令,每条RUN指定创建一个新的镜像层,指令成功会将镜像提交,依次类推,镜像层层提交。执行RUN的时候其实就是在执行/bin/sh -c来执行后面的touch、echo、cat命令

2、基于dockerfile构建镜像

	 docker build -t="softwarebird/mydocker" .

构建镜像时,-t指定了仓库名softwarebird,镜像名称mydocker,"."表示构建镜像用的dockerfile去当前目录下去找。运行命令,会生成需要的镜像。
也可以构建镜像时指定镜像的版本号,如下:

		docker build -t="softerwarebird/my_hello:v0.1" .

如果不指定版本号,默认生成的是latest版本,如下所示:
在这里插入图片描述
构建镜像时也可以指定dockerfile的位置,如下(文件的名字不一定需要命名dockerfile):

	docker build -t="softerwarebird/my_hello:v0.1" -f /home/demo/my_dockerfile

在指定目录先构建镜像时,可以在该目录下创建".dockerignore"文件,凡是做镜像时不需要把指定的文件做入镜像的,可以在".dockerignore"设置需要过滤的文件。与git的".gitignore"类似。

3、dockerfile与缓存
dockerfile的每一步构建过程都会生成一个镜像,并将镜像缓存起来,在下次构建镜像时,如果缓存中已经有了,直接用缓存中的镜像进行建构,如下所示:
在这里插入图片描述
如果强制不适用缓存的镜像,命令如下:
在这里插入图片描述
4、基于构建缓存的dockerfile模板
在用dockerfile构建镜像是,每次都会执行一遍dockerfile中命令,但是如果在dockerfile中通过ENV命令设置一个刷新时间,只要这个时间不变,除第一次构建后,后续每次构建都会利用缓存中的镜像;如果时间变动,就会把ENV命令后的所有命令重新构建一遍镜像。dockerfile示例如下:

	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    ENV REFRESHED_AT 2019-03-18
	    RUN apt-get update

基于此dockerfile第一次构建镜像时,命令如下:

    docker build -t="softwarebird/mydocker" .

运行结果如下:
在这里插入图片描述
第二次基于此dockerfile构建镜像时,执行docker build -t="softwarebird/mydocker" .,运行结果如下:
在这里插入图片描述
从运行结果可以看出,每一步都应用了缓存中的镜像进行构建。
下面修改dockerfile文件中ENV制定的缓存时间

	    ENV REFRESHED_AT 2019-03-17

再次构建镜像,运行docker build -t="softwarebird/mydocker" . ,运行结果如下:
在这里插入图片描述
从运行结果可以看, ENV命令前的 MAINTAINER还是用的缓存中的镜像,ENV后面的apt-aget update没有用缓存中的,而是重新执行的。

5、查询创建的镜像
上面构建完镜像后,下面查询创建的镜像,执行

    docker images softwarebird/mydocker 

显示结果如下:
在这里插入图片描述
如果想查询镜像的每一步的构建情况,即构成最终镜像的每一层镜像的叠加,执行命令如下:

	    docker history softwarebird/mydocker

显示结果如下:
在这里插入图片描述
6、用构建的镜像启动容器
利用最开始的dockerfile构建的镜像启动容器

	    #version 0.0.1
	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    RUN touch ~/hello.txt
	    RUN echo "hello lzj" >> ~/hello.txt
	    RUN cat ~/hello.txt

启动容器

     docker run -i -t softwarebird/my_hello /bin/bash

进入启动后的容器查询创建的hello.txt文件
在这里插入图片描述

二、Dockerfile指令

在编写dockerfile文件过程中,除了上面用到的FROM、MAINTAINER、RUN命令,还可以用如下命令。
1、CMD
cmd命令用于指定容器启动时,默认执行的命令。dockerfile示例如下:

    #version 0.0.1
    FROM ubuntu
    MAINTAINER lzj "leezhongjian@163.com"
    RUN touch ~/hello.txt
    RUN echo "hello lzj" >> ~/hello.txt
    CMD ["/bin/bash"]

用该dockerfile制作镜像,docker build -t="softwarebird/my_hello" . 然后运行该制作的镜像docker run -i -t softwarebird/my_hello,发现启动容器时,没有指定执行的/bin/bash命令,但在容器启动时却默认执行/bin/bash,就是因为dockerfile中指定了CMD ["/bin/bash"]。当然也可以在启动容器时指定执行的命令,docker build -t="softwarebird/my_hello" . 这样就会覆盖CMD ["/bin/bash"]中命令。
注意:dockerfile中只能指定一条CMD命令,即使指定了多条,也只有最后一条生效。
2、ENTRYPOINT
ENTRYPOINT命令与CMD命令类似,都可表示容器启动时默认执行的命令,但是CMD执行的命令可以被容器启动时传入的命令覆盖,而ENTRYPOINT执行的命令却不可以覆盖,容器启动时传入的命令可以作为ENTRYPOINT后的命令的参数。例如,基于如下dockerfile构建镜像

    #version 0.0.1
    FROM ubuntu
    MAINTAINER lzj "leezhongjian@163.com"
    RUN touch ~/hello.txt
    RUN echo "hello lzj" >> ~/hello.txt
    ENTRYPOINT ["ls", "-l"]

基于此dockerfile制作镜像,执行命令docker build -t="softwarebird/my_hello" .,然后执行利用该镜像启动一个容器,执行命令如下:

    docker run -i softwarebird/my_hello /root/hello.txt

输出结果如下:
在这里插入图片描述
可见启动容器时指定的“/root/hello.txt”传给了ENTRYPOINT 命令后的“ls -l”命令。

3、WORKDIR
WORKDIR为下面的RUN、CMD、ENTRYPOINT等提供工作目录。dockerfile示例如下:

#version 0.0.1
FROM ubuntu
MAINTAINER lzj "leezhongjian@163.com"
WORKDIR /root
RUN touch hello.txt
RUN echo "hello lzj" >> hello.txt
WORKDIR /home
RUN touch test.txt
RUN echo "hello test" >> test.txt

上面制作镜像时,在/root/下面创建了hello.txt文件,在/home/下面创建了test.txt文件。利用此dockerfile构建镜像docker build -t="softwarebird/my_hello" . ,然后运行该镜像docker run -i -t softwarebird/my_hello /bin/bash 。查看制作镜像时创建的文件结果如下:
在这里插入图片描述
4、USER
USER指令用来指定该镜像以什么用户进行,比如USER lzj 镜像以lzj用户运行。可以指定用户名或用户名的UID以及用户组以及组的GID进行组合,如下所示

			    USER user
			    USER user:group
			    USER uid
			    USER uid:gid
			    USER user:gid
			    USER uid:group

例如dockerfile内容如下,指定root用户:

	    #version 0.0.1
	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    USER root
	    ENV home_path /home
	    WORKDIR $home_path
	    RUN touch test2.txt
	    RUN echo "hello test2" >> test2.txt

通过该dockerfile构建镜像 docker build -u root -t="softwarebird/my_hello" .,用root用户运行该镜像,结果如下:
在这里插入图片描述
用lzj用户运行该镜像,结果如下:
在这里插入图片描述
可见用lzj用户是失败的。

5、VOLUME
VOLUME指令用来向基于镜像创建的容器添加卷,一个卷可以存在于一个或多个容器内的特定目录,提供数据共享或者对数据进行持久化的功能。卷有如下功能:

  • 卷可以在容器间共享和重用

  • 一个容器可以不是必须和容器共享卷

  • 对卷的修改时立即生效的

  • 对卷的修改不会对更新镜像产生影响

  • 卷会一直存在直到没有任何容器再使用它
    下面举一个容器与宿主机共享文件的例子,也即容器可以把数据持久化到宿主机上,dockerfile如下:

         #version 0.0.1
         FROM ubuntu
         MAINTAINER lzj "leezhongjian@163.com"
         VOLUME ["/home/my_volume"]
    

表示在容器的/home的目录下添加了一个my_volume目录。
下面利用该dockerfile构建镜像,运行 docker build -t="softwarebird/my_hello" . ,然后运行该镜像docker run -i -t --name hello_container softwarebird/my_hello /bin/bash,启动容器后,进行容器的/home/my_volume目录,发现该目录下为空。下面在宿主机上找到对应该容器共享的目录,另外打开一个终端,执行docker inspect hello_container,查找到"Source": "/var/lib/docker/volumes/6afa1de9d514a765dd8f7a503270a199fb12d2b9c6e683423155b370472d2e0f/_data",/var/lib/docker/volumes/6afa1de9d514a765dd8f7a503270a199fb12d2b9c6e683423155b370472d2e0f/_data即为宿主机上对应容器上/home/my_volume的目录,在宿主机的该目录下创建一个hello.txt,那么在容器的/home/my_volume目录下可以立即看到hello.txt文件,示意图如下:
在这里插入图片描述
6、ADD
ADD指令用来将构建环境下的文件和目录复制到镜像中。格式:ADD src dest,示例如下,采用如下dockerfile构建镜像

	    #version 0.0.1
	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    WORKDIR /home
	    ADD hello.txt .            

然后在dockerfile所在的目录下新建一个hello.txt文件,然后执行命令构建镜像:docker build -t="softwarebird/my_hello" .,然后执行构建的镜像: docker run -i -t softwarebird/my_hello /bin/bash,最后可以在容器的home目录下看到一个hello.txt文件,即为从宿主机上copy过来的。
在这里插入图片描述
在ADD文件时,docker通过目的地址的末尾是否有“/”来判断目的源是文件还是目录,如果目的地址以“/”结尾,docker默认源位置是目录,如果目的地址不是以“/”结尾,那么源地址为文件。
ADD还可以把URL加入到容器中,例如ADD http://xxx/file.txx /home/
ADD还可以把压缩文件加入到容器目录中,并自动实现解压功能,例如ADD test.zip /home/test/

7、COPY
COPY功能与ADD相似,但COPY没有提取压缩文件的功能。格式COPY src dest src为宿主机上的文件或目录,必须是相对于存放dockerfile的文件或目录,不能copy其它位置的目录或文件。

8、LABEL
LABEL指令用于为docker镜像添加元数据,元数据以键值对的形式出现,格式docker key="value",例如,以下面dockerfile为例

    #version 0.0.1
    FROM ubuntu
    MAINTAINER lzj "leezhongjian@163.com"
    LABEL version="0.1" author="lzj" date="20190323"

利用该dockerfile构建镜像,docker build -t="softwarebird/my_hello" .,下面可以利用inspect查看生成的softwarebird/my_hello镜像元数据信息,执行docker inspect softwarebird/my_hello,结果如下所示
在这里插入图片描述
9、STOPSIGNAL
STOPSIGNAL指令用来设置stop容器时,宿主机发送什么信号量给容器,这个信号量必须是内核系统调用表中合法的信号量,如SIGTERM、SIGKILL等。
格式:

STOPSIGNAL 信号量

默认情况下,当要stop一个容器,执行docker stop 容器名/容器id,宿主机向容器发送的是SIGTERM信号,容器接受到SIGTERM信号后,会执行一系列的软件等关闭操作,然后执行退出关闭容器操作,如果短暂的时间内容器没有关闭,宿主机继续向容器发送一个SIGKILL信号,强制容器关闭。

  • 下面示例默认情况,采用dockerfile如下:

     #version 0.0.1
     FROM ubuntu
     MAINTAINER lzj "leezhongjian@163.com"
     RUN touch ~/hello.txt
     RUN echo "hello world" >> ~/hello.txt
    

然后构建镜像,利用该镜像启动容器,过程如下:
在这里插入图片描述
进入容器后就可以执行一系列操作了,下面执行stop操作,观看容器的反应,启动另外一个终端,然后在另外一个终端上执行docker stop my_container1 关闭容器操作,容器退出过程如下:
在这里插入图片描述
可见,由于容器中目前没有执行耗时的操作,所以容器接受到SIGTERM信号后,自动执行了exit退出容器的操作。

  • 下面定义容器关闭是,不响应默认的SIGTERM信号,而是直接响应SIGKILL信号
    采用dockerfile如下,添加了指定响应的SIGKILL信号

     #version 0.0.1
     FROM ubuntu
     MAINTAINER lzj "leezhongjian@163.com"
     RUN touch ~/hello.txt
     RUN echo "hello world" >> ~/hello.txt
     STOPSIGNAL SIGKILL
    

然后构建镜像,启动容器,过程如下:
在这里插入图片描述
下面启动另外一个终端,在另外一个终端上执行stop容器操作docker stop my_container2,容器响应如下
在这里插入图片描述
可见当宿主机执行stop操作后,宿主机向容器发送SIGTERM信号后,容器没有反应,随之发送SIGKILL信号后,容器立即退出。从上图可以看出容器并没有执行exit操作,会立即退出容器,导致未执行完的东西也立即退出,这就是与默认时的区别所在。

10、ARG
ARG指令用来定义可以在docker build命令运行时传递给构建运行时的变量,在运行docker build时只需用–build-arg标志即可,在dockerfile中格式如下 ARG key=value ,下面实例显示,所用dockerfile如下:

	    #version 0.0.1
	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    ARG arg1=docker_arg1
	    ARG arg2
	    RUN touch ~/hello.txt
	    RUN echo $arg1 >> ~/hello.txt
	    RUN echo $arg2 >> ~/hello.txt

下面利用该dockerfile构建镜像,构建镜像时,只需要加入–build-arg标志即可:

docker build --build-arg arg2=docker_arg2 -t="softwarebird/my_hello" .

构建镜像时,没有为arg1传参数,则arg1取默认值docker_arg1,为arg2传入的参数为docker_arg2,那么利用该镜像启动容器,查看是否正确
在这里插入图片描述

11、ONBUILD
ONBUILD指令能为镜像添加触发器,当一个镜像被用作其它镜像的基础 镜像时,该镜像中的触发器就会执行。触发器会在构建的过程中插入新的指令,这些指令紧跟在FROM之后执行。示例如下
首先要新构建一个基础镜像,该镜像所用的dockerfile如下:

	    #version 0.0.1
	    FROM ubuntu
	    MAINTAINER lzj "leezhongjian@163.com"
	    ONBUILD ADD hello.txt /home/

该dockerfile中添加一个ONBUILD 触发器,但是利用此dockerfile构建镜像时没有影响,只是在它的子镜像构建过程中才会发挥作用。构建基础镜像过程如下:
在这里插入图片描述
下面在上面的基础镜像softwarebird/my_hello上构建镜像,所用my_docker2/dockerfile如下:

    FROM softwarebird/my_hello
    MAINTAINER lzj "leezhongjian@163.com"

在my_docker2目录下新建hello.txt文件,为后面测试用,内容如下:

		    hello dockerfile2
		    it's based on dockerfile

下面利用该dockerfile构建镜像,构建的镜像是基于softwarebird/my_hello镜像的,那么在基础镜像softwarebird/my_hello所用的dockerfile中的触发器就会发挥作用(ONBUILD ADD hello.txt /home/),会在构建子镜像执行FROM softwarebird/my_hello后执行ADD hello.txt /home/命令,过程如下:
在这里插入图片描述
可见在基于基础镜像softwarebird/my_hello构建softwarebird/my_hello2镜像时,触发了ONBUILD触发器,因此在构建softwarebird/my_hello2时执行了ADD hello.txt /home/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值