永利总站网址

如何编写最佳的Dockerfile

十月 11th, 2019  |  永利总站手机版

译者按:Dockerfile的语法非常简单,然而如何加快镜像构建速度,如何减少Docker镜像的大小却不是那么直观,需要积累实践经验。这篇博客可以帮助你快速掌握编写Dockerfile的技巧。

Dockerfile

  • 原文:How to write excellent Dockerfiles

  • 译者:Fundebug

Docker 可以通过 Dockerfile 的内容来自动构建镜像。Dockerfile
是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据
Dockerfile 的内容构建镜像,在介绍如何构建之前先介绍下 Dockerfile
的基本语法结构。

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

Dockerfile 有以下指令选项:

我已经使用Docker有一段时间了,其中编写Dockerfile是非常重要的一部分工作。在这篇博客中,我打算分享一些建议,帮助大家编写更好的Dockerfile。

FROM
MAINTAINER
RUN
CMD
EXPOSE
ENV
ADD
COPY
ENTRYPOINT
VOLUME
USER
WORKDIR
ONBUILD

目标:

    • 更小的Docker镜像大小
  • 更少的Docker镜像层

    • 增加Dockerfile可读性
  • 让Docker容器使用起来更简单

7.1 FROM
用法:
FROM <image>

总结

  • 编写.dockerignore文件

    • 将多个RUN指令合并为一个
  • 基础镜像的标签不要用latest

  • 每个RUN指令后删除多余文件

  • 选择合适的基础镜像(alpine版本最好)

  • 设置WORKDIR和CMD

  • 使用ENTRYPOINT

  • 在entrypoint脚本中使用exec

  • COPY与ADD优先使用前者

  • 合理调整COPY与RUN的顺序

  • 设置默认的环境变量,映射端口和数据卷

  • 使用LABEL设置镜像元数据

  • 添加HEALTHCHECK

或者
FROM <image>

示例

示例Dockerfile犯了几乎所有的错。接下来,我会一步步优化它。假设我们需要使用Docker运行一个Node.js应用,下面就是它的Dockerfile(CMD指令太复杂了,所以我简化了,它是错误的,仅供参考)。

FROM ubuntuADD . /appRUN apt-get update RUN apt-get upgrade -y RUN
apt-get install -y nodejs ssh mysql RUN cd /app && npm install# this
should start three processes, mysql and ssh# in the background and node
app in foreground# isn’t it beautifully terrible? <3CMD mysql & sshd
& npm start

docker build -t wtf .

FROM指定构建镜像的基础源镜像,如果本地没有指定的镜像,则会自动从 Docker
的公共库 pull 镜像下来。
FROM必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile
从FROM语句开始。
FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile
中创建多个镜像。
如果FROM语句没有指定镜像标签,则默认使用latest标签。

1. 编写.dockerignore文件

构建镜像时,Docker需要先准备context,将所有需要的文件收集到进程中。默认的context包含Dockerfile目录中的所有文件,但是实际上,我们并不需要.git目录,node_modules目录等内容。.dockerignore的作用和语法类似于.gitignore,可以忽略一些不需要的文件,这样可以有效加快镜像构建时间,同时减少Docker镜像的大小。示例如下:

.git/node_modules/

7.2 MAINTAINER
用法:
MAINTAINER <name>

2. 容器只运行单个应用

从技术角度讲,你可以在Docker容器中运行多个进程。你可以将数据库,前端,后端,ssh,supervisor都运行在同一个Docker容器中。但是,这会让你非常痛苦:

  • 非常长的构建时间(修改前端之后,整个后端也需要重新构建)

    • 多个应用的日志难以处理(不能直接使用stdout,否则多个应用的日志会混合到一起)
  • 横向扩展时非常浪费资源(不同的应用需要运行的容器数并不相同)

  • 僵尸进程问题 – 你需要选择合适的init进程

因此,我建议大家为每个应用构建单独的Docker镜像,然后使用Docker
Compose运行多个Docker容器。

现在,我从Dockerfile中删除一些不需要的安装包,另外,SSH可以用docker
exec替代。示例如下:

