Docker-Dockerfile方式镜像的构建

1. 创建一个Dockerfile

默认在构建的时候会把当前目录所有数据发送到docker引擎,如果构建在根目录,会把跟目录所有数据发送给docker引擎进行构建,所以,创建Dockerfile尽量不要在根目录

mkdir docker

cd docker

vim Dockerfile
FROM busybox
RUN echo helloword > testfile

• 构建镜像

[root@vm2 demo]# docker build -t busybox:v2 .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM busybox
 ---> beae173ccac6
Step 2/2 : RUN echo helloword > testfile
 ---> Running in 33889fdfb36c
Removing intermediate container 33889fdfb36c
 ---> af46689dc5b5
Successfully built af46689dc5b5
Successfully tagged busybox:v2

• 查看镜像的分层结构

[root@vm2 demo]# docker history busybox:v2
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
af46689dc5b5   11 minutes ago   /bin/sh -c echo helloword > testfile            10B       
beae173ccac6   5 months ago     /bin/sh -c #(nop)  CMD ["sh"]                   0B        
<missing>      5 months ago     /bin/sh -c #(nop) ADD file:6db446a57cbd2b7f4…   1.24MB

• 镜像的缓存特性

构建镜像中有相同的镜像层时,会使用缓存来加速构建。

[root@vm2 demo]# vim Dockerfile 
FROM busybox
RUN echo helloword > testfile
COPY file /
[root@vm2 demo]# vim file
FROM busybox
RUN echo helloword > testfile
[root@vm2 demo]# docker build -t busybox:v3 .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM busybox
 ---> beae173ccac6
Step 2/3 : RUN echo helloword > testfile
 ---> Using cache
 ---> af46689dc5b5
Step 3/3 : COPY file /
 ---> 972a56410e72
Successfully built 972a56410e72
Successfully tagged busybox:v3

通过Dockerfile来构建镜像,可以清除的看到每一层都干了什么,有安全审计的功能。而通过docker commit 构建新镜像的方式则无法知晓具体在镜像内做了什么操作,无法对镜像进行审计,存在安全隐患。

• dockerfile 最佳实践

dockerfile常用指令
FROM 指定base镜像,如果本地不存在会从远程仓库下载。
MAINTAINER 设置镜像的作者,比如用户邮箱等。
COPY 把文件从build context复制到镜像
支持两种形式:COPY src dest 和 COPY [“src”, “dest”]
src必须指定build context中的文件或目录
ADD 用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到
dest,也可以自动下载URL并拷贝到镜像:
ADD html.tar /var/www
ADD http://ip/html.tar /var/www
ENV 设置环境变量,变量可以被后续的指令使用:
ENV HOSTNAME sevrer1.example.com
     EXPOSE 如果容器中运行应用服务,可以把服务端口暴露出去:
EXPOSE 80
VOLUME 申明数据卷,通常指定的是应用的数据挂在点:
VOLUME [“/var/www/html”]
WORKDIR 为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当
前工作目录,如果目录不存在会自动创建。
RUN 在容器中运行命令并创建新的镜像层,常用于安装软件包:
RUN yum install -y vim
       CMD

ENTRYPOINT

这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker
run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最
后一个有效。

 

 

2. 常用指令实践

2.1 COPY 把文件从build context复制到镜像

[root@vm2 ~]# cd docker/demo/
[root@vm2 demo]# ls
Dockerfile  file
[root@vm2 demo]# vim Dockerfile 
FROM busybox
COPY file /
[root@vm2 demo]# vim file 
hello docker
root@vm2 demo]# docker build -t busybox:v3 .
Sending build context to Docker daemon  1.077MB
Step 1/2 : FROM busybox
 ---> beae173ccac6
Step 2/2 : COPY file /
 ---> 609f28019307
Successfully built 609f28019307
Successfully tagged busybox:v3
[root@vm2 demo]# docker run -it --rm busybox:v3
/ # ls
bin   dev   etc   file  home  proc  root  sys   tmp   usr   var
/ # cat file 
hello docker
/ #

2.2 ADD 用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到
dest,也可以自动下载URL并拷贝到镜像

[root@vm2 demo]# ls
Dockerfile  file  nginx-1.21.6.tar.gz
[root@vm2 demo]# vim Dockerfile
FROM busybox
ADD nginx-1.21.6.tar.gz / 
[root@vm2 demo]# docker build -t busybox:v4 .
Sending build context to Docker daemon  1.077MB
Step 1/2 : FROM busybox
 ---> beae173ccac6
