计算机系统应用教程网站

网站首页 > 技术文章 正文

dockerfile详解 dockerfile详解add与copy

btikc 2024-09-27 01:13:55 技术文章 6 ℃ 0 评论

dockerfile文件的格式

一是:# comment。二是:INSTRUCTION arguments 指令和参数,其中约定俗成是指令使用大写,参数小写,但是dockerfile文件本身不区分大小写。

dockerfile文件内的指令是自上而下一次顺序执行,通常是一行一个指令,如果指令有相互依赖关系一定要注意指令的先后顺序。

dockerfile文件内的第一个非注释行都是以'FROM'指令,它用来指定做当前镜像是基于那个基础镜像来实现,所以我们的镜像制作都是建立在某个已存在的基础镜像上(如果没有指定基础镜像默认情况下docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件,如果仓库中也没有那么dockerfile也无法制作,那就比较麻烦。),dockerfile文件内的指令也都是基于当前基础镜像的指令,基础镜像没有或不支持的指令也将是无法执行的,所以dockerfile的制作环境都是底层基础镜像启动的容器提供的环境。

dockerfile配置文件

必须有一个专门的目录文件放置Dockerfile文件,而Dockerfile的文件的首字母必须是大写,且如果Dockerfile文件中需要安装的安装包或引用的文件也必须和Dockerfile文件在同一个目录文件内,不能是这个目录文件外的内容,但可以是这个文件内的子目录的内容。

dockeringore文件又是另外的一个文件,所有写在dockeringore文件中的路径文件,在Dockerfile配置文件中打包时那个路径文件都不会被打包进去,一般一行一个文件,当然也可以使用通配符。

docker build通过读取Dockerfile文件来制作镜像,打上标签推到仓库就可以使用了。

Dockerfile编写规则

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

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

3、文件名必须是Dockerfile

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

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

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

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

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

dockerfile文件中的环境变量

变量赋值:变量名=赋值

变量引用:$variable_name or ${variable_name}

给变量默认值:

${变量名:-字符串}:如果parameter没被赋值或其值为空,就以string作为默认值,它不会赋值给变量

${变量名:=字符串}:如果parameter没被赋值或其值为空,就以string作为默认值,它会赋值给变量(用户没有传递值)

${变量名:+字符串}:如果parameter没被赋值或其值为空,就什么都不做,否则用string替换变量内容

dockerfile的指令

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

4.1、COPY <src> <dest>

4.2、COPY ["<src>",.... "<dest>"]

4.3、<src>:要复制的源文件或目录,支持使用通配符

1、<src>必须是build上下文中的路径,不能是其父目录路径

2、如果<src>是目录,则其内部文件和子目录都会被递归复制,但是<src>目录本身不会被复制

3、如果指定了多个<src>,或者<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾

4.4、<dest>:目标路径,即正在创建的images的文件系统路径

1、建议使用绝对路径,否则COPY指定以WORKDIR为其实路径

2、如果<dest>不存在,将会被自动创建,包括其父目录路径一起创建

4.5、复制文件

COPY testFile /mnt

4.6、复制目录

COPY testDir /mnt/testDir

1、testDir下所有文件和目录都会被递归复制

2、目标路径要写testDir,否则会复制到/mnt下

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

5.1、ADD <src> <dest>

5.2、ADD ["<src>",.... "<dest>"]

5.4、如果<src>是一个压缩文件(tar),会被解压为一个目录,但是通过URL下载的tar文件不会被解压

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

6.1、WORKDIR /mnt,如果目录不存在会自动创建,包括他的父目录

6.2、一个Dockerfile中WORKDIR可以出现多次,其路径也可以为相对路径,相对路径是基于前一个WORKDIR路径

6.3、WORKDIR也可以调用ENV指定的变量

6.4:举例

from python:latest

workdir /mnt

run touch a.txt

workdir /usr

run touch b.txt

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

7.1、VOLUM mount_point

7.2、VOLUM ["mount_point1","mount_point2"]

7.3、如果挂载点目录下有文件存在,docker run命令会在卷挂载完成后将所有文件复制到容器中

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

8.1、EXPOSE <port> </portocol>

1、<port>:端口号

2、</portocol>:协议类型,默认为TCP协议

EXPOSE 8080/tcp 8081/udp

8.2、不会直接对外暴露这里的端口,只有在run的时候加上-P(大写)才会将EXPOSE的端口暴露出去

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

9.1、ENV key value

1、key之后的所有内容都会被视为value,因此,一次只能设置一个变量

9.2、ENV key=value

1、可以设置多个变量,每个key=value键值对为一个变量

2、如果value中包含空格需要用反斜杠转义,也可以对value加引号进行标识,反斜杠也可以用于续行

9.3、调用格式:$variable_name 或 ${variable_name}

9.4、定义多个变量建议使用第二种方式,以便在同一层中完成

9.5、举例

ENV DOC_DIR=/mnt/doc

