Dockerfile

Dockerfile

Dockerfile 是用于构建Docker镜像的脚本文件,由一系列指令构成。通过docker build命令构建镜像时,Dockerfile中的指令会由上到下依次执行,每条指令都会构建出一个镜像。这就是镜像的分层。因此,指令越多,层次也就越多,创建的镜像也就越多,效率也会越低。

所以在定义Dockerfile时,能在一个指令完成的动作就不要分为两条。

scratch镜像与ADD指令

scratch镜像是一个空镜像,不能pull、runn。

ENV

【语法1】ENV <key> <value>

用于指定环境变量,这些环境变量,后续可以被RUN指令使用,容器运行起来后,也可以在容器中获取这些环境变量。

【语法2】 ENV <key>=<value1> <key2>=<value2> ...

可以设置多个变量,每个变量为一对<key>=<value>指定。

WORKDIR

【语法】WORKDIR path

容器打开后默认进入的目录,一般在后续的RUN、CMD、ENTRYPOINT、ADD等指令中会引用改目录。可以设置多个WORKDIR指令。后续WORKDIR指令若是用的是相对路径,则会基于之前WORKDIR指令指定的路径。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录

RUN

【语法1】RUN <command>

这里的command就是shell命令。docker build执行的过程中,会使用shell运行指定的command。

【语法2】RUN ["EXECUTABLE","PARAM1","PARAM2",...] 非shell,可执行命令

在docker build执行过程之中,会调用第一个参数"EXECUTABLE"指定的应用程序运行,并使用后面第二、三等参数作为应用程序的运行参数。

CMD

【语法1】CMD ["EXECUTABLE","PARAM1","PARAM2",...]

在容器启动之后,即在执行完 docker run 后会立即调用执行"EXECUTABLE"指定的可执行文件,并使用后面的第二、三等参数作为应用程序的运行参数。

【语法2】 CMD command param1 param2,...

这里的command就是shell命令,在容器启动之后会立即运行指定的shell命令。

【语法3】 CMD ["PARAM1","PARAM2",...]

提供给ENTERYPOINT的默认参数

dockerfile 复制代码
FROM centos:7
CMD cal

FROM centos:7
CMD ["cal"]
bash 复制代码
docker build -t mycal:1.0

我也可以把cal给替换掉

bash 复制代码
docker run mycal:1.0 date
bash 复制代码
docker build -f Dockerfile2 -t mycal:2.0 .
dockerfile 复制代码
FROM centos:7
CMD ["/bin/bash","-c","cal"]  

语法:CMD ["EXECUTABLE","PARAM1","PARAM2",...]

/bin/bash表示可执行文件,-c表示要执行的命令来源于命令行

其实就是用/bin/bash来执行cal

依旧还是不能加参数-y

结论:CMD的都不能用带选项的命令来替换

ENTRYPOINT

【语法1】ENTRYPOINT ["EXECUTABLE","PARAM1","PARAM2",...]

【解析】在容器启动过程中,也就是在执行docker run时,会调用执行"EXECUTABLE"指定的应用程序,并使用后面第二、三等参数作为应用程序的运行参数。

【语法2】ENTRYPOINT command param1 param2,...

【解析】这里的command就是shell命令。在容器启动过程中,也就是在执行docker run时,会运行指定的shell命令。

dockerfile 复制代码
FROM centos:7
ENTRYPOINT ["cal"]
dockerfile 复制代码
FROM centos:7
ENTRYPOINT ["/bin/bash","-c","cal"]
dockerfile 复制代码
FROM centos:7
ENTRYPOINT cal  不起作用
如果ENTRYPOINT发现后面是一个shell,直接就运行shell了,不会去进行拼接

FROM centos:7
ENTRYPOINT ["cal"]  OK
只有这种才会进行拼接

FROM centos:7
ENTRYPOINT ["/bin/bash","-c","cal"]  不起作用
因为这里的-y的作用对象变成/bin/bash了,会被直接忽略