FROM ubuntuADD . /appRUN apt-get update RUN apt-get upgrade -y# we
should remove ssh and mysql, and use# separate container for database
RUN apt-get install -y nodejs # ssh mysql RUN cd /app && npm installCMD
npm start

指定创建镜像的用户
RUN 有两种使用方式
RUN
RUN “executable”, “param1”,
“param2”

3. 将多个RUN指令合并为一个

Docker镜像是分层的,下面这些知识点非常重要:

  • Dockerfile中的每个指令都会创建一个新的镜像层。

    • 当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
  • 某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效

  • 镜像层是不可变的,如果我们再某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件(只是这个文件在Docker容器中不可见了)。

Docker镜像类似于洋葱。它们都有很多层。为了修改内层,则需要将外面的层都删掉。记住这一点的话,其他内容就很好理解了。

现在,我们将所有的RUN指令合并为一个。同时把apt-get upgrade删除,因为它会使得镜像构建非常不确定(我们只需要依赖基础镜像的更新就好了)

FROM ubuntuADD . /appRUN apt-get update \ && apt-get install -y nodejs
\ && cd /app \ && npm installCMD npm start

记住一点,我们只能将变化频率一样的指令合并在一起。将node.js安装与npm模块安装放在一起的话,则每次修改源代码,都需要重新安装node.js,这显然不合适。因此,正确的写法是这样的:

FROM ubuntuRUN apt-get update && apt-get install -y nodejs ADD . /app
RUN cd /app && npm installCMD npm start

每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的版本控制。
exec 方式会被解析为一个 JSON 数组,所以必须使用双引号而不是单引号。exec
方式不会调用一个命令 shell,所以也就不会继承相应的变量,如:
RUN [ “echo”, “$HOME” ]

4. 基础镜像的标签不要用latest

当镜像没有指定标签时,将默认使用latest标签。因此,FROM ubuntu指令等同于FROM ubuntu:latest。当时,当镜像更新时,latest标签会指向不同的镜像,这时构建镜像有可能失败。如果你的确需要使用最新版的基础镜像,可以使用latest标签,否则的话,最好指定确定的镜像标签。

示例Dockerfile应该使用16.04作为标签。

FROM ubuntu:16.04 # it’s that easy!RUN apt-get update && apt-get
install -y nodejs ADD . /app RUN cd /app && npm installCMD npm start

这种方式是不会达到输出 HOME 变量的,正确的方式应该是这样的
RUN [ “sh”, “-c”, “echo”, “$HOME” ]

5. 每个RUN指令后删除多余文件

假设我们更新了apt-get源,下载,解压并安装了一些软件包,它们都保存在/var/lib/apt/lists/目录中。但是,运行应用时Docker镜像中并不需要这些文件。我们最好将它们删除,因为它会使Docker镜像变大。

示例Dockerfile中,我们可以删除/var/lib/apt/lists/目录中的文件(它们是由apt-get
update生成的)。

FROM ubuntu:16.04RUN apt-get update \ && apt-get install -y nodejs \
# added lines && rm -rf /var/lib/apt/lists/*ADD . /app RUN cd /app &&
npm installCMD npm start

RUN产生的缓存在下一次构建的时候是不会失效的,会被重用,可以使用–no-cache选项,即docker
build –no-cache,如此便不会缓存。
7.3 CMD
CMD有三种使用方式:
CMD
“executable”,”param1″,”param2″
CMD
“param1″,”param2”
CMD command param1 param2 (shell form)

6. 选择合适的基础镜像(alpine版本最好)

在示例中,我们选择了ubuntu作为基础镜像。但是我们只需要运行node程序,有必要使用一个通用的基础镜像吗?node镜像应该是更好的选择。

FROM nodeADD . /app # we don’t need to install node # anymore and use
apt-getRUN cd /app && npm installCMD npm start

更好的选择是alpine版本的node镜像。alpine是一个极小化的Linux发行版,只有4MB,这让它非常适合作为基础镜像。

FROM node:7-alpineADD . /app RUN cd /app && npm installCMD npm start

apk是Alpine的包管理工具。它与apt-get有些不同,但是非常容易上手。另外,它还有一些非常有用的特性,比如no-cache--virtual选项,它们都可以帮助我们减少镜像的大小。

