Dockerfile构建之上下文路径

文章介绍了Docker镜像构建上下文的概念,纠正了关于构建路径和Dockerfile位置的误解。Docker使用客户端/服务器架构,dockerbuild命令将上下文目录打包发送到服务端进行镜像构建。COPY和ADD指令引用的文件路径是相对于构建上下文的。文章通过示例验证了上下文可以自定义,并强调了使用-f选项指定Dockerfile的重要性,同时提醒应合理管理构建上下文以避免不必要的文件传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考原文博客地址:《Docker之构建上下文详解》

简单回顾Docker镜像构建

  1. cd命令进入 Dockerfile 文件所在目录

  2. docker build -t [imageName:imageTag](imagename:imageTag) .命令进行构建

对于以上的常规操作,很容易让人陷入如下误区:

  1. docker build 后面的构建上下文路径只能为 Dockerfile 所在的目录.
  2. Dockerfile 文件名必须为 Dockerfile;

针对上面的两点错误理解要想准确理解其含义,首先我们需要先了解下 Docker 的架构和 docker build 的工作原理。

Docker架构简介

Docker 引擎使用C/S (客户端/服务器)体系的架构,Docker 客户端与 Docker 引擎的守护进程通信,Docker 引擎守护进程负责构建,运行和分发 Docker 容器。Docker 客户端和 Docker 引擎守护进程可以在同一个系统上运行,也可以将 Docker 客户端连接到远程 Docker 引擎守护进程。Docker 客户端和 Docker 引擎守护进程使用 REST API 通过UNIX套接字或网络接口进行通信。

总结:docker build 动作发生在 Docker 引擎中

docker build工作原理

  1. Client端执行 docker build -t [imageName:imageTag](imagename:imageTag) .命令 ;
  2. Docker 客户端会将构建命令后面指定的路径(.)下的所有文件打包发送给 Docker 服务端;
  3. Docker服务端对客户端发送的包进行解压,然后根据 Dockerfile 里面的指令进行镜像的分层构建;

镜像构建上下文

Dockerfile 中使用 COPY 指令、ADD 等这些指令时。往往是期望对宿主机上的某些文件进行操作;而 docker build 命令构建镜像的过程其实并非在客户端本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得客户端的本地文件呢?

这就引入了上下文的概念。当构建的时候,用户需要指定构建镜像上下文的路径,docker build 命令会将路径下的所有内容打包并上传给 Docker 引擎。最后 Docker 引擎解压,这样在构建时就可以获取镜像所需的一切文件。
如果在 Dockerfile 中这么写:

# 这表示将构建上下文路径下的
# package.json文件复制到容器内的/app/下
COPY ./package.json /app/

上述COPY指令仅仅表明复制的是构建上下文路径下的 package.json。它既不是要复制执行 docker build 命令所在目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json。
因此,COPY这类指令中的源文件的路径都是相对路径。这也是初学时经常迷惑为什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。

示例验证

基于上面的理解;对其进行实验验证:
验证命题:

  1. docker build命令后面的构建上下文路径不是必须为 Dockerfile 所在的目录.;还可以指定上下文路径。
  2. 如果指定上下文路径,则必须使用-f选项指定Dockerfile路径;因为指定上下文路径不是.,即使在Dockerfile所在目录下执行docker build也不好使。

验证思路:

编写 Dockerfile 文件保存在宿主机的/home/dockerfile/demo/目录下;Dockerfile 的内容就以 nginx 为例,将宿主机下自定义/tmp/index.html文件COPY到 nginx 容器/usr/share/nginx/html/进行替换

第一步:准备index.html
将编写好的index.html文件上传到服务器的/tmp/路径下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>docker构建上下文路径</title>
</head>
<body>
  <h1>docker构建上下文路径可以自定义指定验证</h1>
</body>
</html>

第二步:编写Dockerfile文件


# 这是一个简单Dockerfile练习
FROM nginx

# 将‘构建上下文路径’下的index.html进行复制替换操作
COPY ./index.html /usr/share/nginx/html

编写完成以后将文件上传至服务器的/home/dockerfile/demo/

第三步:撇弃默认,自定义上下文路径进行构建
下图为Dockerfileindex.html在服务器上的位置
在这里插入图片描述

注意:在撇弃默认的构建上下文路径.;自定义上下文路径的情况下,一定要使用-f指定Dockerfile文件路径(即使在Dockerfile所在目录下执行docker build也需要);否则会出现如下错误:

[root@VM-8-3-opencloudos demo]# docker build -t nginx-test:01 /tmp
unable to prepare context: unable to evaluate symlinks in >Dockerfile path: lstat /tmp/Dockerfile: no such file or >directory

第四步:正确构建的命令选项

[root@VM-8-3-opencloudos ~]# docker build -f /home/dockerfile/demo/Dockerfile -t nginx-test:01 /tmp
Sending build context to Docker daemon  24.24MB
Step 1/2 : FROM nginx
 ---> 021283c8eb95
Step 2/2 : COPY ./index.html /usr/share/nginx/html
 ---> 6789af79468c
Successfully built 6789af79468c
Successfully tagged nginx-test:01

示例总结

基于自定义构建上下文路径的情况下,必须使用-f指定Dockerfile路径(即使在Dockerfile所在目录下执行docker build也需要)

构建上下文经验之谈

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

  1. 一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。并且构建上下文路径就使用.

  2. 如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个.dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

  3. 实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用-f 指定某个文件作为 Dockerfile。

  4. 一般习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值