Step 2/2 : ADD nginx-1.21.6.tar.gz /
 ---> Using cache
 ---> 0ec99bc72f19
Successfully built 0ec99bc72f19
Successfully tagged busybox:v4
[root@vm2 demo]# docker run -it --rm busybox:v4
/ # ls
bin           etc           nginx-1.21.6  root          tmp           var
dev           home          proc          sys           usr
/ # cd nginx-1.21.6/
/nginx-1.21.6 # ls
CHANGES     LICENSE     auto        configure   html        src
CHANGES.ru  README      conf        contrib     man

2.3  ENV 设置环境变量,变量可以被后续的指令使用

[root@vm2 demo]# ls
Dockerfile  file  nginx-1.21.6.tar.gz
[root@vm2 demo]# vim Dockerfile
FROM busybox
ENV hostname vm2
ADD nginx-1.21.6.tar.gz / 
[root@vm2 demo]# docker build -t busybox:v5 .
Sending build context to Docker daemon  1.077MB
Step 1/3 : FROM busybox
 ---> beae173ccac6
Step 2/3 : ENV hostname vm2
 ---> Running in 5c5ba3805525
Removing intermediate container 5c5ba3805525
 ---> cebb03891923
Step 3/3 : ADD nginx-1.21.6.tar.gz /
 ---> e9aa8cc15264
Successfully built e9aa8cc15264
Successfully tagged busybox:v5
[root@vm2 demo]# docker run -it --rm busybox:v5
/ # env
HOSTNAME=57164b2b12e9
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
hostname=vm2
PWD=/
/ # 

2.4 VOLUME:申明数据卷,通常指定的是应用的数据挂载点

2.4.1 编辑Dockerkile文件,构建镜像

[root@vm2 demo]# ls
Dockerfile  file  nginx-1.21.6.tar.gz
[root@vm2 demo]# vim Dockerfile
FROM busybox
ENV hostname vm2
ADD nginx-1.21.6.tar.gz /
VOLUME ["/data"]
[root@vm2 demo]# docker build -t busybox:v6 .
Sending build context to Docker daemon  1.077MB
Step 1/4 : FROM busybox
 ---> beae173ccac6
Step 2/4 : ENV hostname vm2
 ---> Using cache
 ---> cebb03891923
Step 3/4 : ADD nginx-1.21.6.tar.gz /
 ---> Using cache
 ---> e9aa8cc15264
Step 4/4 : VOLUME ["/data"]
 ---> Running in d5212c93a723
Removing intermediate container d5212c93a723
 ---> aaa7d50b9466
Successfully built aaa7d50b9466
Successfully tagged busybox:v6

2.4.2  查看镜像的创建历史,进入容器,创建文件

[root@vm2 demo]# docker history busybox:v6
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
aaa7d50b9466   About a minute ago   /bin/sh -c #(nop)  VOLUME [/data]               0B        
e9aa8cc15264   5 minutes ago        /bin/sh -c #(nop) ADD file:8e86f7dae7bf3e74b…   6.46MB    
cebb03891923   5 minutes ago        /bin/sh -c #(nop)  ENV hostname=vm2             0B        
beae173ccac6   5 months ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B        
<missing>      5 months ago         /bin/sh -c #(nop) ADD file:6db446a57cbd2b7f4…   1.24MB    
[root@vm2 demo]# docker run -it --rm busybox:v6
/ # cd data/
/data # ls
/data # touch file

##ctrl+p+q退出

2.4.3 查看挂载信息,找到并进入挂载目录,编辑之前在镜像内创建的文件file(挂载的目录和镜像内的目录是同步的,编辑挂载目录的文件,镜像内的文件同样会被更改)

