docker build与Dockerfile用法解释

105 篇文章 135 订阅

踩坑前言

第一次用docker build创建maven项目的镜像时,心中存在以下疑惑:docker build时,把哪些文件放到了镜像里?然后网上查阅资料时,发现好多误导人的博客,尤其是以下错误居多:

 

 这个点.不是表示Dockerfile所在文件夹。因为在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录(Context)下的名为Dockerfile 的文件作为 Dockerfile。 这只是默认行为。 当然,一般大家习惯性的会使用默认的文件名 Dockerfile ,以及会将其置于镜像构建上下文目录中。但是这个. 不代表Dockerfile的路径!!!实际上 Dockerfile 的文件名并不要求必须为Dockerfile ,而且并不要求必须位于上下文目录(Context)中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile 。

用法解释

   官方文档中docker build的使用格式为

Dockerbuild官方解释参考https://docs.docker.com/engine/reference/commandline/build/ 

  • The command builds Docker images from a Dockerfile and a “context”. A build’s context is the set of files located in the specified or . The build process can refer to any of the files in the context. For example, your build can use a COPY instruction to reference a file in the context.docker buildPATHURL

    The parameter can refer to three kinds of resources: Git repositories, pre-packaged tarball contexts and plain text files.URL

具体option参考:https://www.runoob.com/docker/docker-build-command.html

通常用法:

 镜像创建时要打包的内容(Context)

       docker build  命令最后有一个 路径。大家通常在最后用 .  表示当前目录,而Dockerfile 就在当前目录,因此不少人以为这个路径是在指定Dockerfile 所在路径,这么理解其实是不准确的。如果对应上面的命令格式和官方文档说明,你可能会发现,这是在指定context路径,有人翻译为上下文路径(context)。那么什么是Context呢?

        首先要理解  docker build  的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程,本机上就有该引擎)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如  docker  命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种  docker  功能,但实际上,一切都是使用的调用形式在服务端(Docker 引擎)完成。

        当我们进行镜像构建的时候,经常会需要将一些本地文件复制进镜像,比如通过  COPY  指令、 ADD  指令等。而  docker build  命令构建镜像,其实并非在本地客户端构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?

      这就引入了Context的概念。当构建的时候,用户会指定构建镜像Context的路径, docker build  命令得知这个路径后,会将该路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个包后,就会获得构建镜像所需的一切文件。注意:此时会将ContextPath下的所有文件上传到Docker 引擎,所以ContextPath路径下的文件尽量不要存在无用的文件。如果在  Dockerfile  中这么写:

则会把 Docker 引擎中的Context中的package.json文件加入到镜像中。

将ContextPath下的所有文件打包上传到Docker 引擎不意味着把所有文件加入镜像,将引擎中context中的所需文件加入镜像需要 Dockerfile中的COPY等指令。

        因此, COPY  这类指令中的源文件的路径都是相对路径,./意味着(context) 目录。这也是为什么  COPY ../package.json /app  或者  COPY /opt/xxxx /app  无法工作的原因,因为这些路径已经超出了引擎中context的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到context目录中去。

        现在就可以理解刚才的命令  docker build 命令中的最后的路径,实际上是在指定context的目录, docker build  命令会将该目录下的内容打包交给Docker 引擎以帮助构建镜像。

        如果观察  docker build  输出,其实能够看到这个发送context的过程:

        理解构建context对于镜像构建是很重要的,避免犯一些不应该的错误。比如在发现  COPY /opt/xxxx /app  不工作后,于是干脆将  Dockerfile  放到了硬盘根目录去构建,结果发现  docker build  执行后,在发送一个几十 GB 的无用东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让  docker build 打包整个硬盘,这显然是使用错误。

        参考官方说法:

The docker build command builds an image from a and a context. The build’s context is the set of files at a specified location or . The is a directory on your local filesystem. The is a Git repository location.DockerfilePATHURLPATHURL

A context is processed recursively. So, a includes any subdirectories and the includes the repository and its submodules. This example shows a build command that uses the current directory as context:PATHURL

The build is run by the Docker daemon, not by the CLI. The first thing a build process does is send the entire context (recursively) to the daemon. In most cases, it’s best to start with an empty directory as context and keep your Dockerfile in that directory. Add only the files needed for building the Dockerfile.

Warning

Do not use your root directory, , as the as it causes the build to transfer the entire contents of your hard drive to the Docker daemon./PATH

To use a file in the build context, the refers to the file specified in an instruction, for example, a instruction. To increase the build’s performance, exclude files and directories by adding a file to the context directory. For information about how to create a .dockerignore file see the documentation on this page.DockerfileCOPY.dockerignore

        一般来说,应该会将  Dockerfile  置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以写一个  .dockerignore ,该文件是用于剔除不需要作为context传递给 Docker 引擎的。

        那么为什么会有人误以为  .  是指定  Dockerfile  所在目录呢?这是因为在默认情况下,如果不额外指定  Dockerfile  的话,会将[ContextPath]目录下的名为Dockerfile  的文件作为 Dockerfile,大家也常常把[ContextPath]定义为. 。

        这只是默认行为,实际上  Dockerfile  的文件名并不要求必须为Dockerfile  ,而且并不要求必须位于[ContextPath]目录中,比如可以用  -f ../Dockerfile.php  参数指定某个文件作为  Dockerfile  。

        当然,一般大家习惯性的会使用默认的文件名  Dockerfile  ,以及会将其置于[ContextPath]目录中。

关于Dockerfile的最佳实践和使用说明请参考官网的两篇文章:

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

https://docs.docker.com/engine/reference/builder/#usage

转载至https://blog.csdn.net/weixin_43002202/article/details/108735549

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值