首先我们要理解 docker build 的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 DockerRemote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举
当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过COPY 指令、 ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径, docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎(即:服务端)。这样Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件
如果在 Dockerfile 中这么写:COPY ./package.json /app/,这并不是要复制执行 docker build 命令所在的目录下的 package.json ,也不是复制 Dockerfile 所在目录下的 package.json ,而是复制上下文(context) 目录下的 package.json
因此, COPY 这类指令中的源文件的路径都是相对路径。这也是初学者经常会问的为什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去
现在就可以理解刚才的命令 docker build -t nginx:v3 .
中的这个 .
(即./
),实际上是在指定上下文的目录, docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像
如果观察 docker build 输出,我们其实已经看到了这个发送上下文的过程:
$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
...
理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build 执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误
一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore ,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的
那么为什么会有人误以为 . 是指定 Dockerfile 所在目录呢?这是因为在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。这只是默认行为,实际上Dockerfile 的文件名并不要求必须为 Dockerfile ,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile。当然,一般大家习惯性的会使用默认的文件名 Dockerfile ,以及会将其置于镜像构建上下文目录中
上下文就是:Docker服务端(即:Docker引擎)里面的一个临时文件夹,build时会将宿主机上(通过相对或绝对位置)指定的文件夹拷贝一份上传到Docker服务端里,作为上下文环境(临时文件夹);后面再执行Dockerfile中的ADD/COPY等指令时,实际上就相当于从Docker服务端里面的该临时文件夹(即:上下文环境)里ADD/COPY到该镜像指定的目录下了
如docker build -t {镜像名} .
指令中的.
(即./
),就是将宿主机的当前文件夹作为上下文
给出一张上下文环境测试方法:
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令
所要完成的Makefile 文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile 的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(通常对于一个工程来说会是多个)正确的 Makefile。编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令。整个工程完全自动编译,极大提高了效率
Docker提供了和Makefile完全一样的机制来管理镜像,这就是Dockerfile
指令 | 说明 |
---|---|
FROM | 指定要创建的镜像的基础镜像 |
MAINTAINER | 指定镜像维护者(创建者)信息 |
RUN | (当镜像创建容器后,该容器需要)运行的shell命令 注:如果有多条命令,可以用 && 连接 |
CMD | docker start启动(镜像创建的)容器后, 要默认运行的命令 |
LABEL | 指定生成镜像的元数据标签信息 |
EXPOSE | 常用于映射(暴露)端口(此表格后,会详细介绍) |
ENV | 指定环境变量 |
ADD | 复制上下文中的src 路径下的内容到容器中的dest 路径下注: src 可以为URL注:如果 src 路径为tar文件,会自动解压到dest 路径下 |
COPY | 复制上下文中的src 路径下的内容到容器中的dest 路径下注:一般情况下推荐使用COPY而不是ADD |
ENTRYPOINT | 指定镜像的默认入口 |
VOLUME | 指定数据挂载点 |
USER | 指定运行容器时的用户名或UID |
WORKDIR | 配置工作目录 |
ARG | 指定镜像内使用的参数(例如版本号信息等) |
ONBUILD | ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行 |
STOPSIGNAL | 容器退出的信号 |
HEALTHCHECK | 健康检查 |
SHELL | 指定使用SHELL时的默认SHELL类型 |
…… |
EXPOSE
指定容器需要映射到宿主机器的端口
设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项
映射一个端口
EXPOSE port1
相应的运行容器使用的命令
docker run -p port1 image
映射多个端口
EXPOSE port1 port2 port3
相应的运行容器使用的命令
docker run -p port1 -p port2 -p port3 image
还可以指定需要映射到宿主机器上的某个端口号
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
端口映射是docker比较重要的一个功能,原因在于我们每次运行容器的时候容器的IP地址不能指定而是在桥接网卡的地址范围内随机生成的。宿主机器的IP地址是固定的,我们可以将容器的端口的映射到宿主机器上的一个端口,免去每次访问容器中的某个服务时都要查看容器的IP的地址。对于一个运行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID来查看该端口号在宿主机器上的映射端口
指令
# 若不指定-f,则默认取上下文目录里名为"Dockerfile"的文件作为Dockerfile
docker build -t {镜像名} {上下文目录} -f {Dockerfile文件名}
注:Dockerfile文件可以不在上下文目录
下,可以在宿主机上的任意位置,只需要在docker build的时候-f
指定一下即可
示例
docker build -t ds/myimages . -f myDockerfile.txt
ds/myimages
:镜像名myDockerfile.txt
:Dockerfile文件.
:上下文目录,等价于./
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。