CMD和ENTRYPOINT联用

dockerfile 复制代码
FROM centos:7
CMD ["hello world"]
ENTRYPOINT ["echo"]

CMD中的内容就是ENTRYPOINT的参数。

也就是 echo "hello world"

总结:Dockerfile中的[command]或者["EXCUTABLE"]如果是通过CMD指定的,该镜像的启动命令docker run 中是不能添加参数[ARG]的。一位内Dockerfile中的CMD是可以被命令中[COMMAND]替代的。

如果命令中的IMAGE后依旧有内容,此时对于docker daemon来说,其首先认为是替代用的[COMMAND],如果有两个或者两个以上的内容,后面的内容才会认为是[ARG]。所以,添加的-y会报错,因为没有-y这样的[COMMAND]。

ADD

【语法1】ADD<src> <dest>

【语法2】ADD ["<src>","<dest>"] #路径中存在空格时使用双引号引起来

【解析】该指令将赋值当前宿主机中指定文件src到容器中的指定目录dest中。src可以是宿主机中的绝对路径,也可以是相对路径。但是相对路径是相对于docker build命令所指定的路径的。src指定的文件可以是一个压缩文件,压缩文件复制到容器后会自动解压为目录。src也可以是一个URL,此时ADD指令相当于wget。src最好不要使目录,其会将该目录中的所有内容复制到指定目录中。dest是一个绝对路径,其最后面的路径必须要加上斜杠,否则系统会将最后的目录名称当作是文件名的。

COPY

【说明】功能和ADD指令相同,不过src不能是URL,如果src为压缩文件,复制到容器后也不会自动解压。

如果COPY zookeeper.tar.gz /opt/copy/ 没有最后的 / ,表示copy是一个文件

【建议】全都加上/

dockerfile 复制代码
FROM centos:7
WORKDIR /opt
ADD zookeeper.tar.gz /opt/add/
COPY zookeeper.tar.gz /opt/copy/
CMD ["/bin/bash"]

ARG

【语法】ARG <varname>[=<default value>]

【解析】定义一个变量,该变量将会使用于镜像构建时。若要定义多个变量,则需要定义多个ARG指令。

dockerfile 复制代码
FROM centos:7
ARG name=TOM
RUN echo $name

指定变量

bash 复制代码
docker build -t myargs:2.0 --build-arg name=Jerry .

前提是这个ARG在Dockerfile中存在

ONBUILD

【语法】ONUILD [INSTRUCTION]

【解析】该指令用于指定当前镜像的子镜像进行构建时要执行的指令。

dockerfile 复制代码
FROM centos:7
ENV WORKPATH /usr/local
WORKDIR $WORKPATH
ONBUILD RUN yum install -y wget
CMD ["/bin/bash"]
dockerfile 复制代码
FROM parent:1.0
bash 复制代码
docker build -f Dockerfile2 -t son:1.0 .

会在子镜像中安装wget

EXPOSE

【语法】RUN <port> [<port>...]

指定容器准备对外暴露的端口号,但该端口号并不会真正的对外暴露。如果要真的暴露,需要在执行docker run命令的时候使用-p来指定。

构建新镜像的方式总结

可以构建出新镜像的方式:

docker build

docker commit

docker import

docker compose

docker hub中完成Automated Builds

注意:docker load并没有构建出新的镜像,和原镜像是同一个镜像。

相关推荐
浮游本尊7 小时前
Java学习第22天 - 云原生与容器化
java
JuiceFS7 小时前
从 MLPerf Storage v2.0 看 AI 训练中的存储性能与扩展能力
运维·后端
渣哥8 小时前
原来 Java 里线程安全集合有这么多种
java
间彧8 小时前
Spring Boot集成Spring Security完整指南
java
间彧9 小时前
Spring Secutiy基本原理及工作流程
java
Java水解10 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆12 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学12 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole12 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊13 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端