Docker--dockerfile构建镜像

本文详细介绍了Dockerfile的概念和结构,包括如何基于Dockerfile创建镜像,以及Docker镜像的分层原理。讨论了CMD和ENTRYPOINT的使用区别,以及Docker镜像的构建和缓存机制。此外,还涵盖了镜像的存储驱动,如AUFS和overlay,以及联合文件系统在Docker中的应用。
摘要由CSDN通过智能技术生成


一、Dockerfile概念

Docker是一个文本文件,文件中包含了一条条的指令(instruction),用于构建镜像。每一条指定构建一层镜像,因此每一条指令的内容,就是描述该层镜像应当如何构建

  • dockerfile是自定义镜像的一套规则
  • docker由多条指定构成,docker的每一条指令都会对应于docker镜像中的每一层

dockerfile的原理就是镜像分层

  • Dockerfile中的每一个指定都会创建一个新的镜像层(是一个临时的容器,执行完后将不再存在,再往后进行重新的创建与操作)
  • 镜像曾被缓存和复用(后续的镜像层基于前面的每一层,每一层都会有下几层的缓存)
  • 当Dockerfile的指令修改了,复制的文件变化了,或构建镜像时指定的变量不同了,那么对应的镜像层缓存就会失效(因为后续的操作必然更改前面的镜像层)
  • 某一层的镜像缓存失效了之后,它之后的镜像层缓存就会失效(第一层不成功,那么第二层也会失效)
  • 容器的修改并不会影响镜像,如果在某一层中添加一个文件,在下一层中删除它,镜像中依然会包含该文件
    在这里插入图片描述

二、Docker镜像的创建

创建镜像有三种办法

  • 基于已有镜像的创建
  • 基于本地模板创建
  • 基于Dockerfile创建

1.基于已有镜像创建

原理:将容器里面运行的程序及运行环境打包生成新的镜像

docker commit [选项] [容器id] 仓库名:标签

常用选项

选项描述
-m说明信息
-a作者信息
-p生成过程中停止容器的运行

基于已有镜像创建案例
在这里插入图片描述

2.基于本地模板创建

原理:通过导入操作系统模板文件生成新的镜像

wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
#使用wget命令导入为本地镜像

docker import debian-7.0-x86-minimal.tar.gz -- debian:v1
或
cat debian-7.0-x86-minimal.tar.gz |docker import - debian:v1
#生成镜像

docker images
#查看镜像

docker run -itd debian:v1 bash
#创建并启动容器

在这里插入图片描述
在这里插入图片描述

3.基于dockerfile创建

  • dockerfile是一组指令组成的文件
  • dockerfile每行支持一条指令,每条指令可携带多个参数,一条指令可以用&&方式,去写多条指令
  • dockerfile支持以"#"为开头的注释

3.1dockerfile结构

  • 基于镜像信息(linux发行版:比如centos、ubuntu、suse、debian、alpine、redhat)
  • 维护者信息(docker search可查看)
  • 镜像操作指令(tar yum make)
  • 容器启动时执行指令(cmd [“/root/run/sh”]、entrypoint、都是系统启动时,第一个加载的程序/脚本/命令)

3.2构建镜像的命令

可以在构建镜像时指定资源限制

在编写Docker时,需要遵守严格的格式

  • 第一行必须使用FROM指令指明所基于的镜像名称
  • 之后使用MAINTAINER指令说明维护该镜像的用户信息
  • 然后是镜像操作相关指令,如RUN指令。每一条指令,都会给基础镜像添加新的一层
  • 最后使用CMD指令指定启动容器时,要运行的命令操作

三、镜像分层的原理

Docker镜像结构的分层
镜像不是一个单一的文件,而是有多层结构构成。容器其实在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读可写层的容器层

  • Dockerfile中的每个指令都会创建一个新的镜像层
  • 镜像层将被缓存和复用
  • 当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
  • 某一层的镜像缓存失效,它之后的镜像层缓存都会失效
  • 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在Docker容器中不可见了

