Dockerfile使用介绍

一、Dockerfile概念
  Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。我们使用Dockerfile定义镜像,依赖镜像来运行容器,因此Dockerfile是镜像和容器的关键。首先通过一张图来了解Docker镜像、容器和Dockerfile三者之间的关系。
  在这里插入图片描述
  通过上图我们可以看出使用Dockerfile来定义镜像,运行镜像然后启动镜像。
  Dockerfile镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包括一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
  镜像的定制实际上就是定制每一层所添加的配置文件;如果我们可以把每一层的修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决了。这个脚本就是Dockerfile。
  Dockerfile是一个文本文件,其包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了Dockerfile,当我们需要定制自己额外的需求时,只需要再Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。

二、Dockerfile的基本结构
Dockerfile由一行行命令语句组成,并支持以#开头的注释行。
Dockerfile文件格式如下:

1 ##  Dockerfile文件格式
2 # This dockerfile uses the ubuntu image
3 # VERSION 2 - EDITION 1
4 # Author: docker_user
5 # Command format: Instruction [arguments / command] ..
6 # 1、第一行必须指定 基础镜像信息
7 FROM ubuntu
8 # 2、维护者信息
9 MAINTAINER docker_user docker_user@email.com
10 # 3、镜像操作指令
11 RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
12 RUN apt-get update && apt-get install -y nginx
13 RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
14 
15 # 4、容器启动执行指令
16 CMD /usr/sbin/nginx

Dockerfile分为四部分:1.基础镜像信息、2.维护者信息、3.镜像操作指令、4.容器启动执行指令。一开始必须要指明所基于基础镜像的名称,接下来一般会说明维护者信息;后面则是镜像操作指令,例如RUN指令。每执行一条RUN指令,镜像添加新的一层,并提交;最后是CMD指令,来指明运行容器时的操作指令。

三、构建镜像
  docker build命令会根据Dockerfile文件以及上下文构建新的Docker镜像。构建上下文是指Dockerfile所在的本地路径或一个URL(Git仓库地址)。构建上下文环境会被递归处理,所以构建所指定的路径还包含了子目录,而URL还包括了其中指定的子模块。
  将当前目录作为构建上下文时,可以像下面这样使用docker build命令构建镜像:

1 docker build .
2 Sending build context to Docker daemon  6.51 MB
3 ...

说明:构建会在Docker后台的守护进程(daemon)中执行,而不是CLI中。构建前,构建进程会将全部内容(递归)发送到守护进程。大多数情况下,应该将一个空目录作为构建Dockerfile上下文环境,并将Dockerfile文件放在该目录下。
  在构建上下文中使用的Dockerfile文件,是一个构建指令的文件。为了提高构建性能,可以通过.dockerignore文件排除上下文目录下不需要的文件和目录。
  在Docker构建镜像的第一步,docker CLI会先在上下文目录中寻找.dockerignore文件,根据.dockerignore文件排除上下文目录中的部分文件和目录,然后把剩下的文件和目录传递给Docker服务。
  Dockerfile一般位于构建上下文的根目录,也可以通过-f来指定该文件的位置:

1 docker build -f /path/to/a/Dockerfile .

构建时,还可以通过-t参数来对指定构建成的镜像打标签。

四、缓存
  Docker守护进程会一条一条的执行Dockerfile中的指令,而且会在每一步提交并生成一个新镜像,最后会输出最终镜像的ID。生成完成后,Docker守护进程会自动清理你发送的上下文。Dockerfile文件中的每条指令会被独立执行,并会创建一个新镜像,RUN cd /tmp等命令不会对下条指令影响。Docker会重用已经生成的中间镜像,以加速docker build的构建速度。以下是一个使用了缓存镜像的执行过程:

1 $ docker build -t svendowideit/ambassador .
2 Sending build context to Docker daemon 15.36 kB
3 Step 1/4 : FROM alpine:3.2
4  ---> 31f630c65071
5 Step 2/4 : MAINTAINER SvenDowideit@home.org.au
6  ---> Using cache
7  ---> 2a1c91448f5f
8 Step 3/4 : RUN apk update &&      apk add socat &&        rm -r /var/cache/
9  ---> Using cache
10  ---> 21ed6e7fbb73
11  Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-
12  ---> Using cache
13  ---> 7ea8aef582cc
14 Successfully built 7ea8aef582cc

构建缓存仅会使用本地父生成链上的镜像,如果不想使用本地缓存的镜像,也可以通过–cache-from指定缓存。指定后将不再使用本地生成的镜像链,而是从镜像仓库中下载。

