编写Dockerfiles最佳技术实践_第1页
编写Dockerfiles最佳技术实践_第2页
编写Dockerfiles最佳技术实践_第3页
编写Dockerfiles最佳技术实践_第4页
编写Dockerfiles最佳技术实践_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 编写Dockerfiles最佳技术实践目 录 TOC o 1-3 h z u HYPERLINK l _Toc60741912 1.理解构建上下文 PAGEREF _Toc60741912 h 3 HYPERLINK l _Toc60741913 2.基于stdin的构建上下文 PAGEREF _Toc60741913 h 4 HYPERLINK l _Toc60741914 3.使用stdin的Dockerfile从本地上下文构建镜像 PAGEREF _Toc60741914 h 5 HYPERLINK l _Toc60741915 4.使用stdin的Dockerfile从远程上下文构建

2、镜像 PAGEREF _Toc60741915 h 5 HYPERLINK l _Toc60741916 5.通过.dockerignore排除文件 PAGEREF _Toc60741916 h 6 HYPERLINK l _Toc60741917 6.使用多阶段构建 PAGEREF _Toc60741917 h 6 HYPERLINK l _Toc60741918 7.解耦应用程序 PAGEREF _Toc60741918 h 7 HYPERLINK l _Toc60741919 8.最小化层数 PAGEREF _Toc60741919 h 7 HYPERLINK l _Toc6074192

3、0 10.利用构建缓存 PAGEREF _Toc60741920 h 8 HYPERLINK l _Toc60741921 11.Dockerfile指令 PAGEREF _Toc60741921 h 9 HYPERLINK l _Toc60741922 12.FROM PAGEREF _Toc60741922 h 9 HYPERLINK l _Toc60741923 13.LABEL PAGEREF _Toc60741923 h 9 HYPERLINK l _Toc60741924 14.RUN PAGEREF _Toc60741924 h 10 HYPERLINK l _Toc607419

4、25 15.官方镜像的例子 PAGEREF _Toc60741925 h 19本文介绍了构建高效镜像的建议最佳实践和方法。Docker通过读取Dockerfile中的指令自动构建镜像,一个文本文件包含构建镜像的所有指令。Dockerfile遵循特定的格式和指令集,您可以在Dockerfile中引用它们。Docker镜像由只读层组成,每一层代表一个Dockerfile指令集。每一层都是前一层变化的增量。考虑这个Dockerfile:FROMubuntu:18.04COPY . /appRUN make /appCMDpython/app/app.py每条指令创建一个层:FROM 从ubuntu:

5、18.04基础镜像创建一个层。COPY 从Docker客户端当前目录中添加文件。RUN 使用make构建你的应用。CMD 指定容器运行时执行的命令。当你运行一个镜像生成一个容器,在底层的顶部添加一个可写层(容器层)。对正在运行容器所做的所有更改,比如写文件,修改已存在的文件,和删除文件,都被写入这个可写空口层。Dockerfile定义的容器应该生成尽可能短暂的容器,通过“短暂”,我们的意思是容器可以被停止或销毁,然后重建并用最小的设置和配置。从而充分利用容器的分层存储。1.理解构建上下文执行dockerbuild命令时,当前工作目录称为构建上下文。 默认情况下,假定Dockerfile位于此处

6、,但您可以使用文件标志(-f)指定其他位置。 无论Dockerfile实际存在于何处,当前目录中的所有文件和目录的递归内容都将作为构建上下文发送到Docker守护程序。构建上下文件示例:创建并CD进入构建上下文目录,将“hello”写入名为hello的文本文件中,并创建一个在其上运行cat的Dockerfile。从构建上下文(.)中构建镜像。mkdirmyproject & cd myprojectecho hello helloecho -e FROMbusyboxCOPY /hello /RUN cat /hello Dockerfiledocker build -t helloapp:v

7、1 .将Dockerfile和hello移动到单独的目录中并构建映像的第二个版本(不依赖于上一次构建的缓存)。使用-f指向Dockerfile并指定构建上下文的目录:mkdir -p dockerfiles contextmv Dockerfile dockerfiles & mv hello contextdocker build -no-cache -t helloapp:v2 -f dockerfiles/Dockerfile context无意中包含构建不必要的文件会导致更大的构建上下文和更大的镜像,这将增加构建时间,拉取和推送镜像的时间以及容器运行时占用更多的存储空间。查看构建上下文

8、大小,在构建Dockerfile时查找类似信息。Sending buildcontext to Docker daemon 187.8MB2.基于stdin的构建上下文Docker能通过stdin与本址或远程构建上下文管道Dockerfile来构建镜像。通过stdin管道Dockerfile对于执行一次性构建非常有用,无需将Dockerfile写入磁盘,或者在生成Dockerfile的情况下,并且之后不应该持久化。例如,以下命令是等效的:echo -e FROMbusyboxRUN echo hello world | docker build docker build-EOFFROM bus

