linux怎么查看本机内存大小
230
2022-10-23
Dockerfile指令用法
切记:docker file 需要有一个工作目录 文件名开头要大写,所有需要用到的目录必须在这个目录或者子目录里面。如果目录里面有不需要打包进镜像里需要在“.dockeringore”文件中把文件名写进去
FROM
FROM指令是最重要的且必须为Dockerfile文件的开篇第一个非注释行,用于为镜像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境实践中,基准镜像可以是任何可用的镜像文件,默认情况下,docker build 会在docker主机上查找指定的镜像文件,在其不存在时,则会从docker hub registry上拉取所需的镜像文件
语法:
FROM
MAINTAINER 指定作者邮箱信息
用于让Dockerfile制作者提供本人的详细信息Dockerfile并不限制MAINTAINER指令可在出现的位置,单推荐将其放在FROM指令之后
语法:
MAINTAINER
COPY
用于从Docker主机复制文件至创建的新镜像文件
语法:
COPY
注意:在路径中有空白字符时,通常用第二种格式
文件复制准则
ADD
ADD指令类似COPY指令,ADD支持使用TAR和URL路径
语法:
ADD
操作准则
同COPY指令如果
WORKDIR
用于为Dockerfile中所有的RUN,CMD,ENTRYPOINT,COPY和ADD指定设定工作目录
语法:
WORKDIR
在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可为相对路径,不过,其相对路径是对此前一个WORKDIR指令的相对路径另外,WORKDIR也可以调用由ENV定义的变量
示例:
WORKDIR /var/usr/localWORKDIR $PATH
VOLUME
用于在image中创建一个挂在点目录,以Docker host上的卷或其它容器的卷
语法:
VOLUME VOLUME ["
EXPOSE 定义容器暴露的默认端口
用于为容器打开指定要监听的端口已实现与外部通讯
语法:
EXPOSE
注意:要真正让外部能访问到容器,需要在docker run 时加上-P选项
ENV
用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的指令(如ENV、ADD、COPY等)所调用调用格式为$variable_name或者${variable_name}
语法
ENV
第一种格式中,
RUN
用于指定docker bulid过程中运行的程序,其可以是任何命令
语法
RUN
第一种格式中
RUN ["/bin/sh","-c","exexcutable","param1","param2",....]
CMD 容器启动命令
类似于RUN指令,CMD也可以运行任何命令或应用程序,不过二者运行时间点不同 RUN指令运行在docker bulid构建为镜像文件的过程中,而CMD指令运行在基于Dockerfile构建出的镜像文件启动为为容器的过程中CMD指令的首要目的在于为启动容器指定默认要运行的程序,且其运行结束后容器也将终止,不过,CMD指令其可以被docker run时命令行选项所覆盖 CMD指令可以存在多个,但只有最后一个生效!
语法
CMD
前两种的意义都与RUN相同第三种语法则用于ENTRYPOINT指令提供默认参数
ENTRYPOINT
类似于CMD指令的功能,用于为容器指定默认运行层序,从而使得容器像一个单独可执行的程序,与CMD不同的是,有ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令还会被当做参数传递给ENTRYPOINT指定的程序 不过,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
语法
ENTRYPOINT
docker run 命令传入的命令参数会覆盖CMD指令的内容并附加到ENTRYPOINT命令最后作为其参数使用 Dockerfile文件中也可存在多个ENTRYPIONT指令,但仅有最后一个会生效
示例:利用entrypoint.sh脚本初始化nginx环境,可在docker run 通过-e选项对entyypoint.sh脚本传值
# dockerfile工作目录准备的文件[root@node01 NG_Dockerfile]# ls Dockerfile entrypoint.sh(+执行权限) index.html# entrypoint.sh文件,"注意要加执行权限"[root@node01 NG_Dockerfile]# cat entrypoint.sh #!/bin/sh#cat > /etc/nginx/conf.d/conf <
USER 指定当前用户
用于指定运行image时的或运行Dockerfile中任何RUN、CMD、或ENTRYPOINT指令指定的程序时的用户名或UID默认情况下,container的运行身份为root用户
语法:
USER
需要注意的是,
HEALTHCHECK 健康检查
"语法"
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。在没有 HEALTHCHECK 指令前,Docker 引擎只可以通过容器内主进程是否退出来判断容器是否状态异常。很多情况下这没问题,但是如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。在 1.12 以前,Docker 不会检测到容器的这种状态,从而不会重新调度,导致可能会有部分容器已经无法提供服务了却还在接受用户请求。而自 1.12 之后,Docker 提供了 HEALTHCHECK 指令,通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常,从而比较真实的反应容器实际状态。当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy。
HEALTHCHECK 支持下列选项:
--interval=<间隔>:两次健康检查的间隔,默认为 30 秒;--timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;--retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。 和 CMD, ENTRYPOINT 一样,HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。 在 HEALTHCHECK [选项] CMD 后面的命令,格式和 ENTRYPOINT 一样,分为 shell 格式,和 exec 格式。命令的返回值决定了该次健康检查的成功与否:0:成功;1:失败;2:保留,不要使用这个值。假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,我们可以用 curl 来帮助判断,其 Dockerfile 的 HEALTHCHECK 可以这么写:
FROM nginxRUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*HEALTHCHECK --interval=5s --timeout=3s \ CMD curl -fs || exit 1
这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs exit 1 作为健康检查命令。
使用 docker build 来构建这个镜像:
$ docker build -t myweb:v1 .
构建好了后,我们启动一个容器:
$ docker run -d --name web -p 80:80 myweb:v1
当运行该镜像后,可以通过 docker container ls 看到最初的状态为 (health: starting):
$ docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES03e28eb00bd0 myweb:v1 "nginx -g 'daemon off" 3 seconds ago Up 2 seconds (health: starting) 80/tcp, 443/tcp web
在等待几秒钟后,再次 docker container ls,就会看到健康状态变化为了 (healthy):
$ docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES03e28eb00bd0 myweb:v1 "nginx -g 'daemon off" 18 seconds ago Up 16 seconds (healthy) 80/tcp, 443/tcp web
如果健康检查连续失败超过了重试次数,状态就会变为 (unhealthy)。
为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr)都会被存储于健康状态里,可以用 docker inspect 来查看。
$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool{ "FailingStreak": 0, "Log": [ { "End": "2016-11-25T14:35:37.940957051Z", "ExitCode": 0, "Output": "\n\n
\nIf you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.
\n\nFor online documentation and support please refer to\n
\n\n\n", "Start": "2016-11-25T14:35:37.780192565Z" } ], "Status": "healthy"}ARG
语法
ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。在 1.13 之前的版本,要求 --build-arg 中的参数名,必须在 Dockerfile 中用 ARG 定义过了,换句话说,就是 --build-arg 指定的参数,必须在 Dockerfile 中使用了。如果对应参数没有被使用,则会报错退出构建。从 1.13 开始,这种严格的限制被放开,不再报错退出,而是显示警告信息,并继续构建。这对于使用 CI 系统,用同样的构建流程构建不同的 Dockerfile 的时候比较有帮助,避免构建命令必须根据每个 Dockerfile 的内容修改。
ONBUILD 为他人做嫁衣裳
语法
格式:ONBUILD <其它指令>。
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的。假设我们要制作 Node.js 所写的应用的镜像。我们都知道 Node.js 使用 npm 进行包管理,所有依赖、配置、启动信息等会放到 package.json 文件里。在拿到程序代码后,需要先进行 npm install 才可以获得所有需要的依赖。然后就可以通过 npm start 来启动应用。因此,一般来说会这样写 Dockerfile:
FROM node:slimRUN mkdir /appWORKDIR /appCOPY ./package.json /appRUN [ "npm", "install" ]COPY . /app/CMD [ "npm", "start" ]
把这个 Dockerfile 放到 Node.js 项目的根目录,构建好镜像后,就可以直接拿来启动容器运行。但是如果我们还有第二个 Node.js 项目也差不多呢?好吧,那就再把这个 Dockerfile 复制到第二个项目里。那如果有第三个项目呢?再复制么?文件的副本越多,版本控制就越困难,让我们继续看这样的场景维护的问题。
如果第一个 Node.js 项目在开发过程中,发现这个 Dockerfile 里存在问题,比如敲错字了、或者需要安装额外的包,然后开发人员修复了这个 Dockerfile,再次构建,问题解决。第一个项目没问题了,但是第二个项目呢?虽然最初 Dockerfile 是复制、粘贴自第一个项目的,但是并不会因为第一个项目修复了他们的 Dockerfile,而第二个项目的 Dockerfile 就会被自动修复。
那么我们可不可以做一个基础镜像,然后各个项目使用这个基础镜像呢?这样基础镜像更新,各个项目不用同步 Dockerfile 的变化,重新构建后就继承了基础镜像的更新?好吧,可以,让我们看看这样的结果。那么上面的这个 Dockerfile 就会变为:
FROM node:slimRUN mkdir /appWORKDIR /appCMD [ "npm", "start" ]
这里我们把项目相关的构建指令拿出来,放到子项目里去。假设这个基础镜像的名字为 my-node 的话,各个项目内的自己的 Dockerfile 就变为:
FROM my-nodeCOPY ./package.json /appRUN [ "npm", "install" ]COPY . /app/
基础镜像变化后,各个项目都用这个 Dockerfile 重新构建镜像,会继承基础镜像的更新。
那么,问题解决了么?没有。准确说,只解决了一半。如果这个 Dockerfile 里面有些东西需要调整呢?比如 npm install 都需要加一些参数,那怎么办?这一行 RUN 是不可能放入基础镜像的,因为涉及到了当前项目的 ./package.json,难道又要一个个修改么?所以说,这样制作基础镜像,只解决了原来的 Dockerfile 的前4条指令的变化问题,而后面三条指令的变化则完全没办法处理。
ONBUILD 可以解决这个问题。让我们用 ONBUILD 重新写一下基础镜像的 Dockerfile:
FROM node:slimRUN mkdir /appWORKDIR /appONBUILD COPY ./package.json /appONBUILD RUN [ "npm", "install" ]ONBUILD COPY . /app/CMD [ "npm", "start" ]
这次我们回到原始的 Dockerfile,但是这次将项目相关的指令加上 ONBUILD,这样在构建基础镜像的时候,这三行并不会被执行。然后各个项目的 Dockerfile 就变成了简单地:
FROM my-node
是的,只有这么一行。当在各个项目目录中,用这个只有一行的 Dockerfile 构建镜像时,之前基础镜像的那三行 ONBUILD 就会开始执行,成功的将当前项目的代码复制进镜像、并且针对本项目执行 npm install,生成应用镜像。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~