前言

docker的系统学习可以看我这篇博文:https://www.cnblogs.com/zisefeizhu/p/11298818.html 有非常详细的讲解

容器现在都是用kubernetes来编排了, 存储、网络、都归Kubernetes层面管理了,所以对于docker的主要掌握点也就剩dockerfile了,这也是docker的重点。

简介

Dockerfile是一个文本文件,里面包含一条条指令,每一条指令就是一层镜像。

Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本镜像,第一条指令必须是FROM。一个声明以字符开头则被视为注释。

Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录。

Dockerfile中相对路径默认都是Dockerfile所在的目录。

Dockerfile中一定要惜字如金,能写到一行的指令,一定要写到一行,原因是分层构建,联合挂载这个特性。Dockerfile中每一条指令被视为一层。

Dockerfile中指明大写(约定俗成)

dockerfile 图解

dockerfile详解

FROM

指定基础镜像,并且必须是第一条非注释指令。

如果不以任何镜像为基础,那么写法为:FROM scratch。

同时意味着接下来所写的指令将作为镜像的第一层开始

语法:

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest
在一个 Dockerfile 文件中创建多个镜像时,FROM 可以多次出现。只需在每个新命令 FROM 之前,记录提交上次的镜像 ID。

LABEL

功能是为镜像指定标签

语法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...
一个Dockerfile种可以有多个LABEL,不建议这么写,最好是写成一行,如太长需要换行的话则使用\符号
LABEL会继承基础镜像中的LABEL,如遇到key相同,则值覆盖

ENV

设置环境变量

语法:

 ENV <key> <value>
ENV <key>=<value> ...
两者的区别就是第一种是一次设置一个,第二种是一次设置多个

ADD

一个复制命令,把文件复制到镜像中

如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用

语法:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径,推荐写成绝对路径
可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
如果把写成一个url,那么ADD就类似于wget命令
src为一个目录的时候,会自动把目录下的文件复制过去,目录本身不会复制
如果src为多个文件,dest一定要是一个目录
如果 docker 发现文件内容被改变,则接下来的指令都不会再使用缓存。关于复制文件时需要处理的/,基本跟正常的 copy 一致

COPY

看这个名字就知道,又是一个复制命令

语法:

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
与ADD的区别:
COPY的只能是本地文件,其他用法一致

RUN

功能为运行指定的命令

语法:

RUN <command>
RUN ["executable", "param1", "param2"]
第一种后边直接跟shell命令
在linux操作系统上默认 /bin -c
在windows操作系统上默认 cmd /S /C
第二种是类似于函数调用。
可将executable理解成为可执行文件,后面就是两个参数。
RUN 指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定 --no-cache 参数,如:docker build --no-cache。

CMD

功能为容器启动时要运行的命令

