ddddfang's Blog.

docker-file

字数统计: 3.1k阅读时长: 15 min
2019/01/30 Share

参看《第一本dockers书》p80

docker之dockerfile实践

v1

先查看下本地的镜像,选一个作为base image:

1
2
3
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 196e0ce0c9fb 6 weeks ago 197MB

接下来开始编写Dockerfile文件(注意Dockerfile的D需要大写),这里以编译nginx提供web服务来构建新的镜像

  1. 下载nginx源码包到docker_demo目录下:
1
2
3
4
[root@docker docker_demo]# ll
total 960
-rw-r--r--. 1 root root 0 Nov 1 04:34 Dockerfile
-rw-r--r--. 1 root root 981687 Oct 17 09:20 nginx-1.12.2.tar.gz
  1. 以下是编写好的Dockerfile v1版:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@docker docker_demo]# cat Dockerfile
# base image
FROM centos

# MAINTAINER
MAINTAINER json_hc@163.com

# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx(这一步会执行解压操作)
ADD nginx-1.12.2.tar.gz /usr/local/src

# running required command
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx

# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2

# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install

EXPOSE 80
  1. 执行docker build进行构建:
1
docker build -t centos_nginx:v1 .

后面的.代表的是Dockerfile文件所在的目录。构建成功后,查看新构建的镜像:

1
2
3
4
[root@docker docker_demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v1 78d18f16e757 4 hours ago 464MB
centos latest 196e0ce0c9fb 6 weeks ago 197MB
  1. 使用构建的镜像启动一个container并开启nginx服务:
1
2
[root@docker docker_demo]# docker run -d centos_nginx:v1 /usr/local/nginx/sbin/nginx -g "daemon off;"
ea5af922378356a5ebff60992f000b186b09d1e8d6a4915b0b8ccf997ca12404

查看启动的container是否在运行:

1
2
3
[root@docker docker_demo]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ea5af9223783 centos_nginx:v1 "/usr/local/nginx/..." 7 seconds ago Up 6 seconds 80/tcp flamboyant_carson

虽然nginx服务开启了,但是port并没有进行映射到本机host,所以这个container并不能进行访问,重新启动一个进行了映射端口的容器

1
2
[root@docker docker_demo]# docker run -d -p80:80 centos_nginx:v1 /usr/local/nginx/sbin/nginx -g "daemon off;"
e4b6e4846dedc6f130e028701c84828a635f3b367c0d500ebd947de16b1be0b2

再次查看端口映射信息:

1
2
[root@docker docker_demo]# docker port e4b6e4846ded
80/tcp -> 0.0.0.0:80

于是进行访问:192.168.101.14:80

于是基于Dockerfile的一个简单实例构建完成,现在基于这个Dockerfile文件依次添加其他的指令进行构建

v2

添加ENV环境变量指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@docker docker_demo]# cat Dockerfile
# base image
FROM centos

# MAINTAINER
MAINTAINER json_hc@163.com

# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx
ADD nginx-1.12.2.tar.gz /usr/local/src

# running required command
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx

# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2

# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install

ENV PATH /usr/local/nginx/sbin:$PATH

EXPOSE 80

然后进行构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@docker docker_demo]# docker build -t centos_nginx:v2 .
Sending build context to Docker daemon 985.6kB
Step 1/10 : FROM centos
---> 196e0ce0c9fb
Step 2/10 : MAINTAINER json_hc@163.com
---> Using cache
---> cde1d7830106
Step 3/10 : ADD nginx-1.12.2.tar.gz /usr/local/src
---> Using cache
---> 1e4d16340af0
Step 4/10 : RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
---> Using cache
---> 405835ad9b0b
Step 5/10 : RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
---> Using cache
---> 4002738cf7a6
Step 6/10 : RUN useradd -M -s /sbin/nologin nginx
---> Using cache
---> 02961c5c564d
Step 7/10 : WORKDIR /usr/local/src/nginx-1.12.2
---> Using cache
---> f1da71a93c5e
Step 8/10 : RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install
---> Using cache
---> cd2ad4c45004
Step 9/10 : ENV PATH /usr/local/nginx/sbin:$PATH
---> Running in 07ba2f7129bc
---> 9588fa1058aa
Removing intermediate container 07ba2f7129bc
Step 10/10 : EXPOSE 80
---> Running in 473cd847154a
---> 2031faf8894a
Removing intermediate container 473cd847154a
Successfully built 2031faf8894a
Successfully tagged centos_nginx:v2

由于在构建的过程中docker会采用缓存的机制,上面的构建过程中包含很多using cache,所以这次构建非常快,如果需要重新构建,不想使用cache需要添加–no-cache