9、yboxRUN echohello worldEOF在Dockerfile不需要将文件复制到映像中并且提高构建速度的情况下,省略构建上下文非常有用,因为没有文件发送到守护程序。注意:如果使用此语法,尝试构建镜像时使用COPY或ADD的Dockerfile将失败,以下示例说明了这一点:# create a directory to work inmkdir examplecd example # create anexample filetouch somefile.txt docker build t myimage:latest -EOFFROM busyboxCOPYsomefile.tx

10、t .RUN cat /somefile.txtEOF # observethat the build fails.Step 2/3 :COPY somefile.txt .COPY failed:stat /var/lib/docker/tmp/docker-builder249218248/somefile.txt: no such file ordirectory3.使用stdin的Dockerfile从本地上下文构建镜像使用此语法使用本地文件系统上下文构建镜像,但使用stdin中的Dockerfile。语法使用-f(-file)选项指定要使用的Dockerfile,使用连字符(-)作为

11、文件名来指示Docker从stdin读取Dockerfiledocker buildOPTIONS -f- PATH下面的示例使用当前目录(.)作为构建上下文,并使用stdin作为Dockerfile构建镜像。# create adirectory to work inmkdir examplecd example # create anexample filetouchsomefile.txt # build animage using the current directory as context, and a Dockerfile passed throughstdindocker b

12、uild-t myimage:latest -f- . EOFFROM busyboxCOPYsomefile.txt .RUN cat/somefile.txtEOF4.使用stdin的Dockerfile从远程上下文构建镜像使用此语法使用远程git仓库上下文构建镜像,但使用stdin中的Dockerfile。语法使用-f(-file)选项指定要使用的Dockerfile,使用连字符(-)作为文件名来指示Docker从stdin读取Dockerfile。dockerbuildOPTIONS-f-PATH如果您希望从仓库构建映像不包含Dockerfile,或者您希望使用自定义Dockerfil

13、e构建,而不维护自己的仓库分支,则此语法非常有用。下面的示例使用stdin中的Dockerfile构建映像,并在GitHub上的“hello-world”Git仓库中添加README.md文件。docker build -t myimage:latest -f- /docker-library/hello-world.git /numberDocker使用/bin/sh -c解释器执行这些命令,该解释器仅评估管道中最后一个操作的退出代码以确定成功。在上面的示例中,只要wc -l命令成功,即使wget命令失败,此构建步骤也会成功并生成新映像。如果希望命令由于管道中任何阶段的错误而失败,请在之前添

14、加set -o pipefail &,以确保意外错误可防止构建无意义的镜像。例如:RUN set -opipefail & wget -O - https:/some.site | wc -l /number并不是所有shell都支持 o pipefail在基于Debian的映像上的dash shell的情况下,请考虑使用RUN的时候明确选择支持pipefail选项的shell。 例如:RUN/bin/bash,-c,set-opipefail&wget-O-https:/some.site|wc-l/numberCMDCMD指令应该用于运行镜像包含的软件以及任何参数。CMD应该几乎总是以CM

15、D “executable”,“param1”,“param2”的形式使用。因此,如果镜像用于服务,例如Apache和Rails,则可以运行类似CMD“apache2”,“ - DFOREGROUND”的内容。实际上,建议将这种形式的指令用于任何基于服务的镜像。在大多数其他情况下,CMD应该被赋予一个交互式shell,例如bash,python和perl。例如,CMD “perl”,“ - de0”,CMD “python”或CMD “php”,“ - a”。使用这个表单意味着当你执行像docker run -it python这样的东西时,你将被放入一个可用的shell中,准备就绪。 CMD

16、应该很少以CMD “param”,“param”的方式与ENTRYPOINT一起使用,除非您和您的预期用户已经非常熟悉ENTRYPOINT的工作原理。EXPOSEEXPOSE指令指示容器侦听连接的端口。因此,您应该为您的应用程序使用通用的传统端口。 例如,包含Apache Web服务器的映像将使用EXPOSE 80,而包含MongoDB的映像将使用EXPOSE 27017等。对于外部访问,您可以执行docker run,该标志指示如何将指定端口映射到他们选择的端口。对于容器链接,Docker为从接收容器返回源的路径提供环境变量(即MYSQL_PORT_3306_TCP)。ENV为了使新软件更易

17、于运行,您可以使用ENV更新容器安装的软件的PATH环境变量。 例如,ENV PATH/usr/local/nginx/bin:$PATH确保CMD “nginx”正常运行。ENV指令对于提供特定于您希望容纳的服务的必需环境变量也很有用,例如Postgress的PGDATA。最后,ENV还可用于设置常用版本号,以便更容易维护版本,如以下示例所示:ENV PG_MAJOR9.3ENV PG_VERSION 9.3.4RUN curl -SL/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress& ENV PATH/usr/local/