CMD指定在 Dockerfile
中只能使用一次,如果有多个,则只有最后一个会生效。
CMD的目的是为了在启动容器时提供一个默认的命令执行选项。如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。
CMD会在启动容器的时候执行,build
时不执行,而RUN只是在构建镜像的时候执行,后续镜像构建完成之后,启动容器就与RUN无关了,这个初学者容易弄混这个概念,这里简单注解一下。

7. 设置WORKDIR和 CMD

WORKDIR指令可以设置默认目录,也就是运行RUN/CMD/ENTRYPOINT指令的地方。

CMD指令可以设置容器创建是执行的默认命令。另外,你应该讲命令写在一个数组中,数组中每个元素为命令的每个单词。

FROM node:7-alpineWORKDIR /app ADD . /app RUN npm installCMD [“npm”,
“start”]

7.4 EXPOSE
EXPOSE <port> [<port>…]

8. 使用ENTRYPOINT

ENTRYPOINT指令并不是必须的,因为它会增加复杂度。ENTRYPOINT是一个脚本,它会默认执行,并且将指定的命令错误其参数。它通常用于构建可执行的Docker镜像。entrypoint.sh如下:

#!/usr/bin/env sh# $0 is a script name, # $1, $2, $3 etc are passed
arguments# $1 is our commandCMD=$1case “$CMD” in “dev” ) npm install
export NODE_ENV=development exec npm run dev ;; “start” ) # we can
modify files here, using ENV variables passed in # “docker create”
command. It can’t be done during build process. echo “db:
$DATABASE_ADDRESS” >> /app/config.yml export NODE_ENV=production
exec npm start ;; * ) # Run custom command. Thanks to this line we can
still use # “docker run our_image /bin/bash” and it will work exec
$CMD ${@:2} ;;esac

示例Dockerfile:

FROM node:7-alpineWORKDIR /app ADD . /app RUN npm installENTRYPOINT
[“./entrypoint.sh”] CMD [“start”]

可以使用如下命令运行该镜像:

# 运行开发版本docker run our-app dev # 运行生产版本docker run our-app
start # 运行bashdocker run -it our-app /bin/bash

告诉 Docker 服务端容器对外映射的本地端口,需要在 docker run
的时候使用-p或者-P选项生效。
7.5 ENV
ENV <key> <value> # 只能设置一个变量ENV
<key>=<value> … # 允许一次设置多个变量

9. 在entrypoint脚本中使用exec

在前文的entrypoint脚本中,我使用了exec命令运行node应用。不使用exec的话,我们则不能顺利地关闭容器,因为SIGTERM信号会被bash脚本进程吞没。exec命令启动的进程可以取代脚本进程,因此所有的信号都会正常工作。

指定一个环节变量,会被后续RUN指令使用,并在容器运行时保留。
例子:
ENV myName=”John Doe” myDog=Rex\ The\ Dog \ myCat=fluffy

10. COPY与ADD优先使用前者

COPY指令非常简单,仅用于将文件拷贝到镜像中。ADD相对来讲复杂一些,可以用于下载远程文件以及解压压缩包。

FROM node:7-alpineWORKDIR /appCOPY . /app RUN npm installENTRYPOINT
[“./entrypoint.sh”] CMD [“start”]

等同于
ENV myName John DoeENV myDog Rex The DogENV myCat fluffy

11. 合理调整COPY与RUN的顺序

我们应该把变化最少的部分放在Dockerfile的前面,这样可以充分利用镜像缓存。

示例中,源代码会经常变化,则每次构建镜像时都需要重新安装NPM模块,这显然不是我们希望看到的。因此我们可以先拷贝package.json,然后安装NPM模块,最后才拷贝其余的源代码。这样的话,即使源代码变化,也不需要重新安装NPM模块。

FROM node:7-alpineWORKDIR /appCOPY package.json /app RUN npm install
COPY . /appENTRYPOINT [“./entrypoint.sh”] CMD [“start”]

7.6 ADD
ADD <src>… <dest>

12. 设置默认的环境变量,映射端口和数据卷

