DockerFile在我理解就是可以将所需要构建镜像的功能、组件都天前配置好,然后直接生成一个Image,而不是先生成镜像,再通过修改容器的方法来生成最终需要的镜像。
  镜像的定值实际上就是定值每一层所需要添加的配置、文件,将每一层修改、安装、构建、操作的命令都写入一个脚本,最后使用脚本来构建镜像。Dockerfile的每一条指令(instruction)构建一层,描述了该层该如何构建。

Dockerfile的构建

docker build [选项] <上下文路径/URL/->

Dockerfile上下文(context)

一般情况下构建镜像docker build 最后都会有一个.,表示当前目录,有些人会认为这是指定Dockerfile的所在路径,但是其实是在指定上下文路径。在构建镜像的时候,docker build得知上下文路径后,会将该路径下所有东西打包,然后上传给Docker 引擎,Docker引擎就回获得构建镜像所需要的一切文件。
  需要访问打包的文件,必须以./开头,并不是指当前路径,而是上下文环境。应该讲Dockerfile置于一个空目录下,或者项目根目录下,如果该上下文环境有不希望传给Docker引擎的,可以使用.gitignore一样的语法写一个.dockerignore来剔除不需要的环境。

其他Docker builc的用法

直接使用Git repo构建

docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14

用给定的tar包构建

docker build build.tar.gz

DockerFile指定

FROM 指定基础镜像

必选,而且是第一条指令,在制定基础镜像。

FROM nginx

有一个特殊的镜像名为scratch,是虚拟的概念,表示一个空白的镜像,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在,使用Go预研开发的应用很多会使用这种方式来制作镜像。

FROM scratch

RUN 执行命令

用于执行命令,相当于命令行,格式有两种:
shell格式:RUN <命令>,相当于在命令行中写命令。
exec格式:RUN["可执行文件","参数1", "参数2"],相当于函数调用中的格式。

RUN echo 'hello world' > /usr/share/nginx/html/index.html

Dockerfile会将每一个命令视为一层,所以一般使用RUN都是结合&&来将多个RUN视为一层,避免产生臃肿、多层的镜像,增加构建时间而且容易出错。

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps

末尾使用了\的方式,以及行首#进行注释的格式,可以让维护、更为容易。另外,可以在这一组命令最后添加清理工作的命令,删除为了编译固件所需要的软件,并且还清理了qpt缓存文件,可以有效避免镜像臃肿

COPY 复制文件

格式:

COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]

与RUN命令类似,有shell以及函数式调用,将从上下文目录中的源路径复制到一个新的镜像内的目标路径。源路径可以是多个,可以使用通配符,需要满足Go语言的filepath Match规则。
  目标路径可以使容器内的绝对路径,也可以是相对路径,目标路径不需要手动创建,Docker会自动创建确实的目录。
  需要注意的是拷贝过去的文件会保留源文件的特性,比如读写权限、文件变更时间等。

ADD 高级的复制文件

ADD可以理解为一个升级版本的COPY,源路径可以是一个URL(下载之后的文件权限为600);如果源路径是一个tar压缩文件、格式为gzip、bzip2以及xz的情况下,ADD指令可以自动解压该文件到目标路径中。所以这个命令一般用于解压文件更多。
  Docker官方建议尽可能使用COPY,因为ADD语音不明确,并且ADD会另镜像构建缓存失效,从而可能另镜像构建的比较缓慢。因此仅在需要自动解压的情况下使用ADD。

CMD 容器启动命令

和RUN相似,但是CMD、ENTERPOINT、HEALTHCHECK只能出现一次,写了多个只会使用最后一个。两种格式:

shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