1.docker镜像分层(基于AUFS构建)

  • docker镜像位于bootfs之上
  • 每一层镜像的下一层为父镜像
  • 每一层镜像称为base images(操作系统环境镜像)
  • 容器层(可读可写,为了给用户操作),在最顶层(writeable)
  • 容器层以下都是readonly
    在这里插入图片描述

2.bootfs内核空间

主要包含bootloader(引导程序)和kernel(内核)

  • bootloader主要引导加载kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs
  • 这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就在内存中了,此时内存的使用权由bootfs交给内核,此时系统也会写在bootfs
  • 在linux操作系统中,linux加载bootfs时会将rootfs设置为read-only,系统自检后会将只读改为读写,让我们可以在操作系统中进行操作

3.rootfs内核空间

  • bootfs之上(base images,例如centos、ubuntu)
  • 包含的就是典型的linux系统中的/dev、/proc、/bin、/etc等标准目录和文件
  • rootfs就是各种不同的操作系统发行版

4.AUFS与overlay/overlay2

AUFS是一种联合文件系统,它使用同一个linux host上的多个目录,逐个堆叠起来,对外呈现出一个同一的文件系统,AUFS使用该特性,实现了Docker镜像的分层

  • 而docker使用了overlay/overlay2存储驱动来支持分层结构
  • overFS将单个linux主机上的两个目录合并成一个目录,这些目录被称为层,统一过程被称为联合挂载

4.1overlay结构

overlay在linux主机上只有两层,一个目录在下层,用来保存镜像,另一个目录在上层,用来存储容器信息

rootfs    #基础镜像
lower     #下层信息(为镜像层,只读)
upper     #上层目录(容器信息,可写)
worker    #运行的工作目录(copy-on-write写时复制-->准备容器环境)
mergod    #视图层(容器视图)

#docker 镜像层次结构总结
1、base images :基础镜像
2、image :固化了一个标准运行环境,镜像本身的功能-封装一组功能性的文件,通过统一的方式,文件格式提供出来(只读)
3、container :容器层(读写)
4、docker-server 端
5、呈现给docker-client(视图)

5.联合文件系统(UnionFS)

UnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。AUFS、OverlayFS及Devicemapper都是一种UnionFS

Union文件系统是Docker镜像的基础:镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像

特性
一次同时加载多个文件系统,但从外面看起来,智能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

从仓库下载时,我们看到的一层层就是联合文件系统

6.镜像加载原理

  • 在Docker镜像的最底层是bootfs,这一层与我们典型的linux/unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
  • rootfs在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等
  • 我们可以理解成一开始内核里什么都没有,①操作一个命令下载debian,这时就会在内核上面加一层基础镜像;②再安装一个apache,又会在images上层叠加一层image。最后看起来就想一个文件系统即容器的rootfs。在Docker的体系里把这些rootfs叫做Docker的镜像③但是,此时的每一层rootfs都是read-only的,我们此时还不能对其进行操作。当我们创建一个容器,也就是将Docker镜像进行实例化,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs

四、dockerfile操作指令

