Docker 大热,还不了解 Dockerfile 你就OUT啦~

53 阅读5分钟

前 言

前言:近年来 Docker 非常火,想要玩好 Docker 的话 Dockerfile 是绕不开的,这就好比想要玩好 Linux 服务器绕不开 shell 道理是一样的。今天我们就来聊一聊 Dockerfile 怎么写,那些指令到底是什么意思。

一、先来看一个简单的 Dockerfile

image.png

二、Dockerfile 编写规则

指令大小写不敏感,为了区分习惯上用大写

Dockerfile 非注释行第一行必须是 FROM

文件名必须是 Dockerfile

Dockerfile 指定一个专门的目录为工作空间

所有引入映射的文件必须在这个工作空间目录下

Dockerfile 工作空间目录下支持隐藏文件(.dockeringore)

(.dockeringore)作用是用于存放不需要打包导入镜像的文件,根目录就是工作空间目录

每一条指令都会生成一个镜像层,镜像层多了执行效率就慢,能写成一条指定的就写成一条

三、Dockerfile 指令详解

1.FROM:基础镜像

image.png 2.MAINTAINER:镜像作者信息

2.1、废弃了,使用LABLE替代

3.LABLE:镜像描述信息

3.1、LABLE author="haili"

4.COPY:从 Docker 宿主机复制文件至创建的新镜像文件

image.png

5.ADD:类似于 COPY 指令,ADD 支持 tar 文件和 URL 路径

5.1、ADD <src> <dest> 5.2、ADD ["<src>",.... "<dest>"] 5.3、如果<src>为URL切<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<fimename>,如果<dest>以/结尾,则文件名URL指定的文件将被下载并保存为<dest>/fimename 5.4、如果<src>是一个压缩文件(tar),会被解压为一个目录,但是通过URL下载的tar文件不会被解压 5.5、如果是多个<src>,或者是同一个<src>使用了通配符,则<dest>必须是以/结尾的目录,如果<dest>不以/结尾,则<src>会被作为一个普通文件,<src>内容讲被写入到<dest>

6.WORKDIR:用于为 Dockerfile 中所有的 RUN、CMD、ENTRYPOINT、COPY、ADD 指定设定工作目录

image.png

7.VOLUME:数据卷,用于在 image 中创建挂载点目录,以挂载 Docker host 上的卷或者其他容器上的卷

7.1、VOLUM mount_point 7.2、VOLUM ["mount_point1","mount_point2"] 7.3、如果挂载点目录下有文件存在,docker run命令会在卷挂载完成后将所有文件复制到容器中

8.EXPOSE:为容器打开指定的监听端口以实现与外部通信

8.1、EXPOSE 1、:端口号 2、:协议类型,默认为TCP协议 EXPOSE 8080/tcp 8081/udp 8.2、不会直接对外暴露这里的端口,只有在run的时候加上-P(大写)才会将EXPOSE的端口暴露出去

9.ENV:用于为镜像定义所需的环境变量,可以被 Dockerfile 文件中其他命令调用(ENV、ADD、COPY、RUN、CMD)

image.png

10.RUN:docker build 镜像构建的时候需要执行的 shell 命令默认"/bin/sh -c"运行

10.1、docker build过程中需要执行的命令 10.2、RUN是在镜像构建完成之后运行结束 10.3、RUN执行的命令只能基于基础镜像的命令,执行之前先要确定基础镜像是否有该命令 10.4、一个Dockerfile可以写多个RUN 语法一、RUN command1 && command2....
1、通常是shell命令且以"/bin/sh -c"来运行它,此时运行为shell的子进程 2、进程在容器中的PID!=1,不能接收unix信号,当使用docker stop 将无法接收到 3、RUN echo "test_demo" > a.txt 此时可以使用shell特性 语法二、RUN ["executable","param1","param2"] 1、executable为要运行的命令 2、param1为命令运行的参数 3、不会以"/bin/sh -c"运行(非shell子进程),因此不支持shell操作符如变量替换和通配符(?,*等) 4、如果运行命令需要依赖shell特性可以增加参数,手动启动为shell的子进程 RUN ["/bin/bash","-c","executable","param1"] 5、list中的参数要使用双引号

11.CMD:启动容器指定默认要运行的程序或命令,默认"/bin/sh -c"运行

