运维之我的docker-Dockerfile构建镜像详情
介绍 docker构建镜像就像java的编译代码工作一样“docker build -t centos7-nginx .”,这句话意思是自动寻找当前目录下的 Dockerfile文件进行构建(build)镜像,镜像名“centos7-nginx”,至于执行Dockerfile内的指令则是自上而下逐步进行的. 当然Dockerfile写起来很简单,但是希望大家遵循几个docker初创理念,同样是官方推荐用法: 1.你的docker尽量保持轻盈的,保证我们随时可以停止,删除,重新构建新的实现最小化的设置和配置。 这样就要求你在构建镜像时尽量创建一个空目录,在里面放入有效文件进行构建,如果实在无法避免就写一个.dockerignore文件把不必要的文件忽略 2.避免安装不必要的包,否则会增加你的镜像大小 3.每个容器尽量只运行一个进程,多个应用运行多个容器,这样更容易让你横向批量拓展。而不是把多个应用集成到一个容器内,当然如果你只是为了方便拷贝环境确实可以这么做,或者使用更聪明的link方法。 4.层数的最小化,可以说docekr里面每个指令都是一层。为了可读行,快速性方便你以后长期维护 5.当你一行的操作太长的时候尽量使用“\”去把各个操作分成更短的行方便你修改和查看 6.因为Dockerfile是由上向下执行,每个指令都会生成一个层默认会缓存构建结果。如果你最后一指令构建错了或做了修改,重新构建时只会执行最后一个指令。如果想去掉这个缓存请使用--no-cache=true docker在构建新的镜像时需要写一个Dockerfile文件里面描述了新的镜像是基于哪个镜像,中间需要哪些操作等等,下面做把镜像做比喻 docker创建镜像的创建想做饭一样: 1.首先我们准备一个干净厨房:目录`myp_w_picpath`,然后把需要的食材(文件)放到这 2.在目录里面写一个饭菜需要的:食谱“Dockerfile”,当然食谱是需要注明食材加入的先后顺序的 FROMregistry.cn-hangzhou.aliyuncs.com/forker/centos7#这里声明镜像是基于哪个镜像创建的 MAINTAINERbaishaohua #指定维护的人 RUNyum-y installsshd #给你的镜像执行特定操作相当于/bin/sh-c CMD/usr/sbin/sshd-D#一个dockerfile只能有一个CMD如果有多个只执行最后一个 LABELversion="1.0" #标签信息 EXPOSE #容器监听指定端口 上面是几个常用的,下面有几个:ENV,ADD,COPY,ENTRYPOINT,VOLUME,USER,WORKDIR 3.构建容器:材料准备好以后,下面就开始做饭了 [root@salt-node1 bai]#catDockerfile FROMcentos7 RUNyum-yinstall openssh-serveropenssh-clients CMD/usr/sbin/sshd -D [root@salt-node1 bai]#dockerbuild-tcentos7sshv1. SendingbuildcontexttoDockerdaemon2.048kB#docker确认build需要的信息 Step1:FROMcentos7 #引用指定的镜像到本地,这里ID是中间基础容器 --->00f6c5817350 Step2:RUNyum-yinstallopenssh-serveropenssh-clients#基于上面的容器运行RUN里面的命令生成新的基础容器 --->Usingcache --->c173480a6c42 Step3:CMD/usr/sbin/sshd-D #基于上面的容器运行RUN里面的命令生成新的基础容器并构建成镜像,删除临时容器 --->Runningine8072b88b11b --->ee81230261f1 Removing intermediatecontainere8072b88b11b Successfullybuilt ee81230261f1 4.运行新的容器 [root@salt-node1 bai]#dockerrun-d--name"testssh"-p8022:22centos7sshv2 cc225eff2520c47d54b264d5a338bb127933812d53e98f1c2b799bc8bb688f21 #########################| 华丽分割线 |################################### 下面详细介绍各个Dockerfile的参数,这里执行要大些 FROM FROM [base_p_w_picpath] 你的镜像基于哪个基础镜像进行构建的 MAINTAINER MAINTAINER operation@example.com 这个是显示镜像维护人 RUN 运行命令,有两种方式如下,它的运行原理是 /bin/sh -c 注意:1. 这里传递是通过json所以只能用双引号,2.他不会运行脚本所以执行的时候不能获取系统变量 RUN ps RUN ["executable", "param1", "param2"] LABEL 你可以通过标签让更多的人知道你的镜像信息例如:授权许可,帮助你的自动化,或者其它。 你可以添加一个开始标签,一个值或多个值。如果你的字符串包含空格请用双引号进行包裹。 举例: # Set one or more individual labelsLABEL com.example.version="0.0.1-beta"LABEL vendor="ACME Incorporated"LABEL com.example.release-date="2015-02-12"LABEL com.example.version.is-production="" # Set multiple labels on one lineLABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12" # Set multiple labels at once, using line-continuation characters to break long linesLABEL vendor=ACME\ Incorporated \ com.example.is-beta= \ com.example.is-production="" \ com.example.version="0.0.1-beta" \ com.example.release-date="2015-02-12" EXPOSE 用来指定容器监听哪些端口,但是容器并不会暴露这些端口给服务器,除非你启动容器时使用-P参数。 ENV 它将把容器内部的很多变量替换掉,用你指定的key ENV key=value ADD 把指定文件标准输入到镜像内,如果是压缩文件将会被自动解压,当然这里是 支持通配符 < dest >是一个绝对路径或相对路径WORKDIR,源将被复制在目的地的容器。 ADD hom* /mydir/ # adds all files starting with "hom" ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt" ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/ ADD test /absoluteDir/ # adds "test" to /absoluteDir/ ADD http://example.com/foobar / COPY 用法基本和ADD一致 ENTRYPOINT 有两种运行方式,他的主要作用:一些你常用的参数可以加到这里,当你执行的时候自动添加 ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred) ENTRYPOINT command param1 param2 (shell form) VOLUME 创建一个数据卷,这个是映射到系统的“/var/lib/docker/volumes/<容器ID>/_data/” 如果你重新构建镜像这个数据卷信息将被清除,注意:因为这里是为了构建一个标准json所以只能用双引号, 单引号是会报错的 VOLUME /opt/code/ VOLUME ["/data", "/opt"] USER RUN和ENTRYPOINT 将使用哪个用户运行 USER daemon WORKDIR 设置Dockerfile里面RUN, CMD, ENTRYPOINT, COPY 和ADD工作目录,如果WORKDIR不存在,它将被创建,即使它没有在任何后续的Dockerfile指令中使用。 ARG docker build时候的参数,如果命令中带有将不会被使用 ARG <name>[=<default value>] 1 FROM busybox 2 USER ${user:-some_user} 3 ARG user 4 USER $user … 构建docker时就可以传入参数 $ docker build --build-arg user=what_user Dockerfile 使用此Dockerfile示例,CONT_IMG_VER仍然保留在映像中,但其值为v1.0.0,因为它是ENV指令在第3行中的默认设置。 此示例中的变量扩展技术允许您从命令行传递参数,并通过利用ENV指令将它们持久保存在最终映像中。 仅对一组有限的Dockerfile指令支持变量扩展。 Docker有一组预定义的ARG变量,您可以在Dockerfile中使用相应的ARG指令。通过这个参数调用下面的变量 --build-arg <varname>=<value> HTTP_PROXY http_proxy HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy NO_PROXY no_proxy ONBUILD ONBUILD指令在镜像被用作另一个镜像的构建基础时,会触发执行的指令。 触发器将在下游构建的上下文中执行,就好像它已经在下游Dockerfile中的FROM指令之后立即插入指令。 任何构建指令都可以注册为触发器。 如果您正在构建将用作构建其他映像的基础的图像,例如应用程序构建环境或可以使用用户特定配置自定义的后台驻留程序,这将非常有用。 详解: 当build镜像时遇到ONBUILD时候它将插入一个触发器到镜像的metadata,他不会影响当前的构建 在构建结束时,所有触发器的列表存储在镜像的OnBuild清单中的key下。 可以使用docker inspect命令检查它们。 当build执行的时候第一个执行的是FROM 引用一个基础镜像引用后这一步并不会结束他会检查并执行触发器,如果触发器全部执行完成FROM才能算成功,否则只要一个触发器失败FROM就算失败 触发器在执行完成后会被清楚,也就是在新建的镜像中是不会集成这个触发器的 使用ONBUILD ONBUILD是不允许的,也就是不能自己触发自己,同样也不可以触发FROM和MAINTAINER [...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...] STOPSIGNAL 给系统发送退出信号(终止信号),该信号可以是与内核系统调用 “9”相似,或者是格式为SIGNAME的信号名称,例如SIGKILL。 STOPSIGNAL signal HEALTHCHECK HEALTHCHECK指令是在Docker 1.12版本加入,此指令有两种格式: HEALTHCHECK [OPTIONS] CMD command #在容器内运行一个命令检测容器健康 HEALTHCHECK NONE #禁止从基础镜像集成任何健康检测 描述 HEALTHCHECK 指令告诉docker如何去检测容器仍然在工作,例如你的web容器因为一个无限循环卡住无法创建新的连接它可以告诉容器不再健康,即使现在进程依然在运行。 容器的初始状态是‘starting’,如果健康检测容器正常他的状态会是'healthy'状态码为“0”, 如果健康检测出现连续失败会出现'unhealthy' 状态码为“1”,如果因为非健康执行退出则为“reserved”状态码为“2”。 参数介绍: 可以出现在CMD的参数: --interval=DURATION #默认间隔30s --timeout=DURATION #默认超时时间30s --retries=N #默认重试3次 HEALTHCHECK --interval=5m --timeout=3s \CMD curl -f http://localhost/|| exit 1 上面三个参数连贯起来就是,健康检测默认间隔5分钟运行一次,如果超过3秒则认为超时,如果尝试三次一直失败则认为容器不再健康执行"exit 1"。 假如说在Dockerfile里面多次出现这个参数,将会采用最后一个HEALTHCHECK 指令,这个是和CMD指令一样的。 如果你想获取容器现在的状态可以使用“docker inspect [CONTAINER ID ]”获取当前容器的health_status 下面是一些我写的其它帮助文档: 0.docker安装 阿里云加速你的docker 运行你第一个镜像实例-docker容器 docker命令参数 docker仓库使用和镜像提交 docker镜像构建构建及参数详解 docker镜像的导入导出 docker的网络 docker网络的测试示例 docker数据卷 docker的api和python sdk 单机多容器的编排-compose docker-swarm集群的管理-swarm docker-swarm集群管理详解 docker-swarm集群中删除节点和服务 docker自建仓库Registry 使用技巧和推荐 docker集群web页面管理工具 不要再给你的docker安装ssh server compose快速创建zookeeper集群