–no-cache Do not use cache when building the image

查看v2版本的镜像:

1
2
3
[root@docker docker_demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v2 2031faf8894a 2 minutes ago 464MB

使用v2版本的镜像启动一个container:

1
2
[root@docker docker_demo]# docker run -d -p81:80 centos_nginx:v2 nginx -g "daemon off;"
da48b465b1b1a14824497d724eee52b8408270b3b5223c5dd7094b7c0cef211d

进行访问
img01
上述启动容器的过程中使用的命令docker run -d -p81:80 centos_nginx:v2 nginx -g “daemon off;”为什么这里使用的nginx而不是
/usr/local/nginx/sbin/nginx,因为在Dockerfile中执行了PATH=/usr/local/nginx/sbin:$PATH,添加到了环境变量

v3

添加指令CMD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@docker docker_demo]# cat Dockerfile
# base image
FROM centos

# MAINTAINER
MAINTAINER json_hc@163.com

# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx
ADD nginx-1.12.2.tar.gz /usr/local/src

# running required command
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx

# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2

# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install

ENV PATH /usr/local/nginx/sbin:$PATH

EXPOSE 80

CMD /bin/sh -c 'nginx -g "daemon off;"'

然后进行构建:

1
[root@docker docker_demo]# docker build -t centos_nginx:v3 .

查看v3版本的镜像:

1
2
3
[root@docker docker_demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v3 0e49a2c0562f 11 seconds ago 464MB

然后基于v3版本的镜像启动一个container:

1
2
[root@docker docker_demo]# docker run -d -p82:80 centos_nginx:v3
d988c04d04f49b909f28e7b664be3959a0d51b951f1c1b04fcf5c716552b7c41

最后进行访问:
img01
新增加的CMD /bin/sh -c ‘nginx -g “daemon off;”‘表示当启动一个container时默认运行的命令,如果在启动container时赋予了command的化,那么定义的CMD中的命令将不会被执行,而会去执行command的命令

v4

添加entrypoint指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@docker docker_demo]# cat Dockerfile
# base image
FROM centos

# MAINTAINER
MAINTAINER json_hc@163.com

# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx
ADD nginx-1.12.2.tar.gz /usr/local/src

# running required command
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx

# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2

# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install

ENV PATH /usr/local/nginx/sbin:$PATH

EXPOSE 80

ENTRYPOINT ["nginx"]

CMD ["-g","daemon off;"]

当ENTRYPOINT和CMD连用时,CMD的命令是ENTRYPOINT命令的参数,两者连用相当于nginx -g “daemon off;”
而当一起连用的时候命令格式最好一致(这里选择的都是json格式的是成功的,如果都是sh模式可以试一下)

开始进行构建v4版本:

1
[root@docker docker_demo]# docker build -t centos_nginx:v4 .

查看新建的镜像:

1
2
3
[root@docker docker_demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v4 6c5128aaff05 4 minutes ago 464MB

为v4版本的镜像启动一个container:

1
2
[root@docker docker_demo]# docker run -d -p83:80 centos_nginx:v4
6933c78255f3cebe44d4d5d080caf8a2fde45ded2f9b333ec01cdfe98cd5f417

最后进行访问:
img01

v5

添加VOLUME指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@docker docker_demo]# cat Dockerfile
# base image
FROM centos

# MAINTAINER
MAINTAINER json_hc@163.com

# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx
ADD nginx-1.12.2.tar.gz /usr/local/src

# running required command
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx

# mount a dir to container(本机上: /var/lib/docker/volumes/xxx/_data)
VOLUME ["/data"]

# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2

# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install

# setup PATH
ENV PATH /usr/local/nginx/sbin:$PATH

# EXPOSE
EXPOSE 80

# the command of entrypoint
ENTRYPOINT ["nginx"]

CMD ["-g"]

开始进行构建:

1
[root@docker docker_demo]# docker build -t centos_nginx:v6 .

查看v6版本的镜像:

1
2
3
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v6 959fdf4d4288 35 seconds ago 464MB

利用该镜像启动一个container:

1
2
[root@docker ~]# docker run -d -p 86:80 --name=nginx6 centos_nginx:v6 -g "daemon off;"
6c15a9e93fb1421bdb7eddaabe439996e97415e85a003f80c1d8b4b2c5ee3ffa

查看启动的容器状态:

