Dockerfile build镜像的构建环境(build Context)


通过dockerfile定义文件和docker build命令构建,是推荐使用的镜像构建方式。通常在执行docker build的命令时,最后会加上".", 这个被当做是当前目录的"."是指dockerfile所在的路径吗?

环境简介

假如我们有如下的结构:

  • 当前位于/root/docker/demo,该目录下有个Dockerfile,是我们即将用于构建镜像的定义文件
  • dockerfile的内容如下:从ubuntu基础镜像开始,然后试图导入待执行的jar包文件到指定目录下
  • 待导入的jar包文件目录当前dockerfile的上级目录

下面的环境帮助你理解上述

# cat Dockerfile 
FROM ubuntu:latest
#
ENV RUN_PATH /home/work/bin/demo
RUN mkdir -p $RUN_PATH

#加入待运行的包
ADD ../spring-demo-0.0.1-SNAPSHOT.jar $RUN_PATH/spring-demo-0.0.1-SNAPSHOT.jar


# pwd
/root/docker/demo
# ll
total 4
-rw-r--r--. 1 root root 302 Mar 28 10:59 Dockerfile
# tree ../
../
├── demo
│   └── Dockerfile
├── demoApp
│   ├── Dockerfile
│   └── spring-demo-0.0.1-SNAPSHOT.jar
└── spring-demo-0.0.1-SNAPSHOT.jar

执行构建

按照上述的环境及dockerfile, 执行如下构建,会发生什么了?

# docker build -t "docker/demo:v1" .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM ubuntu:latest
 ---> 72300a873c2c
Step 2/4 : ENV RUN_PATH /home/work/bin/demo
 ---> Using cache
 ---> 7ef7956d22f5
Step 3/4 : RUN mkdir -p $RUN_PATH
 ---> Using cache
 ---> ac1218623a72
Step 4/4 : ADD ../spring-demo-0.0.1-SNAPSHOT.jar $RUN_PATH/spring-demo-0.0.1-SNAPSHOT.jar
ADD failed: Forbidden path outside the build context: ../spring-demo-0.0.1-SNAPSHOT.jar ()

ADD命令执行失败,意思是jar包的位置超出了当前构建的上下文。在此注意如果认为docker build命令最后的"."是指构建时dockerfile的位置,这样是不准确的;实际上它是指当前的构建上下文。Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f …/Dockerfile 参数指定某个文件作为Dockerfile。

理解docker build 的工作原理

Docker实质上是一个C/S架构的程序。Docker的引擎提供了一组REST API,被称为Docker Remote API,而如docker命令这样的cli指令,则是通过API与Docker引擎交互。

当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如上文的ADD指令。而docker build 命令构建镜像,其实并非在本地构建,而是在server端,即Docker引擎中构建的。那么在这种C/S的架构中,如何才能让服务端获得本地文件呢?这就是build context(构建上下文)的意义。当构建的时候,用户会指定构建镜像上下文的路径,docker build命令得知这个路径后,会将路径下的所有内容打包,然后上传给Docker引擎。Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

因此,ADD这类指令中的源文件的路径都是基于上下文的相对路径。而当指定构建的时的上下文是".“时,自然本地的”…/"路径就超出了上下文的范围。同样
ADD /root/docker/demo/spring-demo-0.0.1-SNAPSHOT.jar $RUN_PATH/spring-demo-0.0.1-SNAPSHOT.jar 也是无法正常工作的。

那么如何修正上述错误了?
将错就错(不推荐)
那么在现有目录结构下该如何构建了?修改Dockfile如下

FROM ubuntu:latest
#
ENV RUN_PATH /home/work/bin/demo
RUN mkdir -p $RUN_PATH

#加入待运行的包
ADD ./spring-demo-0.0.1-SNAPSHOT.jar $RUN_PATH/spring-demo-0.0.1-SNAPSHOT.jar

构建:

docker build -t "docker/demo:v1" -f ../demo/Dockerfile ../

你看,如果将上一级目录("…/")作为构建上下文, 那么你需要指定dockerfile的位置,而此时ADD命令执行的是将构建环境目录下的jar包,添加到docker的指定目录下。

为什么不推荐:
如果你将一级目录("…/")作为构建上下文,那么上一级目录下的所有文件都会被打包上传至docker引擎,而demoApp目录下文件,对本次构建来说,完全是多余的,这不仅增加了构建成本,也使得构建结果镜像臃肿。

最佳实践

建一个空目录,创建Dockerfile,并将你要用的文件和所有包置于该目录下。

# tree .
.
├── Dockerfile
└── spring-demo-0.0.1-SNAPSHOT.jar
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值