我们知道Docker不是虚拟机,而容器就是一个进程而已,那么在启动容器的时候就需要指定容器运行的程序以及参数,CMD指令就是用于指定默认的容器主进程的启动命令的。
  在ubuntu默认CDM是/bin/bash,直接docker run -it会直接进入bash,也可以通过手动docker run -it imageid cat /etc/os-release的方式替换默认CMD,打印系统版本信息。
  一般推荐exec的指令格式,会被解析为JSON数组,一定使用双引号而不是单引号。如果直接使用shell格式的话会被包装为sh -c的参数形式执行

CMD echo $HOME
CMD ["sh","-c","echo $HOME"]

这也就是我们为什么可以使用环境变量的原因,因为这些环境变量会被shell进行解析处理。
  另外Docker不是虚拟机,容器中没有后台执行服务的概念,不能使用upstart/systemd去执行后台服务。比如nginx服务

CMD service nginx start

其实会启动之后就立刻推出,甚至systemctl命令根本无法执行。容器中启动进程就是容器应用进程,容器就是为了主进程而存在的,主进程退出容器也就失去了意义。nginx启动应该为:

CMD ["nginx","-g","daemon off;"]

因为service nginx start会被理解为CMD["sh","-c""service nginxstart"],因此主进程是sh,当service nginx start执行完,sh也就结束了,sh作为主进程推出就会导致容器推出。

ENTERPOINT 入口点

作用和CMD类似,都是在容器启动程序及参数,ENTERPOINT在运行时候也可以替代,但是比CMD要繁琐,需要通过docker run的参数 -entrypoint来指定。当指定了ENTERPOINT之后,CMD就不再是直接的运行命令,而是将CMD的内容作为参数传递给ENTERPOINT指令,相当于:

<ENTERPOINT> "<CMD>"

那么有什么用呢?

让镜像变成命令一样使用

有些情况下构建的镜像我们可以当做一个应用直接使用命令行调用,但是使用CMD的构建是写死的。比如获取公网IP:

FROM ubuntu:16:04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD ["curl","-s","http://ip.cn"]

docker build -t myip .构建镜像之后,只需要执行docker run myip就可以查看当前的公网ip。但是如果我们现在想修改一下使用别的参数,比如希望显示http头信息,需要加上-i参数,那么使用docker run myip -i是一定不可行的。因为跟在镜像名后边的command运行时候会替换CMD默认值,相当于直接执行-i,所以绝对不会成功,这个时候就可以使用ENTERPOINT。

FROM ubuntu:16:04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*

然后直接调用docker run myip -i就可以正常执行,相当于curl -s http://ip.cn -i,CMD的内容会作为参数传递给ENTERPOINT,而这里个-i就是新的CMD,和ENTERPOINT组合成新的CMD。

ENV 环境变量

只是设置环境变量,无论是后边其他的任何命令RUN等都可以直接使用这里的环境变量,使用{ENV_NAME}来引用,格式:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>

比如:

ENV NODE_VERSION =7.2.0 DEBUG=on \
NAME="lzy"
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"

以下的指令支持环境变啦ing的展开:
ADD 、 COPY 、 ENV 、 EXPOSE 、 LABEL 、 USER 、 WORKDIR 、 VOLUME 、 STOPSIGNAL 、 ONBUILD
  通过环境变量,我们可以让一份Dockerfile制作更多的镜像,只需要使用不同的环境变量即可。

ARG 构建参数

与ENV想类似,设置环境变量,但是ARG的环境变量在最终声称的容器中不会存在,但是不存在不意味着可以保存密码之类的东西,因为在docker history中也会看到。该值所设置的环境变量可以在docker build时候shiyong --build-arg <参数名>=<值>来覆盖。格式:

ARG <参数名>[=<参数值>]

VOLUME定义匿名卷

如果在容器中进行数据输出,那么最终数据不会被保存,对于需要动态保存数据的应用,应该保存与卷volume中,为了避免用户忘记动态文件所保存目录挂载为卷,可以实现指定默写目录挂载为匿名卷,如果用户不指定挂载,应用也可以正常运行,不会向容器存储层写入大量数据。格式为:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
#比如
COLUME /data