语法:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
第三种比较好理解了,就时shell这种执行方式和写法
第一种和第二种其实都是可执行文件加上参数的形式
举例说明两种写法:
CMD [ "sh", "-c", "echo $HOME"
CMD [ "echo", "$HOME" ]
这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。
原因是参数传递后,docker解析的是一个JSON array

RUN&&CMD

RUN是构件容器时就运行的命令以及提交运行结果
CMD是容器启动时执行的命令,在构件时并不运行,构件时仅仅指定了这个命令到底是做什么的

WORKDIR

设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。

语法:

WORKDIR /path/to/workdir
WORKDIR也可以解析环境变量
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
pwd的执行结果是/path/$DIRNAME

VOLUME

实现挂载功能,可以将宿主机目录挂载到容器中

可用专用的文件存储当作Docker容器的数据存储部分

语法:

VOLUME ["/data"]
使用场景为需要持久化存储数据时.
容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。
所以当数据需要持久化时用这个命令。
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
卷可以容器间共享和重用
容器并不一定要和其它容器共享卷
修改卷后会立即生效
对卷的修改不会对镜像产生影响
卷会一直存在,直到没有任何容器在使用它
VOLUME 让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。

USER

设置启动容器的用户,可以是用户名或UID

语法:

USER daemo
USER UID
如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行,
使用这个命令一定要确认容器中拥有这个用户,并且拥有足够权限。

ENTRYPOINT

启动时的默认命令

语法:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
第一种就是可执行文件加参数
第二种就是写shell

ENTRYPOINT&&CMD

相同点:
只能写一条,如果写了多条,那么只有最后一条生效
容器启动时才运行,运行时机相同
不同点:
ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖
如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数。
FROM ubuntu
ENTRYPOINT ["netstat", "-ln"]
CMD ["-tup"]
如果在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效
FROM ubuntu
ENTRYPOINT ["netstat", "-ln"]
CMD ls -l
那么将执行ls -l ,netstat -ln不会执行。

ARG

设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg =来指定参数

语法:

ARG <name>[=<default value>]
如果用户在build镜像时指定了一个参数没有定义在Dockerfile中,那么将有一个Warning
[Warning] One or more build-args [foo] were not consumed.
可以定义一个或多个参数
FROM busybox
ARG user1
ARG buildno
可以给参数一个默认值
FROM busybox
ARG user1=someuser
ARG buildno=1
如果给了ARG定义的参数默认值,那么当build镜像时没有指定参数值,将会使用这个默认值

HEALTHCHECK

容器健康状况检查命令

语法:

HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
第一个的功能是在容器内部运行一个命令来检查容器的健康状况
第二个的功能是在基础镜像中取消健康检查命令
[OPTIONS]的选项支持以下三中选项:
–interval=DURATION 两次检查默认的时间间隔为30秒
–timeout=DURATION 健康检查命令运行超时时长,默认30秒
–retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3
注意:
HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:
0: success - 表示容器是健康的
1: unhealthy - 表示容器已经不能工作了
2: reserved - 保留值
例:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/8080 || exit 1
健康检查命令是:curl -f http://localhost/8080 || exit 1
两次检查的间隔时间是5秒
命令超时时间为3秒

ONBUILD

用于在dockerfile中定义一个触发器,只对当前镜像的子镜像生效

语法:

ONBUILD [INSTRUCTION]
dockerfile用于build镜像文件,此镜像文件亦可作为base image被另一个dockerfile用作FROM指令参数,并以之构建新的镜像,在后面的dockerfile中的FROM指令在build过程中被执行时,将会触发创建其baseimage的dockerfile文件中的ONBUILD指令定义的触发器。
比如当前镜像为A,在Dockerfile种添加:
ONBUILD RUN ls -l
这个 ls -l 命令不会在A镜像构建或启动的时候执行
此时有一个镜像B是基于A镜像构建的,那么这个ls -l 命令会在B镜像构建的时候被执行。

EXPOSE

功能为暴漏容器运行时的监听端口给外部

语法:

EXPOSE <port>/<tcp/udp>
但是EXPOSE并不会使容器访问主机的端口
EXPOSE 指令并不会让容器监听 host 的端口,如果需要,需要在 docker run 时使用 `-p`、`-P` 参数来发布容器端口到 host 的某个端口上。

STOPSIGNAL

STOPSIGNAL命令是的作用是当容器停止时给系统发送什么样的指令,默认是15

语法:

STOPSIGNAL signal

Dockerfile中使用变量的方式

$varname
${varname}
${varname:-default value}
${varname:+default value}
第一种和第二种相同
第三种表示当变量不存在使用-号后面的值
第四种表示当变量存在时使用+号后面的值

原则及建议

容器轻量化。从镜像中产生的容器应该尽量轻量化,能在足够短的时间内停止、销毁、重新生成并替换原来的容器。

使用 .gitignore。在大部分情况下,Dockerfile 会和构建所需的文件放在同一个目录中,为了提高构建的性能,应该使用 .gitignore 来过滤掉不需要的文件和目录。

为了减少镜像的大小,减少依赖,仅安装需要的软件包。

一个容器只做一件事。解耦复杂的应用,分成多个容器,而不是所有东西都放在一个容器内运行。如一个 Python Web 应用,可能需要 Server、DB、Cache、MQ、Log 等几个容器。一个更加极端的说法:One process per container。

减少镜像的图层。不要多个 Label、ENV 等标签。

对续行的参数按照字母表排序,特别是使用apt-get install -y安装包的时候。

使用构建缓存。如果不想使用缓存,可以在构建的时候使用参数--no-cache=true来强制重新生成中间镜像。

实战

我的一篇docker实战博文

https://blog.csdn.net/zisefeizhu/article/details/90729970

再学dockerfile的更多相关文章

  1. 【C】 01 - 再学C语言

    “C语言还用再学吗?嵌入式工程师可是每天都在用它,大家早就烂熟于心,脱离语言这个层面了”.这样说不无道理,这门古老的语言以其简单的语法.自由的形式的而著称.使用C完成工作并不会造成太大困扰,所以很少有 ...

  2. [Python]再学 socket 之非阻塞 Server

    再学 socket 之非阻塞 Server 本文是基于 python2.7 实现,运行于 Mac 系统下 本篇文章是上一篇初探 socket 的续集, 上一篇文章介绍了:如何建立起一个基本的 sock ...

  3. 再学Java 之 interface的成员变量

    前言:最近在学多线程,写“哲学家就餐问题(Dining Philosophers)”的时候,需要定义一个全局的变量,即哲学家的人数.常用的做法是在其中一个类中定义一个static final的变量,然 ...

  4. 再学python类(终结篇)

    续写 初学python类,这几天吃坏东西了,拖着虚弱的身躯写的.有些乱请各位看官海涵. 声明:本人编程新手,还在学习中.所表述的东西都是基础语法之类的,分享我的学习笔记.还望多多指点,我一定虚心接受. ...

  5. 他学习一年Python找不到工作,大佬都说你别再学Python了!

    引言: 都说,滴水穿石非一日之功.然而有些人即使奋斗一辈子也比不上别人一年,别人学习一年比不得你学习一个月.其中缘由,有些人看了大半辈子还没看明白. 即使Python这么火,为何你学习一年的Pytho ...

  6. 一张图学dockerfile

        Dockerfile是为快速构建docker image而设计的,当你使用dockerbuild 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文 ...

  7. Java编码方式再学

    一直以来对编码方式对了解不是很深入.建议读下这几篇博文 学点编码知识又不会死:Unicode的流言终结者和编码大揭秘 编码研究笔记 这几篇博文上回答了内心存在的一些问题,这些问题可能也是大家经常遇到的 ...

  8. 不要再学 JSP 了,学 SpringBoot + Thymeleaf + Vue吧

    老读者就请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题. 读 ...

  9. 再学ajax--第二天 | 基于php+mysql+ajax的表单注册、登录、注销

    写在前面 ajax学习到了第二天,这次是用第一天封装的ajax函数,后端使用了php+mysql实现基本的注册,登录,注销. php是我前几个月get到的技能,我已经学习到了面向对象,知道各修饰符的含 ...

随机推荐

  1. Flutter ColorFiltered 将ColorFilter应用于其子级。

    ColorFiltered ColorFilter BlendMode Example <summary>main.dart</summary> import 'package ...

  2. SharedPreferences 数据传输中遇到的一些问题总结

    原构想:MainActivity 设置两个按钮,btn1--跳转Main2Activity通过复选框组选择并提交,btn2--跳转Main3Activity通过RecycleView显示选择结果. 主 ...

  3. 经典面试题:在浏览器地址栏输入一个 URL 后回车,背后发生了什么

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...

  4. vue路由理解

    vue路由:就是一个菜单的概念比如说有一个菜单栏,菜单栏上有很多按钮,当你点击一个按钮时会出现不同的页面,这就是vue路由

  5. Android获取OneNET云平台数据

    尝试HttpURLConnection "get"方式获取了www.baidu.com的数据后,试着获取OneNET云平台的设备数据(设备数据已成功上传至云平台) .java文件 ...

  6. xscan的安装和使用(作业整理)

    1.将学习通上下载的xscan.rar进行解压. 2.将缺少的.dll文件粘贴到软件解压目录中. 3.点击打开软件. 3.1在运行中除了发现缺少.dll文件的问题,我电脑又出现类似问题, 采取了关闭防 ...

  7. 基于 react + electron 开发及结合爬虫的应用实践🎅

    前言 Electron 是一个可以使用 Web 技术如 JavaScript.HTML 和 CSS 来创建跨平台原生桌面应用的框架.借助 Electron,我们可以使用纯 JavaScript 来调用 ...

  8. 关于python中的[::-1],[:,:,::-1]的反转理解

    其实就是单纯的关于反转,我们只需要记住每一个列表的中间有两个冒号: 即[a: b:c],意思是从a到b,间隔是c,因为经常省略c,所以经常看到[a:b]. 一.在一维数据中的反转 import num ...

  9. Java 基础加强 02

    基础加强·反射 和 枚举 类的加载概述和加载时机 * A:类的加载概述 * 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载.连接.初始化来实现对这个类的初始化 * 加载 * 就是指 ...

  10. TestLink测试用例管理工具使用说明

    TestLink使用说明 打开网页,登录账号:(这里的账号是已经注册过的,并且拥有admin权限,可以创建用户.当然也可以通过点击登录页面的"新用户注册"按钮进行注册,但是权限是g ...