运行Docker容器时很可能需要一些环境变量。在Dockerfile设置默认的环境变量是一种很好的方式。另外,我们应该在Dockerfile中设置映射端口和数据卷。示例如下:

FROM node:7-alpineENV PROJECT_DIR=/appWORKDIR $PROJECT_DIRCOPY
package.json $PROJECT_DIR RUN npm install COPY . $PROJECT_DIRENV
MEDIA_DIR=/media \ NODE_ENV=production \ APP_PORT=3000VOLUME
$MEDIA_DIR EXPOSE $APP_PORTENTRYPOINT [“./entrypoint.sh”] CMD
[“start”]

ENV指令指定的环境变量在容器中可以使用。如果你只是需要指定构建镜像时的变量,你可以使用ARG指令。

ADD复制本地主机文件、目录或者远程文件 URLS 从 并且添加到容器指定路径中

支持通过 Go
的正则模糊匹配,具体规则可参见 Go
filepath.Match
ADD hom* /mydir/ # adds all files starting with “hom”ADD hom?.txt
/mydir/ # ? is replaced with any single character

13. 使用LABEL设置镜像元数据

使用LABEL指令,可以为镜像设置元数据,例如镜像创建者或者镜像说明。旧版的Dockerfile语法使用MAINTAINER指令指定镜像创建者,但是它已经被弃用了。有时,一些外部程序需要用到镜像的元数据,例如nvidia-docker需要用到com.nvidia.volumes.needed。示例如下:

FROM node:7-alpine LABEL maintainer “jakub.skalecki@example.com” …

路径必须是绝对路径,如果 不存在,会自动创建对应目录
路径必须是 Dockerfile 所在路径的相对路径
如果是一个目录,只会复制目录下的内容,而目录本身则不会被复制

14. 添加HEALTHCHECK

运行容器时,可以指定--restart always选项。这样的话,容器崩溃时,Docker守护进程(docker
daemon)会重启容器。对于需要长时间运行的容器,这个选项非常有用。但是,如果容器的确在运行,但是不可(陷入死循环,配置错误)用怎么办?使用HEALTHCHECK指令可以让Docker周期性的检查容器的健康状况。我们只需要指定一个命令,如果一切正常的话返回0,否则返回1。对HEALTHCHECK感兴趣的话,可以参考这篇博客。示例如下:

FROM node:7-alpine LABEL maintainer “jakub.skalecki@example.com”ENV
PROJECT_DIR=/app WORKDIR $PROJECT_DIRCOPY package.json $PROJECT_DIR
RUN npm install COPY . $PROJECT_DIRENV MEDIA_DIR=/media \
NODE_ENV=production \ APP_PORT=3000VOLUME $MEDIA_DIR EXPOSE
$APP_PORT HEALTHCHECK CMD curl –fail ||
exit 1ENTRYPOINT [“./entrypoint.sh”] CMD [“start”]

当请求失败时,curl --fail命令返回非0状态。

7.7 COPY
COPY <src>… <dest>

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React
Native、Node.js和Java线上应用实时BUG监控。
自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎大家免费试用!

永利总站手机版 1

COPY复制新文件或者目录从 并且添加到容器指定路径中
。用法同ADD,唯一的不同是不能指定远程文件 URLS。
7.8 ENTRYPOINT
ENTRYPOINT “executable”, “param1”,
“param2”
ENTRYPOINT command param1 param2 (shell form)

版权声明

转载时请注明作者Fundebug以及本文地址:

配置容器启动后执行的命令,并且不可被 docker run
提供的参数覆盖,而CMD是可以被覆盖的。如果需要覆盖,则可以使用docker run
–entrypoint选项。
每个 Dockerfile
中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。
Exec form ENTRYPOINT 例子
通过ENTRYPOINT使用 exec form
方式设置稳定的默认命令和选项,而使用CMD添加默认之外经常被改动的选项。
FROM ubuntuENTRYPOINT [“top”, “-b”]CMD [“-c”]

通过 Dockerfile 使用ENTRYPOINT展示前台运行 Apache 服务
FROM debian:stableRUN apt-get update && apt-get install -y –force-yes
apache2EXPOSE 80 443VOLUME [“/var/www”, “/var/log/apache2”,
“/etc/apache2”]ENTRYPOINT [“/usr/sbin/apache2ctl”, “-D”,
“FOREGROUND”]