[root@vm2 demo]# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED          STATUS                    PORTS                       NAMES
5f4abc5a3f53   busybox:v6                           "sh"                     39 seconds ago   Up 38 seconds                                         frosty_burnell
[root@vm2 demo]# docker inspect 5f4abc5a3f53
......
 "Mounts": [
            {
                "Type": "volume",
                "Name": "ab9ce083e6c488a9d0758ca147381bed63ff56e46469ce365b9e1975c9e85a32",
                "Source": "/var/lib/docker/volumes/ab9ce083e6c488a9d0758ca147381bed63ff56e46469ce365b9e1975c9e85a32/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
......
[root@vm2 demo]# cd /var/lib/docker/volumes/ab9ce083e6c488a9d0758ca147381bed63ff56e46469ce365b9e1975c9e85a32/_data
[root@vm2 _data]# ls
file
[root@vm2 _data]# echo hello > file 
[root@vm2 _data]# cat file 
hello

2.4.4  用id重新启动镜像,查看镜像内的文件变化,之后删除镜像内的文件

[root@vm2 _data]# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED         STATUS                    PORTS                       NAMES
5f4abc5a3f53   busybox:v6                           "sh"                     3 minutes ago   Up 3 minutes                                          frosty_burnell
[root@vm2 _data]# docker attach 5f4abc5a3f53
/data # ls
file
/data # cat file 
hello
/data # rm -rf file 
/data # 

##ctrl+p+q退出

2.4.5 释放数据卷

[root@vm2 demo]# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED          STATUS                    PORTS                       NAMES
5f4abc5a3f53   busybox:v6                           "sh"                     39 seconds ago   Up 38 seconds                                         frosty_burnell
[root@vm2 demo]# docker rm -f 5f4abc5a3f53
5f4abc5a3f53
[root@vm2 ~]# docker volume ls
DRIVER    VOLUME NAME
local     4e845a124d5f7f442b48c0af033bcb0c0d47cadf7e810693b6c5faef02ca5a6f
local     4e94218a40e8e7e7032d46875f3d017812beded488a583bb0f7c79962721f07f
local     09df272ed7af46dd81c4b73d02065002a4ec5b26df93e6872d062436b0e855d2
local     71fead7e8d08a2517d51fca07b65550c78d9c2eb458217d6e161ec533fe98964
local     a70ac57ff1d5cdd3c0e386c75783fdea4f2ab8847b4553c5d7163b71452c950f
local     c213a62a6f11a530e55d1625055debb756935155ed0049c744ac0d9b0db6a19b
local     cb3f2b87f9c47c02a413ed0b89c5190bd63b691a0515f89488e447903781ff8f
local     e2eab2b9fd7f5245f93c8912e64ab03048060441ad826c1f3301a9db19fe02ba
local     e68f0462ac4c0f488fa369965a88a71ab8d09624cf68ef7fdf920f9cf7a5dcd5
[root@vm2 ~]# docker volume prune 
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
4e94218a40e8e7e7032d46875f3d017812beded488a583bb0f7c79962721f07f
c213a62a6f11a530e55d1625055debb756935155ed0049c744ac0d9b0db6a19b
e2eab2b9fd7f5245f93c8912e64ab03048060441ad826c1f3301a9db19fe02ba

Total reclaimed space: 40B

2.5  WORKDIR  为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。

[root@vm2 demo]# vim Dockerfile 
FROM busybox
ENV hostname vm2
WORKDIR /nginx
ADD nginx-1.21.6.tar.gz /nginx
VOLUME ["/data"] 
[root@vm2 demo]# docker build -t busybox:v7 .
Sending build context to Docker daemon  1.077MB
Step 1/5 : FROM busybox
 ---> beae173ccac6
Step 2/5 : ENV hostname vm2
 ---> Using cache
 ---> cebb03891923
Step 3/5 : WORKDIR /nginx
 ---> Running in 13d5345cb0fb
Removing intermediate container 13d5345cb0fb
 ---> 46333adf45d3
Step 4/5 : ADD nginx-1.21.6.tar.gz /nginx
 ---> bbe7bb3a02d6
Step 5/5 : VOLUME ["/data"]
 ---> Running in a5db4a665710
Removing intermediate container a5db4a665710
 ---> 6972165107ed
Successfully built 6972165107ed
Successfully tagged busybox:v7
[root@vm2 demo]# docker run -it --rm busybox:v7
/nginx # ls
nginx-1.21.6
/nginx #

进入容器镜像时就默认在/nginx这个目录下,而将nginx的包解压在了这个目录中,这个目录之前并不存在,是WORKDIR自动创建的

2.6 这两个指令都是用于设置容器启动后执行的命令,但CMD会被dockerrun后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效

2.6.1  CMD编辑方式,docker run后面的命令行会覆盖文件中echo所要输出的内容

[root@vm2 demo]# vim Dockerfile 
ENV hostname vm2
WORKDIR /nginx
ADD nginx-1.21.6.tar.gz /nginx
VOLUME ["/data"]
CMD echo hello docker                   
[root@vm2 demo]# docker build -t busybox:v8 .
Sending build context to Docker daemon  1.077MB
Step 1/6 : FROM busybox
 ---> beae173ccac6
Step 2/6 : ENV hostname vm2
 ---> Using cache
 ---> cebb03891923
Step 3/6 : WORKDIR /nginx
 ---> Using cache
 ---> 46333adf45d3
Step 4/6 : ADD nginx-1.21.6.tar.gz /nginx
 ---> Using cache
 ---> bbe7bb3a02d6
Step 5/6 : VOLUME ["/data"]
 ---> Using cache
 ---> 6972165107ed
Step 6/6 : CMD echo hello docker
 ---> Running in 31994c2b2989
Removing intermediate container 31994c2b2989
 ---> 6ee395d6f7b5
Successfully built 6ee395d6f7b5
Successfully tagged busybox:v8
[root@vm2 demo]# docker run --rm busybox:v8        ##执行了文件中CMD后的echo命令
hello docker
[root@vm2 demo]# docker run --rm busybox:v8 ls     ##运行容器时ls覆盖了文件中CMD后echo命令, CMD后的命令不会输出
nginx-1.21.6

2.6.2 ENTRYPOINT编辑方式,docker run后面的命令行不会覆盖文件中echo所要输出的内容

[root@vm2 demo]# vim Dockerfile 
FROM busybox
ENV hostname vm2
WORKDIR /nginx
ADD nginx-1.21.6.tar.gz /nginx
VOLUME ["/data"]
ENTRYPOINT echo hello docker
[root@vm2 demo]# docker build -t busybox:v9 .
Sending build context to Docker daemon  1.077MB
Step 1/6 : FROM busybox
 ---> beae173ccac6
Step 2/6 : ENV hostname vm2
 ---> Using cache
 ---> cebb03891923
Step 3/6 : WORKDIR /nginx
 ---> Using cache
 ---> 46333adf45d3
Step 4/6 : ADD nginx-1.21.6.tar.gz /nginx
 ---> Using cache
 ---> bbe7bb3a02d6
Step 5/6 : VOLUME ["/data"]
 ---> Using cache
 ---> 6972165107ed
Step 6/6 : ENTRYPOINT echo hello docker
 ---> Running in 715694ec8a58
Removing intermediate container 715694ec8a58
 ---> 87b3a373d13c
Successfully built 87b3a373d13c
Successfully tagged busybox:v9
[root@vm2 demo]# docker run -it --rm busybox:v9
hello docker
[root@vm2 demo]# docker run -it --rm busybox:v9 ls    ##用ENTRYPOINT方式编辑后,echo后的输出内容不会被覆盖
hello docker

2.7 RUN  在容器中运行命令并创建新的镜像层,常用于安装软件包

[root@vm2 demo]# vim Dockerfile 
FROM centos:7
RUN yum install -y pcre-devel
[root@vm2 demo]# docker build -t centos:v1 .
.....
Complete!
Removing intermediate container 1f8aa8292c49
 ---> 4f7c0b7f02c1
Successfully built 4f7c0b7f02c1
Successfully tagged centos:v1
[root@vm2 demo]# docker history centos:v1
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
4f7c0b7f02c1   About a minute ago   /bin/sh -c yum install -y pcre-devel            171MB     
eeb6ee3f44bd   9 months ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      9 months ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      9 months ago         /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

3. Shell和exec格式的区别

3.1 Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量

[root@vm2 demo]# vim Dockerfile  
FROM centos:7
RUN yum install -y pcre-devel
ENV HOSTNAME vm2
CMD echo "hello $HOSTNAME"
[root@vm2 demo]# docker build -t centos:v2 .
Sending build context to Docker daemon  1.077MB
Step 1/4 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/4 : RUN yum install -y pcre-devel
 ---> Using cache
 ---> 4f7c0b7f02c1
Step 3/4 : ENV HOSTNAME vm2
 ---> Running in 27a73e988532
Removing intermediate container 27a73e988532
 ---> 3afd2ae3e8cd
Step 4/4 : CMD echo "hello $HOSTNAME"
 ---> Running in db45d44d800a
Removing intermediate container db45d44d800a
 ---> 95a0bfc8780e
Successfully built 95a0bfc8780e
Successfully tagged centos:v2
[root@vm2 demo]# docker run -it --rm centos:v2
hello vm2

3.2 exec格式则不会调用/bin/sh -c来执行命令,不会解析变量

[root@vm2 demo]# vim Dockerfile 
FROM centos:7
RUN yum install -y pcre-devel
ENV HOSTNAME vm2
CMD ["/usr/bin/echo", "hello $HOSTNAME"]
[root@vm2 demo]# docker build -t centos:v3 .
Sending build context to Docker daemon  1.077MB
Step 1/4 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/4 : RUN yum install -y pcre-devel
 ---> Using cache
 ---> 4f7c0b7f02c1
Step 3/4 : ENV HOSTNAME vm2
 ---> Using cache
 ---> 3afd2ae3e8cd
Step 4/4 : CMD ["/usr/bin/echo", "hello $HOSTNAME"]
 ---> Running in d779e71086d9
Removing intermediate container d779e71086d9
 ---> 2771036a6065
Successfully built 2771036a6065
Successfully tagged centos:v3
[root@vm2 demo]# docker run -it --rm centos:v3
hello $HOSTNAME                       ##直接输出了变量的字符,没有解析

3. 3  exec格式如果需要解析变量,则需要手动调用

[root@vm2 demo]# vim Dockerfile 
[root@vm2 demo]# cat Dockerfile 
FROM centos:7
RUN yum install -y pcre-devel
ENV HOSTNAME vm2
CMD ["/bin/sh", "-c","echo hello $HOSTNAME"]    ##通过手动来调用
[root@vm2 demo]# docker build -t centos:v
v1  v2  v3  
[root@vm2 demo]# docker build -t centos:v4 .
Sending build context to Docker daemon  1.077MB
Step 1/4 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/4 : RUN yum install -y pcre-devel
 ---> Using cache
 ---> 4f7c0b7f02c1
Step 3/4 : ENV HOSTNAME vm2
 ---> Using cache
 ---> 3afd2ae3e8cd
Step 4/4 : CMD ["/bin/sh", "-c","echo hello $HOSTNAME"]
 ---> Running in 7497b4af118a
Removing intermediate container 7497b4af118a
 ---> 49c388eaa47e
Successfully built 49c388eaa47e
Successfully tagged centos:v4
[root@vm2 demo]# docker run -it --rm centos:v4
hello vm2                                       ##通过手动调用后,解析成功

3.4 Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数。

[root@vm2 demo]# vim Dockerfile 
FROM centos:7
RUN yum install -y pcre-devel
ENV HOSTNAME vm2
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]
[root@vm2 demo]# docker build -t centos:v5 .
Sending build context to Docker daemon  1.077MB
Error response from daemon: dockerfile parse error line 4: unknown instruction: INT
[root@vm2 demo]# vim Dockerfile 
[root@vm2 demo]# docker build -t centos:v5 .
Sending build context to Docker daemon  1.077MB
Step 1/5 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/5 : RUN yum install -y pcre-devel
 ---> Using cache
 ---> 4f7c0b7f02c1
Step 3/5 : ENV HOSTNAME vm2
 ---> Using cache
 ---> 3afd2ae3e8cd
Step 4/5 : ENTRYPOINT ["/bin/echo", "hello"]
 ---> Running in ea01406169bf
Removing intermediate container ea01406169bf
 ---> 7f9fe55cd861
Step 5/5 : CMD ["world"]
 ---> Running in 87c795be89e2
Removing intermediate container 87c795be89e2
 ---> 493b16943da0
Successfully built 493b16943da0
Successfully tagged centos:v5
[root@vm2 demo]# docker run -it --rm centos:v5
hello world

3.5 Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数,更直观的感受到上面2.6中,CMD 与 ENTRYPOINT的区别

[root@vm2 demo]# docker run -it --rm centos:v5 westos
hello westos
[root@vm2 demo]# docker run -it --rm centos:v5 linux
hello linux
[root@vm2 demo]# docker run -it --rm centos:v5 redhat
hello redhat
[root@vm2 demo]#

云野 » Docker-Dockerfile方式镜像的构建

发表回复