上述的/data就会在运行时候自动挂载为匿名卷,运行时也可以覆盖这个挂载设置

docker run -d -v mydata:/data xxxx

上述就是使用了mydata目录来挂载到了/data位置,替代了Dockerfile中匿名卷的挂载配置。

EXPOSE 声明端口

生命运行时候容器提供服务端口,只是一个生命,在运行时候不会因为这个生命就会开启这个端口。主要作用是帮助镜像使用者理解这个镜像服务的守护端口,方便配置映射。另外就是使用随机端口映射时候docker run -P可以自动随机映射expose的端口。格式为:

EXPOSE <端口1> [<端口2>...]

expose和运行时候指定-p 宿主端口:容器端口不同,-p用户映射宿主端口和容器端口,将容器对应端口公开给外界访问。expose仅仅是生命容器打算使用什么端口而已,并不会自动在宿主机进行端口映射。

WORKDIR 指定工作目录

首先,Dockerfile中不同于执行shell命令,每一层都是不同的运行环境如下的命令一定会报/app/world.txt不存在的错误。

RUN cd /app
RUN echo "hello" > world.txt

第一层的cd /app仅仅是当前进程的工作目录变更,一个内存上的变化而已,结果不会造成任何文件变更。第二层时候是一个全新的容器,自然不可能集成前一层的内存变化,所以如果想是想cd /app的效果,必须使用WORKDIR指令来更改工作空间,并且如果目录不存在,WORKDIR会帮我们建立目录。

USER 指定当前用户

USER <用户名>

USER和WORKDIR类似,都会改变环境状态并影响到以后的层。WORKDIR是改变工作目录,USER是改变之后层的执行RUN、CMD、ENTERPONIT等命令的身份,用户必须提前建立好,否则无法切换

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN ["redis-server"]

HEALTHCHECK 健康检查

HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

告知Docker如何判断容器的状态是否正常,于1.12版本引入。当镜像制定了healthcheck指令,指定一行命令之后,勇气启动容器,初始状态为starting,在HEALTHCHECK指令检查陈宫之后变为healthy,如果连续一定次数失败,则会变成unhealthy。HEALTHCHECK支持的选项有:

interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3 次。

ARG

语法:

ARG <name>[=<default value>]

设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<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镜像时没有指定参数值,将会使用这个默认值

ONBUILD

语法:

ONBUILD [INSTRUCTION]

这个命令只对当前镜像的子镜像生效。

比如当前镜像为A,在Dockerfile种添加:

ONBUILD RUN ls -al

这个 ls -al 命令不会在A镜像构建或启动的时候执行

此时有一个镜像B是基于A镜像构建的,那么这个ls -al 命令会在B镜像构建的时候被执行。

STOPSIGNAL

语法:

STOPSIGNAL signal

STOPSIGNAL命令是的作用是当容器推出时给系统发送什么样的指令

HEALTHCHECK

容器健康状况检查命令

语法有两种:

1. HEALTHCHECK [OPTIONS] CMD command
2. 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/ || exit 1

健康检查命令是:curl -f http://localhost/ || exit 1

两次检查的间隔时间是5秒

命令超时时间为3秒