Docker寻找缓存的逻辑其实就是树形结构根据Dockerfile指令遍历子节点的过程。下图可以说明这个逻辑。

 FROM base_image:version           Dockerfile:
           +----------+                FROM base_image:version
           |base image|                RUN cmd1  --> use cache because we found base image
           +-----X----+                RUN cmd11 --> use cache because we found cmd1
                / \
               /   \
       RUN cmd1     RUN cmd2           Dockerfile:
       +------+     +------+           FROM base_image:version
       |image1|     |image2|           RUN cmd2  --> use cache because we found base image
       +---X--+     +------+           RUN cmd21 --> not use cache because there's no child node
          / \                                        running cmd21, so we build a new image here
         /   \
RUN cmd11     RUN cmd12
+-------+     +-------+
|image11|     |image12|
+-------+     +-------+

大部分指令可以根据上述逻辑去寻找缓存,除了ADD和COPY。这两个指令会复制文件内容到镜像内,除了指令相同以外,Docker还会检查每个文件内容校验(不包括最后修改时间和最后访问时间),如果检验不一致,则不会使用缓存。
  除了这两个命令,Docker并不会去检查容器内的文件内容,比如RUN apt-get -y update,每次执行时文件可能都不一样,但是Docker认为命令一致,会继续使用缓存。这样一来,以后构建时都不会再重新运行apt-get -y update。
  如果Docker没有找到当前指令的缓存,则会构建一个新的镜像,并且之后所要的指令都不会再去寻找缓存。

五、利用Dockerfile构建镜像的简单示例
1)编辑Dockerfile文件
  接下来用一个简单的示例来感受一下Dockerfile是如何用来构建镜像启动容器。我们以定制Nginx镜像为例子,在一个空白目录中,建立一个文本文件,并命名为Dockerfile:

1 mkdir mynginx
2 cd mynginx
3 vim Dockerfile

构建一个Dockerfile文件内容为:

1 FROM nginx
2 #前提是使用yum安装nginx,或者指定nginx中的index.html的位置
3 RUN echo '<h1>Hello,Docker!</h1>' > /usr/share/nginx/html/index.html

这个Dockerfile很简单,一共就两行涉及到了两条指令:FROM和RUN。FROM表示获取指定的基础镜像,RUN执行命令,在执行的过程中重写了nginx的默认页面信息,并将信息替换为:Hello,Docker!。

2)构建镜像
  在Dockerfile文件所在的目录执行(或者通过-f选项来指定其路径):

1 # 命令最后有一个.表示的当前目录
2 docker build -t nginx:v1 . 

3)查看镜像
  构建完成之后,使用docker image命令查看所有的镜像,如果存在REPOSITORY为nginx和TAG是v1的信息,就表示构建成功。

REPOSITORY                    TAG                 IMAGE ID            CREATED              SIZE
nginx                         v1                  c7ccff6ef09b        About a minute ago   126MB
nginx                         latest              ab56bba91343        2 days ago           126MB

4)运行镜像
  接下来我们就可以使用docker run 命令来启动容器

[root@docker mynginx]# docker run --name docker_nginx_v1 -d -p 80:80 nginx:v1 
4af7cb4e7f917aee15bc0bdddc6b2f1deae9dc46724145eb986b981ebb7816c4
[root@docker mynginx]# docker port docker_nginx_v1 
80/tcp -> 0.0.0.0:80
[root@docker mynginx]# 

这条命令会用nginx镜像启动一个容器,命名为docker_nginx_v1,并且映射到了宿主机的80端口,这样我们就可以用浏览器去访问这个nginx服务器:xx.xx.xx.xx,页面返回信息入下:
  在这里插入图片描述
  这样一个简单使用Dockerfile构建镜像并运行容器的实例就完成了。

5)修改容器内容
  容器启动后,如果需要对容器内的文件进行进一步的完善,我们可以使用docker exec -it xx /bin/bash命令进入容器实例内再次对容器的配置进行修改,以上面的示例为基础,修改nginx启动的页面内容:

[root@docker mynginx]# docker exec -it  docker_nginx_v1  /bin/bash
root@4af7cb4e7f91:/# echo "<h1>Hello,Docker JiangYiYang</h1>" > /usr/share/nginx/html/index.html 
root@4af7cb4e7f91:/# exit
exit

在这里插入图片描述
  以交互式终端的方式进入docker_nginx_v1容器,并执行了bash命令,也就是获得了一个可操作的Shell。然后,我们用<h1>Hello,Docker JiangYiYang</h1>覆盖了/usr/share/nginx/html/index.html的内容。再次刷新浏览器,会发现内容被改变。
  修改了容器的文件,也就是改动了容器的存储层,可以通过docker diff命令看到具体的改动。

[root@docker mynginx]# docker diff docker_nginx_v1 
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
C /run
A /run/nginx.pid
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /root
A /root/.bash_history

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值