文章目录
深入Dockerfile
前言
博主语录:一文精讲一个知识点,多了你记不住,一句废话都没有
经典语录:一厢情愿,就得愿赌服輸
一、命令说明
Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。
一般而言,Dockerfile可以分为四部分
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 启动时执行指令
指令 | 说明 |
FROM | 指定基础镜像 |
MAINTAINER | 指定维护者信息,已经过时,可以使用LABELmaintainer-xxx来替代 |
RUN | 运行命令v |
CMD | 指定启动容器时默认的命令v |
ENTRYPOINT | 指定镜像的默认入口.运行命令v |
EXPOSE | 声明镜像内服务监听的端口v |
ENV | 指定环境变量,可以在docker run的时候使用-e改变v;会被固化到image的config里面 |
ADD | 复制指定的src路径下的内容到容器中的dest路径下,src可以为url会自动下载,可以为tar文件,会自动解压 |
cOPY | 复制本地主机的src路径下的内容到镜像中的dest路径下,但不会自动解压等 |
LABEL | 指定生成镜像的元数据标签信息 |
VOLUME | 创建数据卷挂载点 |
USER | 指定运行容器时的用户名或UID |
WORKDIR | 配置工作目录,为后续的RUN、CMD、ENTRYPOINT指令配置工作目录 |
ARG | 指定镜像内使用的参数(如版本号信息等),可以在build的时候,使用--build-args改变v |
OBBUILD | 配置当创建的镜像作为其他镜像的基础镜像是,所指定的创建操作指令 |
STOPSIGNAL | 容器退出的信号值 |
HEALTHCHECK | 健康检查 |
SHELL | 指定使用shell时的默认shel类型 |
二、FROM
FROM 指定基础镜像,最好挑一些 apline , slim 之类的基础小镜像
scratch 镜像是一个空镜像,常用于多阶段构建
如何确定我需要什么要的基础镜像?
- Java应用当然是java基础镜像(SpringBoot应用)或者Tomcat基础镜像(War应用)
- JS模块化应用一般用nodejs基础镜像
- 其他各种语言用自己的服务器或者基础环境镜像,如python、golang、java、php等
三、LABEL
标注镜像的一些说明信息。
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
四、RUN
- RUN指令在当前镜像层顶部的新层执行任何命令,并提交结果,生成新的镜像层。
- 生成的提交映像将用于Dockerfile中的下一步。 分层运行RUN指令并生成提交符合Docker的核心概念,就像源代码控制一样。
- exec形式可以避免破坏shell字符串,并使用不包含指定shell可执行文件的基本映像运行RUN命令。 可以使用SHELL命令更改shell形式的默认shell。 在shell形式中,您可以使用\(反斜杠)将一条RUN指令继续到下一行。
总结:什么是shell和exec形式
五、CMD和ENTRYPOINT
5.1、都可以作为容器启动入口
CMD 的三种写法:
- CMD ["executable","param1","param2"] ( exec 方式, 首选方式)
- CMD ["param1","param2"] (为ENTRYPOINT提供默认参数)
- CMD command param1 param2 ( shell 形式)
ENTRYPOINT 的两种写法:
- ENTRYPOINT ["executable", "param1", "param2"] ( exec 方式, 首选方式)
- ENTRYPOINT command param1 param2 (shell 形式)
5.2、只能有一个CMD
- Dockerfile中只能有一条CMD指令。 如果您列出多个CMD,则只有最后一个CMD才会生效。
- CMD的主要目的是为执行中的容器提供默认值。 这些默认值可以包含可执行文件,也可以省略可执行文件,在这种情况下,您还必须指定ENTRYPOINT指令。
5.3、CMD为ENTRYPOINT提供默认参数
- 如果使用CMD为ENTRYPOINT指令提供默认参数,则CMD和ENTRYPOINT指令均应使用JSON数组格式指定。
5.4、组合最终效果
无ENTRYPOINT | ENTRYPOINTexec_entryp1_entry | ENTRYPOINT["exec_entry"pl_entry"] | |
无CMD | 错误不允许的写法;容器没有启动命令 | /bin/sh-cexec_entryp1_entry | exec_entry pl_entry |
CMD[exec_cmd","pl_cmd"] | exec_cmd p1_cmd | /bin/sh-cexec_entryp1l_entry | exec_entry p1_entryexec_cmd p1_cmd |
CMD["p1_cmd","p2_cmd"] | p1_cmd p2_cmd | /bin/sh-cexec_entrypl_entry | exec_entryp1_entry p1_cmdp2_cmd |
CMDexec_cmdp1_cmd | /bin/sh-c exec_cmdp1_cmd | /bin/sh-cexec_entrypl_entry | exec_entry p1_entry/bin/sh-c exec_cmdp1_cmd |
这条竖线,总是以ENTRYPOINT的为准 | 这条竖线,ENTRYPOINT和CMD共同作用 |
5.5、docker run启动参数会覆盖CMD内容
六、ARG和ENV
6.1、ARG
- ARG指令定义了一个变量,用户可以在构建时使用--build-arg = 传递,docker build命令会将其传递给构建器。
- --build-arg 指定参数会覆盖Dockerfile 中指定的同名参数
- 如果用户指定了 未在Dockerfile中定义的构建参数 ,则构建会输出 警告 。
- ARG只在构建期有效,运行期无效
- 不建议使用构建时变量来传递诸如github密钥,用户凭据等机密。因为构建时变量值使用docker history是可见的。
- ARG变量定义从Dockerfile中定义的行开始生效。
- 使用ENV指令定义的环境变量始终会覆盖同名的ARG指令。
6.2、ENV
- 在构建阶段中所有后续指令的环境中使用,并且在许多情况下也可以内联替换。
- 引号和反斜杠可用于在值中包含空格。
- ENV 可以使用key value的写法,但是这种不建议使用了,后续版本可能会删除
- docker run --env 可以修改这些值
- 容器运行时ENV值可以生效
- ENV在image阶段就会被解析并持久化(docker inspect image查看),参照下面示例。
6.3、综合测试示例
七、ADD和COPY
7.1、COPY
COPY 的两种写法
- --chown功能仅在用于构建Linux容器的Dockerfiles上受支持,而在Windows容器上不起作用
- COPY指令从 src 复制新文件或目录,并将它们添加到容器的文件系统中,路径为 dest 。
- 可以指定多个 src 资源,但是文件和目录的路径将被解释为相对于构建上下文的源。
- 每个 src 都可以包含通配符,并且匹配将使用Go的filepath.Match规则进行。
7.2、ADD
同 COPY 用法,不过 ADD 拥有自动下载远程文件和解压的功能。
注意:
- src 路径必须在构建的上下文中; 不能使用 ../something /something 这种方式,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护程序。
- 如果 src 是URL,并且 dest 不以斜杠结尾,则从URL下载文件并将其复制到 dest 。
- 如果 dest 以斜杠结尾,将自动推断出url的名字(保留最后一部分),保存到 dest
- 如果 src 是目录,则将复制目录的整个内容,包括文件系统元数据。
八、WORKDIR和VOLUME
8.1、WORKDIR
- WORKDIR指令为Dockerfile中跟随它的所有 RUN,CMD,ENTRYPOINT,COPY,ADD 指令设置工作目录。 如果WORKDIR不存在,即使以后的Dockerfile指令中未使用它也将被创建。
- WORKDIR指令可在Dockerfile中多次使用。 如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径。 例如:
- 也可以用到环境变量
8.2、VOLUME
作用:把容器的某些文件夹映射到主机外部
写法:
注意:
用 VOLUME 声明了卷,那么以后对于卷内容的修改会被丢弃,所以, 一定在 volume 声明之前修改内容 ;
九、USER
写法:
USER 指令设置运行映像时要使用的用户名(或 UID )以及可选的用户组(或 GID ),以及 Dockerfile中USER 后面所有 RUN , CMD 和 ENTRYPOINT 指令。
十、EXPOSE
- EXPOSE指令通知Docker容器在运行时在指定的网络端口上进行侦听。 可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。
- EXPOSE指令实际上不会发布端口。 它充当构建映像的人员和运行容器的人员之间的一种文档,即有关打算发布哪些端口的信息。 要在运行容器时实际发布端口,请在docker run上使用-p标志发布并映射一个或多个端口,或使用-P标志发布所有公开的端口并将其映射到高阶端口。
十一、multi-stage builds
多阶段构建
11.1、使用
https://docs.docker.com/develop/develop-images/multistage-build/
解决:如何让一个镜像变得更小 ; 多阶段构建的典型示例
11.2、生产示例
docker build --build-arg url="git address" -t demo:test . :自动拉代码并构建镜像
自己 写一个多阶段构建
- 1、自动从git下载指定的项目
- 2、把项目自动打包生成镜像
- 3、我们只需要运行镜像即可
十二、Images瘦身实践
- 选择最小的基础镜像
- 合并RUN环节的所有指令,少生成一些层
- RUN期间可能安装其他程序会生成临时缓存,要自行删除。如:
- 使用 .dockerignore 文件,排除上下文中无需参与构建的资源
- 使用多阶段构建
- 合理使用构建缓存加速构建。[--no-cache]
学习更多 Dockerfile 的写法: https://github.com/docker-library/
十三、springboot java 最终写法
- 📢博客主页:https://lansonli.blog.csdn.net
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