COPY index.html ${DOC_DIR:-/mnt/doc}

#-:如果DOC_DIR不存在则使用-后面的默认值

#+:如果DOC_DIR存在则使用+后面的值

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中的参数要使用双引号

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指令提供默认参数使用

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"]

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进行执行

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

1、使用用户名或者UID

2、默认情况下container的运行身份为root用户

3、USER UID | user_name

4、UID 和 user_name必须存在/etc/passwd当中,否则会报错

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

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

STOPSIGNAL:给主进程发送信号

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 过程中替换参数

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指令要格外小心,因为新构建过程山下文缺少指定的源文件就会失败

Dockerfile文件测试:

[root@localhost /]# mkdir images

[root@localhost /]# vim /images/Dockerfile

[root@localhost /]# vim /images/index.html

[root@localhost /]# cp -R /etc/yum.repos.d/ /images/

[root@localhost /]# ls -la /images/

[root@localhost /]# vim /images/Dockerfile

COPY 如果<src>是目录,则其内部文件和子目录都会被递归复制,但是<src>目录本身不会被复制。
在Dockerfile文件,每一条指令都会增加一个镜像层,所以能把两个指令合成一条就合成一条,能一条搞定的指令绝不分成两条指令,镜像层越多,以后联合挂载的效率越差。

进入当前目录制作镜像:

[root@localhost /]# cd /images/

[root@localhost images]# docker build -t testhttpd:v0.1 ./

做好的镜像

启动容器并查看并验证Dockerfile文件中的打包文件是否存在

[root@localhost images]# docker run --name test1 -it --rm testhttpd:v0.1

也可不用进入交互式模式,直接使用shell命令查看

[root@localhost images]docker run --name test1 -it --rm testhttpd:v0.1 ls -la /etc/

[root@localhost images]docker run --name test1 -it --rm testhttpd:v0.1 ls -la /data/web

COPY和ADD指令的区别

WORKDIR指令:指定当前工作目录

VOLUME指令:指定docke容器管的卷的目录。

验证查看指定docker管理的卷

[root@localhost images]# docker run --name test2 -it --rm testhttpd:v0.2 mount

EXPOE指令:暴露对外端口,这里的端口暴露只是对内的ip地址的暴露,如果需要在宿主机的地址上暴露,在启动容器时需要加上-p选项,容器会自动暴露Dockerfeil文件中EXPOE指令指定的端口。

基于以上Dockerfeil文件制作容器:

[root@localhost images]# docker build -t testhttpd:v0.3 ./

启动容器并运行指定的httpd服务而不是容器默认的程序进程,-f运行在前台-h并指定httpd服务程序的家目录。

[root@localhost images]#docker run --name test3 -it --rm testhttpd:v0.3 /bin/httpd -f -h /data/web/html

查看容器信息里test3容器的ip地址

[root@localhost ~]# docker inspect test3

[root@localhost ~]# curl 192.168.100.3

[root@localhost images]# docker run --name test4 -it -P --rm testhttpd:v0.3 /bin/httpd -f -h /data/web/html

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

ENV DOC_DIR=/mnt/doc

COPY index.html ${DOC_DIR:-/mnt/doc}

#-:如果DOC_DIR不存在则使用-后面的默认值

#+:如果DOC_DIR存在则使用+后面的值

输出容器的环境变量:

[root@localhost images]# docker run --name test1 -it -P --rm testhttpd:v0.1 printenv

在启动容器时也可以加上-e选项重新给变量赋值如:

docker run --name test1 -it -P --rm -e DOC_ROOT="/data/mysql/" testhttpd:v0.1

RUN指令:

CMD指令:

[root@localhost images]# docker image inspect web:v0.1 查看镜像详情

[root@localhost images]# docker run --name testweb -it --rm -P web:v0.1

这里的命令加上-it参数也是没有用的因为http是没有交互式接口的,所以就出现来卡在下面的界面。

[root@localhost ~]# docker exec -it testweb /bin/sh

从下图中可以看出默认启动的程序进程已经被改变了。

ENTRYPOINT指令:

测试:例如运行nginx让nginx灵活接受配置文件

一:在dockerHUB上下载nginx基础镜像.

[root@localhost images]# docker pull nginx:1.23.1-alpine

我这里下载的是nginx的alpine的为基础镜像,也可以直接下载docker pull nginx

二:编辑Dockerfeil文件以及entrypoint.sh脚本(脚本使用的是/bin/sh.而不是/bin/bash/因为nginx的基础镜像是alpine版本不支持/bin/bash)

注意:这里使用单引号可能会报错,应使用双引号。

entrypoint.sh脚本

[root@localhost images]# vim entrypoint.sh

这里的$@表示脚本的所有参数传递的参数是什么脚本就运行什么, exec $@是替换当前的进程

[root@localhost images]# vim index.html

编辑网页文件

[root@localhost images]# docker build -t myweb:v0.1 ./

制作镜像 (测试中,容器启动报错,没成功)

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表