Shell form ENTRYPOINT 例子
这种方式会在/bin/sh -c中执行,会忽略任何CMD或者docker
run命令行选项,为了确保docker
stop能够停止长时间运行ENTRYPOINT的容器,确保执行的时候使用exec选项。
FROM ubuntuENTRYPOINT exec top -b

如果在ENTRYPOINT忘记使用exec选项,则可以使用CMD补上:
FROM ubuntuENTRYPOINT top -bCMD –ignored-param1 # –ignored-param2 …
–ignored-param3 … 依此类推

7.9 VOLUME
VOLUME [“/data”]

创建一个可以从本地主机或其他容器挂载的挂载点,后续具体介绍。
7.10 USER
USER daemon

指定运行容器时的用户名或
UID,后续的RUN、CMD、ENTRYPOINT也会使用指定用户。
7.11 WORKDIR
WORKDIR /path/to/workdir

为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。
WORKDIR /aWORKDIR bWORKDIR cRUN pwd

最终路径是/a/b/c。
WORKDIR指令可以在ENV设置变量之后调用环境变量:
ENV DIRPATH /pathWORKDIR $DIRPATH/$DIRNAME

最终路径则为 /path/$DIRNAME。
7.12 ONBUILD
ONBUILD [INSTRUCTION]

配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
例如,Dockerfile 使用如下的内容创建了镜像 image-A:
[…]ONBUILD ADD . /app/srcONBUILD RUN /usr/local/bin/python-build
–dir /app/src[…]

如果基于 image-A 创建新的镜像时,新的 Dockerfile 中使用 FROM image-A
指定基础镜像时,会自动执行 ONBUILD
指令内容,等价于在后面添加了两条指令。
Automatically run the followingADD . /app/srcRUN
/usr/local/bin/python-build –dir /app/src

使用ONBUILD指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild。
7.13 Dockerfile Examples
Nginx## VERSION 0.0.1FROM ubuntuMAINTAINER Victor Vieux
victor@docker.comRUN
apt-get update && apt-get install -y inotify-tools nginx apache2
openssh-server# Firefox over VNC## VERSION 0.3FROM ubuntu# Install
vnc, xvfb in order to create a ‘fake’ display and firefoxRUN apt-get
update && apt-get install -y x11vnc xvfb firefoxRUN mkdir ~/.vnc# Setup
a passwordRUN x11vnc -storepasswd 1234 ~/.vnc/passwd# Autostart firefox
(might not be the best way, but it does the trick)RUN bash -c ‘echo
“firefox” >> /.bashrc’EXPOSE 5900CMD [“x11vnc”, “-forever”,
“-usepw”, “-create”]# Multiple images example## VERSION 0.1FROM
ubuntuRUN echo foo > bar# Will output something like ===>
907ad6c2736fFROM ubuntuRUN echo moo > oink# Will output something
like ===> 695d7793cbe4# You᾿ll now have two images, 907ad6c2736f
with /bar, and 695d7793cbe4 with# /oink.

7.14 docker build
$ docker build –helpUsage: docker build [OPTIONS] PATH | URL | -Build
a new image from the source code at PATH –force-rm=false Always remove
intermediate containers, even after unsuccessful builds #
移除过渡容器,即使构建失败 –no-cache=false Do not use cache when
building the image # 不实用 cache -q, –quiet=false Suppress the
verbose output generated by the containers –rm=true Remove intermediate
containers after a successful build # 构建成功后移除过渡层容器 -t,
–tag=”” Repository name (and optionally a tag) to be applied to the
resulting image in case of success

参考文档:Dockerfile
Reference
7.15 dockerfile 最佳实践
使用.dockerignore文件

为了在docker
build过程中更快上传和更加高效,应该使用一个.dockerignore文件用来排除构建镜像时不需要的文件或目录。例如,除非.Git在构建过程中需要用到,否则你应该将它添加到.dockerignore文件中,这样可以节省很多时间。
避免安装不必要的软件包