11.1、docker run过程中需要执行的命令 11.2、CMD运行结束后容器就将终止 11.3、CMD指定的命令将可以被 docker run 最后面的命令覆盖 11.4、一个Dockerfile写多个CMD只有最后一个CMD会生效 语法一、CMD command 1、通常是shell命令且以"/bin/sh -c"来运行它,此时运行为shell的子进程,能使用shell操作符 2、进程在容器中的PID!=1,不能接收unix信号,当使用docker stop 将无法接收到 3、CMD /bin/httpd -f -h ${httpd} 此时在运行容器的时候加-it参数无法进入交互式模式,需要使用docker exec进入交互模式 语法二、CMD ["executable","param1","param2"] 1、不会以"/bin/sh -c"运行(非shell子进程),因此不支持shell操作符如变量替换和通配符(?,*等) 2、如果运行命令需要依赖shell特性可以增加参数,手动启动为shell的子进程 CMD "/bin/bash","-c","executable","param1","param2" 语法三、CMD ["param1","param2"] 1、需要结合ENTRYPOINT指令提供默认参数使用

12.ENTRYPOINT:类型 CMD 指令的功能,用于为容器指定默认运行程序或命令

1、与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数覆盖,这些命令行参数会被当做参数传递给ENTRYPOINT指定的程序 2、docker run命令的 --entrypoint选项参数可以覆盖ENTRYPOINT指令指定的程序 3、一个Dockerfile中可以有多个ENTRYPOINT,但是只有最后一个会生效 4、ENTRYPOINT主要用于shell作为启动其他进程的父进程,后面跟的参数被当成子进程来启动 语法一:ENTRYPOINT command 语法二:ENTRYPOINT ["/bin/bash","param1","param2"]

13.CMD 和 ENTRYPOINT 同时存在 Dockerfile 中

1、CMD的值会当做参数传递给ENTRYPOINT 2、实现使用shell子进程启动httpd 3、如果docker run再传入参数,是传给ENTRYPOINT的,因为ENTRYPOINT有自己的参数,此时CMD参数会被ducker run后面跟的参数覆盖,并不是覆盖ENTRYPOINT的参数,要覆盖ENTRYPOINT的参数需要使用--entrypoint选项 CMD ["/bin/httpd/","-f"] ENTRYPOINT /bin/bash -c -h 通过传参启动容器 FROM python:latest LABLE auth="haili" ENV NGX_DOC_ROOT='/data/web/html' ADD entrypoint.sh /bin/ CMD ['/usr/sbin/nginx','-g','daemon off;'] ENTRYPOINT ['/bin/sh','-c','/bin/entrypoint.sh'] 1、先执行ENTRYPOINT,然后讲CMD的值当做参数传给ENTRYPOINT进行执行

14.USER:指定运行 image 时和 Dockerfile 中任何 RUN、CMD、ENTRYPOINT 指令指定的程序的用户

1、使用用户名或者UID 2、默认情况下container的运行身份为root用户 3、USER UID | user_name 4、UID 和 user_name必须存在/etc/passwd当中,否则会报错

15.HEALTHCHECK:健康检查,定义一个命令用于检查主进程工作状态是否健康

15.1、HEALTHCHECK参数 1、--interval=DURATION(default 30s) 健康检查间隔时间 2、--timeout=DURATION(default 30s) 超时时间 3、--start-period=DURATION(default 0s) 容器启动多久后执行健康检查 4、--retries=N(default 30s) 检测次数 15.2、检查结果 0:成功 1:失败 2:预留字段

15.3、举例 HEALTHCHECK --interval=5m --timeout=5s CMD curl -f http://localhost:8080 ||exit1

16.SHELL:指定运行 RUN、CMD、ENTRYPOINT 的 shell 程序

17.OPSIGNAL:给主进程发送信号

18.ARG:docker build 过程中的参数

18.1、定义pyton镜像作者,通过参数传入 FROM python ARG author="latest" LABLE author="${author}" 18.2、使用 docker build --build-arg author="haili" 18.3、常用在docker build 过程中替换参数

19.ONBUILD:用于在 Dockerfile 中定义一个触发器

19.1、Dockerfile1中加一个ONBUILD add file,当docker build -t=testpython Dockerfile1的时候ONBUILD指令不会被执行,Dockerfile2中FROM testpython(Dockerfile1构建后生成的镜像),当运行docker build -t=test Dockerfile2的时候Dockerfile1中的ONBUILD add file会被执行 19.2、Dockerfile用于build镜像文件,此镜像文件可以作为base image被另外一个Dockerfile作为FROM参数使用,并以之构建新的镜像文件 19.3、在后面这个Dockerfile中的FROM指令在build过程中被执行时,将触发创建其base image的Dockerfile中ONBUILD指定定义的触发器 19.4、尽管任何指令都可以注册为触发器指令,但是ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令 19.5、使用包含ONBUILD指令的Dockerfile构建镜像应该使用特殊标签如,python:1.0-onbuild 19.6、ONBUILD指令中使用ADD COPY指令要格外小心,因为新构建过程山下文缺少指定的源文件就会