Docker build 的几种方式

docker build 的帮助文件中我们可以看到,docker build 不仅能支持本地 Dcokerfile 的构建,还可以从 URL 以及标准输入(-)中读取信息进行构建,下面就来说说 docker build 的几种构建方式。

1
2
3
4
5
[hzz@magedu TEST]$ docker build --help

Usage: docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

使用 dockerfile 构建

最常见的也是最便捷的一种构建方式,可以指定 dockerfile 文件,也可以自动使用上下文路径中以 Dockerfile 命名的文件来构建。

使用方式:

1
2
3
4
5
6
7
8
9
10
[hzz@magedu MyNginx]$ docker build -f nginx.dockerfile -t nginx:v1 . 
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e548f1a579cf
Step 2 : RUN echo '<h1>Hello Docker</h1>' >/usr/share/nginx/html/index.html
---> Running in a9ede88e3831
---> dfbb5a23f527
Removing intermediate container a9ede88e3831
Successfully built dfbb5a23f527
[hzz@magedu MyNginx]$

上下文路径

什么是上下文路径呢?大家可以注意到构建命令后面有个 .。没错,它就是初学 docker 时误以为是 Dockerfile 存放路径的那个上下文路径。

其实这个上下文路径并不是 Dockerfile 的存放路径,虽然默认的 Dockerfile 确实是从此路径中获取,但是 Dockerfile 可以使用 -f 参数指定,所以上下文路径和 Dockerfile 的存放路径没有必然的联系。

在 Dockerfile 的编写中,无可避免地会使用 COPYADD 来将本地文件拷贝到镜像内,比如:

1
COPY Centos-6.repo /etc/yum.repos.d/CentOS-Base.repo

这个 Centos-6.repo 所存在的本地路经,并不是绝对路径,也不是相对于 Dockerfile 的路经(使用自定义名称 Dockerfile 的时候),而是 build 命令最后的那个上下文路径(也就是那个 .)。

使用 git repo 构建

docker build 可以使用 URL 进行构建,这个 URL 也可以是 git 仓库地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[hzz@magedu ~]$ docker build https://github.com/nginxinc/docker-nginx.git#:stable/stretch
Sending build context to Docker daemon 6.144 kB
Step 1 : FROM debian:stretch-slim
Trying to pull repository docker.io/library/debian ...
stretch-slim: Pulling from docker.io/library/debian
8176e34d5d92: Already exists
Digest: sha256:e8e19950797443676474a4d12624325371f739f195abb3162c67df8d0fba0c50
---> 87afbf13bea7
Step 2 : LABEL maintainer "NGINX Docker Maintainers <docker-maint@nginx.com>"
---> Running in ab2991a0e7be
---> 3da0b815865c
Removing intermediate container ab2991a0e7be
Step 3 : ENV NGINX_VERSION 1.12.2-1~stretch
---> Running in 42d2b33b2707
---> 47b9b8de8fa5
Removing intermediate container 42d2b33b2707
Step 4 : ENV NJS_VERSION 1.12.2.0.1.14-1~stretch
---> Running in 197738c05ee2
---> 42e516616894
...

这个命令主要关注点有两个,一是使用默认分支(一般是 master);二是指定构建路径(#:stable/stretch)。

使用 tar 压缩包构建

docker build 也可以下载 tar 压缩包自动解压进行构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
[hzz@magedu ~]$ docker build http://127.0.0.1/stretch.tar
Step 1 : FROM debian:stretch-slimaemon 10.24 kB://127.0.0.1/stretch.tar [==================================================>] 10.24 kB/10.24 kB
---> 87afbf13bea7
Step 2 : LABEL maintainer "NGINX Docker Maintainers <docker-maint@nginx.com>"
---> Using cache
---> 3da0b815865c
Step 3 : ENV NGINX_VERSION 1.12.2-1~stretch
---> Using cache
---> 47b9b8de8fa5
Step 4 : ENV NJS_VERSION 1.12.2.0.1.14-1~stretch
---> Using cache
---> 42e516616894
...

使用 tar 压缩包构建需要注意一点,就是无法指定构建目录,所以 Dockerfile 必须放置于解压后的根目录下,也就是说打包的时候不能对整个父目录进行打包,只能对 Dockerfile 所在的目录和文件进行打包(tar cvf stretch.tar *)。

从标准输入中读取 dockerfile 构建

docker build 可以从标准输入中读取构建内容来进行构建。

可以直接输入进行构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
[hzz@magedu ~]$ cat | docker build - << EOF
FROM nginx
RUN echo '<h1>Hello Docker</h1>' >/usr/share/nginx/html/index.html
EOF

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e548f1a579cf
Step 2 : RUN echo '<h1>Hello Docker</h1>' >/usr/share/nginx/html/index.html
---> Running in 61508ae65ec2
---> 94d9c716d0d7
Removing intermediate container 61508ae65ec2
Successfully built 94d9c716d0d7

也可以使用读取文件的形式进行构建:

1
2
3
4
5
6
7
8
[hzz@magedu ~]$ cat nginx.dockerfile | docker build -
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e548f1a579cf
Step 2 : RUN echo '<h1>Hello Docker</h1>' >/usr/share/nginx/html/index.html
---> Using cache
---> 94d9c716d0d7
Successfully built 94d9c716d0d7
1
2
3
4
5
6
7
8
[hzz@magedu ~]$ docker build - < nginx.dockerfile 
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e548f1a579cf
Step 2 : RUN echo '<h1>Hello Docker</h1>' >/usr/share/nginx/html/index.html
---> Using cache
---> 94d9c716d0d7
Successfully built 94d9c716d0d7

从标准输入中读取上下文压缩包构建

之前说使用 tar 压缩包构建的时候,使用的是远程的 tar 包进行构建,那本地 tar 包该怎么构建呢?其实还是使用标准输入的方式进行构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[hzz@magedu ~]$ wget http://127.0.0.1/stretch.tar
--2018-03-07 23:41:06-- http://127.0.0.1/stretch.tar
正在连接 127.0.0.1:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:10240 (10K) [application/octet-stream]
正在保存至: “stretch.tar”

100%[=========================================================================================================>] 10,240 --.-K/s 用时 0s

2018-03-07 23:41:06 (119 MB/s) - 已保存 “stretch.tar” [10240/10240])

[hzz@magedu ~]$ docker buid - < stretch.tar
docker: 'buid' is not a docker command.
See 'docker --help'.
[hzz@magedu ~]$ docker build - < stretch.tar
Sending build context to Docker daemon 10.24 kB
Step 1 : FROM debian:stretch-slim
---> 87afbf13bea7
Step 2 : LABEL maintainer "NGINX Docker Maintainers <docker-maint@nginx.com>"
---> Running in 6915e011a570
---> a21cdaa05693
...

Have fun!