1
2
3
[root@docker ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c15a9e93fb1 centos_nginx:v6 "nginx -g 'daemon ..." 4 seconds ago Up 4 seconds 0.0.0.0:86->80/tcp nginx6

利用docker exec进入到container中,查看是否存在卷/data:

1
2
3
4
5
[root@6c15a9e93fb1 /]# ll
total 16
-rw-r--r--. 8 root root 15836 Sep 11 15:53 anaconda-post.log
lrwxrwxrwx. 1 root root 7 Sep 11 15:51 bin -> usr/bin
drwxr-xr-x. 2 root root 6 Nov 2 01:42 data

这个/data挂载的目录对应本机host的这个目录:

1
2
[root@docker _data]# pwd
/var/lib/docker/volumes/3490a9b7f9773b020343e82c1c4236d976b69eb6a80121eb80612d8c39e02820/_data

现在在本机host上的这个目录创建一个文件:

1
2
3
4
[root@docker _data]# touch wadeson.sh
[root@docker _data]# ll
total 0
-rw-r--r--. 1 root root 0 Nov 1 21:45 wadeson.sh

然后切换到container中查看是否存在这个文件:

1
2
3
[root@6c15a9e93fb1 /]# ll /data/
total 0
-rw-r--r--. 1 root root 0 Nov 2 01:45 wadeson.sh

COPY 与 ADD

https://blog.csdn.net/liukuan73/article/details/52936045?utm_source=copy

当从Dockerfile 中 build Docker 镜像时候,你可以选择两种指令来添加本地的目录或者文件到你的镜像中:ADD和COPY。这两种指令格式基本相同并且基本是同样的东西

ADD
COPY

在这两种情况中,目录或者文件()被复制并添加到容器的文件系统中的指定路径()。所以,如果这两种指令相等的话,那为什么还要同时存在呢以及你应该选择哪一种使用呢?继续读会有答案的。当然如果你对他们之间的微小差别不感兴趣的话,只是想知道“我应该使用哪一个”,那么你只要知道:使用COPY即可。

1.ADD指令可以让你使用URL作为参数。当遇到URL时候,可以通过URL下载文件并且复制到
ADD http://foo.com/bar.go /tmp/main.go
ADD http://foo.com/bar.go /tmp/
因为以 / 结尾。Docker 会从URL推断文件名,并且添加到指定目录。一个名叫/tmp/bar.go的文件会被添加到容器的文件系统。

2.ADD的另外一个特性是有能力自动解压文件。如果参数是一个可识别的压缩格式(tar, gzip, bzip2, etc)的本地文件(所以实现不了同时下载并解压),就会被解压到指定容器文件系统的路径
ADD /foo.tar.gz /tmp/
上述指令会使foo.tar.gz压缩文件解压到容器的/tmp目录。

有趣的是,URL下载和解压特性不能一起使用。任何压缩文件通过URL拷贝,都不会自动解压。
目前ADD指令有点让人迷惑,有时候解压文件,有时候不解压文件,如果你想拷贝一个压缩文件,你会以为地解压。如果文件是某种不能识别的压缩文件,如果你想解压,你又会意外地复制它。

这种解释似乎是ADD尝试做的太多了,让用户有些疑惑。很明显,没人想要打破向后兼容性。所以决定新增一个行为更加明确的指令。和ADD相似,但是功能少一些。

在Docker 1.0发布时候,包括了新指令COPY。不像是ADD,COPY 更加直接了当,只复制文件或者目录到容器里。COPY不支持URL,也不会特别对待压缩文件。运行curl或者wget可以从远程URLS 中获取包

Docker 团队的建议是在大多数情况下使用COPY。真的,使用ADD的唯一原因就是你有一个压缩文件,你想自动解压到镜像中。

ADD http://foo.com/package.tar.bz2 /tmp/
RUN tar -xjf /tmp/package.tar.bz2 && make -C /tmp/package && rm /tmp/package.tar.bz2

这里我们有一个ADD指令,用于解析URL的压缩包,紧接着是RUN指令,用于解压这个压缩包。然后编译并尝试删除下载的压缩包。
很不幸,当这个压缩包压缩后,rm命令处于独立的镜像层。。

在这个案例中,你最好这样做:
RUN curl http://foo.com/package.tar.bz2 | tar -xjC /tmp/package && make -C /tmp/package

这里,我们curl 这个压缩包并且通过管道传给tar 命令解压。这样就在同一层镜像那么我们就可以删除压缩包了。
最后,只要认准一个原则:使用COPY(除非你明确你需要ADD)

CATALOG
  1. 1. docker之dockerfile实践
    1. 1.0.1. v1
    2. 1.0.2. v2
    3. 1.0.3. v3
    4. 1.0.4. v4
    5. 1.0.5. v5
  2. 1.1. COPY 与 ADD