DockerFile语法【h】的更多相关文章

  1. 四:(之五)Dockerfile语法梳理和实践

    *5.Dockerfile语法梳理和实践 5.1 尽量使用官方的image作为base image 5.2 metadata:指明作者 版本 描述 5.3 每一条run都能形成一个分层,避免无用分层应 ...

  2. Dockerfile语法梳理

    Dockerfile语法 我们先来看一下上篇的 Dockerfile #获取base image FROM adoptopenjdk/openjdk8:latest #类似于执行 linux指令 RU ...

  3. dockerfile语法

    dockerfiles的指令不区分大小写,但约定为全部大写 dockerfiles支持如下语法命令: 1.FROM <image name> 所有的dockerfile都必须以from命令 ...

  4. dockerfile语法规则

    编写Dockerfile 在前面的章节,我们学习了通过docker命令来下载镜像,运行镜像,在容器中部署自己的程序,最后将容器提交到自己的镜像中.但是,这并不是Docker推荐的镜像构建方式.在这一章 ...

  5. dockerfile 语法

    基本语法格式:INSTRUCTION arguments (指令+参数)不分大小写 注释格式:# 注释 第一个指令必须是FROM,标示使用什么镜像 1.解析器指令 解析器指令是可选的,并且影响处理Do ...

  6. Dockerfile语法简介

    Dockerfile是由一系列命令和参数构成的脚本,一个Dockerfile里面包含了构建整个image的完整命令.Docker通过docker build执行Dockerfile中的一系列命令自动构 ...

  7. 一文学会Dockerfile语法

    接应上篇,续讲前文.今天咱来聊一下Dockerfile的使用 . 虽然可以通过docker commit命令来手动创建镜像,但是通过Dockerfile文件,可以帮助我们自动创建镜像,并且能够自定义创 ...

  8. 四:(之八_Linux压力测试工具stress)Dockerfile语法梳理和实践

    8.1 安装stress stress目前是在该目录下的可执行文件 --vm 创建几个进程 --vm-bytes 为每个进程分配多少内存 8.2 debug输出stress创建进程的过程 一直在创建有 ...

  9. 四:(之六_镜像发布)Dockerfile语法梳理和实践

    *6.镜像发布 1>注册Docker Hub账号并登陆. build的镜像名称格式必须是: dockerhub账户名/标识: 使用docker login在项目目录下登录: 浏览器: 2> ...

随机推荐

  1. python基础语法1 用户交互,基本数据类型,格式化输出,运算符

    与用户交互: 输入: python2: input一定要声明你输入的类型 >>> input(">>:") >>:sean Traceba ...

  2. ava 类似jest snapshot 功能试用

    ava也提供了类似jest 的snapshot 测试,可以用来方便的测试web 组件,以下是一个简单的试用, 同时包含了自己碰到问题,以及解决方法,以及一些参考链接 使用typescript 以及ts ...

  3. asyncapi 指南

    asyncapi 是可以用来创建异步机器可读定义api的指南,我们可以用来创建事件驱动的架构. 说明 asyncapi 的定义类似openapi,目前指南版本为2.0,很值得学习下 参考资料 http ...

  4. Kafka的基本概念

    Kafka的前身是由LinkedIn开源的一款产品,2011年初开始开源,加入了 Apache 基金会,2012年从 Apache Incubator 毕业变成了 Apache 顶级开源项目. Top ...

  5. 求等差数列前$n$项和$S_n$的最值

    一.方法依据: 已知数列\(\{a_n\}\)是等差数列,首项为\(a_1\),公差为\(d\),前\(n\)项和为\(S_n\),则求\(S_n\)的最值常用方法有两种: (1).函数法:由于\(S ...

  6. python url码转换 chr()码

    爬虫生成带搜索词语的网址 1.字符串转为url编码 import urllib poet_name = "李白" url_code_name = urllib.quote(poet ...

  7. linux netstat 命令简介

    常用选项: -r, --route 显示路由表 -i, --interfaces 显示接口信息表-s, --statistics 显示网络协议汇总信息 -n, --numeric 不解析域名-p, - ...

  8. java项目里classpath具体指哪儿个路径

    一.classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目 ...

  9. js读取sqlserver数据库,输出至html

    代码: <!DOCTYPE html> <html> <head>   <meta charset="utf-8">   <m ...

  10. 论文阅读:Single Image Dehazing via Conditional Generative Adversarial Network

    Single Image Dehazing via Conditional Generative Adversarial Network Runde Li∗ Jinshan Pan∗ Zechao L ...