为了降低复杂性、依赖性、文件大小以及构建时间,应该避免安装额外的或不必要的包。例如,不需要在一个数据库镜像中安装一个文本编辑器。
每个容器都跑一个进程

在大多数情况下,一个容器应该只单独跑一个程序。解耦应用到多个容器使其更容易横向扩展和重用。如果一个服务依赖另外一个服务,可以参考
Linking Containers
Together。
最小化层

我们知道每执行一个指令,都会有一次镜像的提交,镜像是分层的结构,对于Dockerfile,应该找到可读性和最小化层之间的平衡。
多行参数排序

如果可能,通过字母顺序来排序,这样可以避免安装包的重复并且更容易更新列表,另外可读性也会更强,添加一个空行使用\换行:
RUN apt-get update && apt-get install -y \ bzr \ cvs \ git \
mercurial \ subversion

创建缓存

镜像构建过程中会按照Dockerfile的顺序依次执行,每执行一次指令 Docker
会寻找是否有存在的镜像缓存可复用,如果没有则创建新的镜像。如果不想使用缓存,则可以在docker
build时添加–no-cache=true选项。
从基础镜像开始就已经在缓存中了,下一个指令会对比所有的子镜像寻找是否执行相同的指令,如果没有则缓存失效。在大多数情况下只对比Dockerfile指令和子镜像就足够了。ADD和COPY指令除外,执行ADD和COPY时存放到镜像的文件也是需要检查的,完成一个文件的校验之后再利用这个校验在缓存中查找,如果检测的文件改变则缓存失效。RUN
apt-get -y update命令只检查命令是否匹配,如果匹配就不会再执行更新了。
为了有效地利用缓存,你需要保持你的 Dockerfile 一致,并且尽量在末尾修改。

Dockerfile 指令
FROM: 只要可能就使用官方镜像库作为基础镜像
RUN:
为保持可读性、方便理解、可维护性,把长或者复杂的RUN语句使用\分隔符分成多行不建议RUN
apt-get update独立成行,否则如果后续包有更新,那么也不会再执行更新
避免使用RUN apt-get
upgrade或者dist-upgrade,很多必要的包在一个非privileged权限的容器里是无法升级的。如果知道某个包更新,使用apt-get
install -y xxx
标准写法RUN apt-get update && apt-get install -y package-bar package-foo

例子:
RUN apt-get update && apt-get install -y \ aufs-tools \ automake \
btrfs-tools \ build-essential \ curl \ dpkg-sig \ git \ iptables \
libapparmor-dev \ libcap-dev \ libsqlite3-dev \ lxc=1.0* \
mercurial \ parallel \ reprepro \ ruby1.9.1 \ ruby1.9.1-dev \
s3cmd=1.1.0*

CMD: 推荐使用CMD [“executable”, “param1”, “param2”…]这种格式,CMD
[“param”, “param”]则配合ENTRYPOINT使用
EXPOSE: Dockerfile 指定要公开的端口,使用docker
run时指定映射到宿主机的端口即可
ENV: 为了使新的软件更容易运行,可以使用ENV更新PATH变量。如ENV PATH
/usr/local/nginx/bin:$PATH确保CMD [“nginx”]即可运行

ENV也可以这样定义变量:
ENV PG_MAJOR 9.3ENV PG_VERSION 9.3.4RUN curl -SL
http://example.com/postgres-$PG\_VERSION.tar.xz
| tar -xJC /usr/src/postgress && …ENV PATH
/usr/local/postgres-$PG_MAJOR/bin:$PATH

ADDorCOPY:ADD比COPY多一些特性「tar 文件自动解包和支持远程
URL」,不推荐添加远程 URL

如不推荐这种方式:
永利总站手机版,ADD
http://example.com/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

推荐使用 curl 或者 wget 替换,使用如下方式:
RUN mkdir -p /usr/src/things \ && curl -SL
http://example.com/big.tar.gz
\ | tar -xJC /usr/src/things \ && make -C /usr/src/things all

如果不需要添加 tar 文件,推荐使用COPY。
参考文档:
Best practices for writing
Dockerfiles
Dockerfile最佳实践(一)
Dockerfile最佳实践(二)

标签:, , , ,

Your Comments

近期评论

    功能


    网站地图xml地图