指令含义
FROM指定新镜像所基于的镜像。 第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令, 例如:centos 7from有两层含义: ①开启一个新的镜像,②必须写的一行指令
MAINTAINER说明新镜像的维护人信息(可写可不写)
RUN命令每一条RUN后面跟一条命令 ,在所基于的镜像上执行命令,并提交到新的镜像中, RUN必须大写。
CMD [“要运行的程序”,“参数1”,“参数2”]指定启动容器时需要运行的命令或脚本, Dockerfile只能有一条CMD命令, 如果指定多条则只能执行最后一条,“/bin/bash”也是一条CMD,并且会覆盖images镜像里面的cmd
ENTRYPOINT [“要运行的程序”,“参数1”,“参数2”]设定容器启动时第一个运行的命令及其参数。可以通过使用命令:docker run --entrypoint 来覆盖镜像中的ENTRYPOINT指令的内容
EXPOSE [端口号]指定新镜像加载到Docker时要开启的端口 “暴露端口”,就是这个容器暴露出去的端口号。
ENV [环境变量] [变量值]设置一个 “ 环境变量 ”的值,会被后面的RUN使用,容器可以根据自己的需求创建时传入环境变量,镜像不可以
ADD [源文件/目录] [目标文件/目录]①将源文件复制到目标文件, 源文件要与Dockerfile位于相同目录中。 ②或者时一个URL。 ③若源文件时压缩包的则会将其解压。
COPY [源文件/目录] [目标文件/目录]将本地主机上的文件/目录复制达到目标地点,源文件/目录要与Dockerfile在相同的目录中, copy只能用于复制,add复制的同时,还可以将对象解压, copy比add节省资源
VOLUME [“目录”]在容器中创建一个挂载点,简单来说就是 -v,指定镜像的目录挂载到宿主机上。
USER [用户名/UID]指定运行容器的用户
WORKDIR [路径]为后续的RUN、CMD、ENTRYPOINT指定工作目录, 相当于一个临时的“CD ” ,否则需要使用绝对路径,例如 workdir /opt ,移动到opt目录下, 后续执行的指令都是在/opt下面操作
ONBUILD [命令]指定所生成的镜像作为一个基础镜像时所要运行的命令 “(是一种优化)”
HEALTHCHECK健康检查

1.CMD和ENTRYPOINT介绍

要想了解cmd和entrypoint的区别,首先必须了解到exec模式和shell模式的区别

1.1exec和shell模式的区别

exec模式:容器加载时使用的启动的第一个任务进程
shell模式:容器加载时第一个bash环境(/bin/bash、/bin/sh、/bin/init)

1.2exec模式下传入命令

构建镜像时传入CMD,启动容器时不传入CMD

cd /opt
mkdir test
#创建Dockerfile的工作目录

vim Dockerfile
FROM centos:7
CMD ["top"]
#编写Dockerfile文件

docker build -t centos:7 .
#基于dockerfile构建镜像

docker run -it --name test centos:7
#基于构建好的镜像启动容器

docker logs test
#查看执行的命令

docker exec test ps sux 
#传入ps aux 命令执行,查看结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
启动时传入/bin/bash命令

docker run -itd --name test01 test centos:7 /bin/bash
#基于构建好的镜像启动容器,并且加上/bin/bash命令

docker exec test01 ps aux
#通过exec 传入命令查看执行效果

在这里插入图片描述

1.3使用exec模式无法输出环境变量

cd /opt/test
vim Dockerfile
FROM centos:7
CMD ["echo","$HOME"]
#编写新的dockerfile文件

echo $HOME
#有shell环境下输出的变量值

docker build -t centos:new.
#构建dockerfile镜像

docker images
#查看镜像

docker run -itd --new ydq centos:new
#基于构建好镜像的启动容器

docker ps 
#查看运行的容器

docker logs new
#查看执行结果

在这里插入图片描述
在这里插入图片描述

1.4shell模式


vim Dockerfile
FROM centos:7
CMD ["sh","-c","echo $HOME"]
#编写一个dockerfile文件
 
docker build -t centos:new2
#基于文件编写centos:new2的镜像
 
docker images
#查看镜像
 
docker run -itd --name new2 centos:new2
#启动容器
 
docker logs new2
#查看输出日志

在这里插入图片描述
在这里插入图片描述

1.5小结

例:区别shell 模式和exec 模式
/bin/sh -c nginx         #shell 模式
nginx                    # exec模式
 
exec 和shell 之间的区别  
exec 不可用输出环境变量
shell 模式可以输出环境变量
 
 
cmd 是容器环境启动时默认加载的命令
entrypoint 是容器环境启动时第一个加载的命令程序/脚本程序 init 
 
如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略。
 
如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数。
 
如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式。

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值