18、postgres-$PG_MAJOR/bin:$PATH类似于在程序中使用常量变量(解耦硬编码),此方法允许您更改单个ENV指令以自动神奇地破坏容器中的软件版本。每条ENV都会创建一个新的中间层,就像RUN命令一样。这意味着即使您在将来的镜像中取消设置环境变量,它仍然会在此镜像层中保留,并且其值可以导出。您可以通过创建如下所示的Dockerfile来测试它,然后构建它。FROM alpineENV ADMIN_USER=markRUN echo$ADMIN_USER ./markRUN unsetADMIN_USER $ docker run-rm test sh -c echo $ADMIN

19、_USERmark要防止这种情况,并且实际上取消环境变量,请使用带有RUN命令执行shell执行 set和unset变量。您可以使用; 或分隔命令。如果您使用第二种方法,并且其中一个命令失败,则docker构建也会失败。这通常是一个好办法。使用作为Linux Dockerfiles的行连续符可以提高可读性。 您还可以将所有命令放入shell脚本中,并使用RUN命令运行该shell脚本。FROM alpineRUN export ADMIN_USER=mark & echo $ADMIN_USER ./mark & unset ADMIN_USERCMD sh$ docker run-rm te

20、st sh -c echo $ADMIN_USERADDor COPY尽管ADD和COPY在功能上相似,但一般来说,COPY是优选的。那是因为它比ADD更透明。COPY仅支持将本地文件复制到容器中,而ADD具有一些功能(如本地的tar提取和远程URL支持),这些功能并不是很明显。 因此,ADD的最佳用途是将本地tar文件自动提取到镜像中,如ADD rootfs.tar.xz /所示。如果您有多个使用上下文中不同文件的Dockerfile步骤,请单独复制它们,而不是一次复制它们。 这可确保每个步骤的构建缓存仅在特定所需文件更改时失效(强制重新执行该步骤)。例如:COPY requirements

21、.txt /tmp/RUN pipinstall -requirement /tmp/requirements.txtCOPY . /tmp/由于镜像大小很重要,因此强烈建议不要使用ADD从远程URL获取包。你应该使用curl或wget代替。这样,您可以删除提取后不再需要的文件,也不必在图像中添加其他镜像层。 例如,你应该避免做以下事情:ADD /big.tar.xz /usr/src/things/RUN tar -xJf/usr/src/things/big.tar.xz -C /usr/src/thingsRUN make -C/usr/src/things all最佳做法:RUN mk

22、dir -p/usr/src/things & curl -SL/big.tar.xz | tar-xJC /usr/src/things & make -C /usr/src/things all对于不需要ADD的tar自动提取功能的其他项目(文件,目录),应始终使用COPY。ENTRYPOINTENTRYPOINT的最佳用途是设置图像的主程序,允许该镜像执行命令一样运行(然后使用CMD作为默认标志)。让我们从命令行工具s3cmd的镜像示例开始:ENTRYPOINTs3cmdCMD-help现在可以像这样运行镜像来显示命令的帮助:$ docker runs3cmd或使用正确的参数执行命令:$

23、 docker runs3cmd ls s3:/mybucket这个很有用,因为镜像名称可以兼作二进制文件的引用,如上面的命令所示。ENTRYPOINT指令也可以与辅助脚本结合使用,使其能够以与上述命令类似的方式运行,即使启动该工具可能需要多个步骤。例如,Postgres官方镜像使用以下脚本作为其ENTRYPOINT:#!/bin/bashset -eif $1 = postgres ; then chown -R postgres $PGDATA if -z $(ls -A$PGDATA) ; then gosu postgres initdb fi exec gosu postgres $

24、fiexec$配置应用进程PID为1此脚本使用exec Bash命令,以便最终运行的应用程序成为容器的PID 1.这允许应用程序接收发送到容器的任何Unix信号。帮助程序脚本被复制到容器中并通过容器启动时的ENTRYPOINT运行:COPY./docker-entrypoint.sh /ENTRYPOINT/docker-entrypoint.shCMDpostgres该脚本允许用户以多种方式与Postgres交互。它可以简单地启动Postgres:$ docker runpostgres或者,它可用于运行Postgres并将参数传递给服务器:$ docker runpostgres postgres -help最后,它还可以用来启动一个完全不同的工具,比如Bash:$ docker run rmit postgres bashVOLUMEVOLUME指令用于挂载由docker容器创建的任何数据库存储区域,配置存储或文件/文件夹。强烈建议您将VOLUME用于镜像的任何可变或用户可维护部分。USER如果服务可以在没有权限的情况下运行,请使用USER更改为非root用户。首先在Dockerfile中创建用户和组,例如RUN groupadd -r postgres & useradd -n

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论