Docker镜像分层(二)

目录

  • 一、镜像分层
    • 1.概述
    • 2.镜像内容
  • 二、Docker分层原理
    • 1. docker镜像分层
    • 2.涉及的技术
      • ①LXC
      • ②bootfs(boot file system)内核空间
      • ③rootfs(root file system)内核空间
      • ④AUFS与overlay/overlay2(docker 高版本)
      • ⑤overlay结构:
  • 三、联合挂载
  • 四、Dockerfile编写
    • 1.dockerfile
    • 2.dockerfile操作指令
    • 3.编写dockerfile文件-部署Nginx

一、镜像分层

1.概述

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

2.镜像内容

①基础镜像:操作系统(centos7)
②软件包:Nginx、Tomcat、MySQL
③依赖环境(编译环境):gcc、gcc-c++、make
④配置和编译应用服务
⑤调整应用服务的相关配置文件
⑥启动服务/容器开启时、运行时的脚本/命令/指令

二、Docker分层原理

1. docker镜像分层

基于AUFS构建,新的是overlay2
docker镜像是位于bootfs之上,与内核之间进行共享
每一层的下一层为父镜像
第一层镜像作为基础镜像base image(操作环境镜像)
容器层是可读可写的,在最顶层(writable)
容器层以下都是readonly(只读)
①容器层(contaier 读写层):容器(可读可写)
②镜像层(images 只读层):镜像
③基础层(base image 只读层):系统(centos、ubantu、suse……)
④内核层(bootfs+rootfs+aufs(kernel)+LXC)
加上内核共四层

2.涉及的技术

①LXC

LXC是一种内核容器技术,早期docker在没有将资源容器化的功能时,就是靠内核中LXC来完成容器虚拟化的,在被容器引擎管理。
现在docker拥有了自己的docker libcontainer库文件,这种库文件可以将资源容器化的操作,所以对LXC的依赖性大大降低
LXC是内核中的一个容器技术/驱动,功能是将资源容器化(虚拟化),是早期docker的依赖组件,而目前docker拥有自己的libcontainer库,可以实现容器虚拟化的功能,对LXC的依赖性大大降低

②bootfs(boot file system)内核空间

主要包含了bootloader和kernel
bootloader主要是引导加载kernel,Linux刚启动的时候是会加载bootfs文件系统,也是在docker镜像的最底层(bootfs)。
这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载临时创建的用于加载环境的bootfs。
在linux操作系统中(不同版本的linux发行版本),linux加载bootfs时会将rootfs设置为read-only,系统自检后会将只读改为读写,让我们可以在操作系统中进行操作

③rootfs(root file system)内核空间

rootfs在bootf之上(base images,例如centos、ubuntu)
相当于是挂载的目录/dev、/proc、/bin、/etc等标准目录和文件
rootfs就是各种不同的操作系统的发行版
对于操作文件、标准目录等而言,不同操作系统之间也是会有区别的,但是启动的程序bootfs都是一样的,启动rootfs的程序,使用的文件、权限等等也都是一样的
docker正是看中了这点,rootfs直接使用base image镜像的文件系统,而bootfs直接使用内核的。bootfs占用空间,rootfs占用的比较少,所以容器空间占用的会比centos系统较少。
因为虚拟机centos由完整的内核,完整的操作系统。

bootfs+rootfs:作用是加载、引导内核程序+挂载使用Linux操作系统(centos ubantu)等等一些关键目录

④AUFS与overlay/overlay2(docker 高版本)

docker高版本默认使用的存储引擎
AUFS是一种联合文件系统,它使用同一个Linux host上的多个目录,然后逐个堆叠起来,对外呈现出一个统一的文件系统。AUFS使用这个特性实现了Docker镜像的分层

⑤overlay结构:

overlayfs在Linux主机上只有两层,一个目录在下层用来保存镜像(docker),另一个目录在上层用来存储容器信息
存储引擎结构
⑴rootfs 基础镜像
⑵lower 下层信息(为镜像层,容器,可读)
⑶upper 上层目录(容器信息,可写)
⑷worker 运行的工作目录(copy-on-write写时复制-》 准备容器环境)
⑸merged “视图层”(容器视图)

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

三、联合挂载

cd /mnt 
mkdir lower upper worker meged
echo “lower.aaaa” > lower/aaaa
echo “lower.bbbb” > lower/bbbb
echo “upper.bbbb” > upper/aaaa
echo “upper.cccc” > upper/cccc
mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workerdir=worker meged
df -Th

四、Dockerfile编写

dockerfile编写制作镜像时,镜像会很大,所以每次推送到docker hub只推送增量部分(因为镜像底包比较大,增量推送给/更新部分比较小),所以生产上,只要你执行的镜像再推送的时候增量部分控制到比较小的一个范围就可以
在项目初期考虑到不断的更新迭代,所以要优化镜像,减少镜像大小

1.dockerfile

dockerfile是由一组指令组成的文件
①dockerfile结构
⑴基础镜像信息(指定操作系统镜像是什么镜像、什么版本)
⑵维护者信息(可以省略)
⑶镜像操作指令
⑷容器启动时执行指令(启动容器的时候执行的脚本/命令参数等等)
dockerfile每行支持一条指令,每条指令可以携带多个参数,支持使用“#”号开头注释 &&
②构建镜像命令(PS:可在构建镜像时指定资源限制)
-t:tag打标签
-f:指定dockerfile目录
.: 指构建镜像时使用的环境(当前)目录,构建镜像时使用的上下文环境
PS:
ADD是可以复制完解压
COPY只能复制
CMD与entrypoint:都是容器启动时要加载的命令
exec与shell
exec:容器加载时使用的启动的第一个任务进程
shell:容器加载时使用的第一个bash(/bin/bash,/bin/sh,/bin/init)
在有cmd,使用/bin/bash会优先使用/bin/bash环境,不使用/bin/bash环境则会使用cmd
指令,因为多条cmd命令只有最后一条生效,/bin/bash就相当于一条cmd命令
示例:

cd demo1
vim Dockerfile
From centos:7
CMD [“top”]
docker build -t centos:v1 .
 
docker run -itd --name test centos:v1 /bin/bash
docker run -itd --name test2 centos:v1 
docker ps -a
 
docker exec test ps aux
docker exec test2 ps aux

shell可以输出环境变量,而exec不行
示例:

vim Dockerfile
From centos:7
CMD [“echo”,"$HOME"]
直接echo $HOME
 
docker build -t "centos:v2" .
 
docker run --name test3 --rm centos:v2
 
vim Dockerfile
From centos:7
CMD ["sh","-c","echo $HOME"]
docker build -t centos:v3
 
docker run --name test4 --rm centos:v3

自检完成后,加载的第一个pid 1进程
cmd是容器环境启动时默认加载的命令
entrypoint是容器环境启动时第一个加载的命令程序/脚本程序 init
如果entrypoint使用了shell模式,cmd指令会被忽略
如果entrypoint使用了exec模式,cmd指定的内容被追加为entrypoint指定命令的参数
如果entrypoint使用了exec模式,cmd也应该使用exec模式

2.dockerfile操作指令

①FROM 镜像:指定新镜像所基于的镜像,第一条指令必须为from指令,每创建一个镜像就需要一条from指令
②MAINTAINER名字(选写):说明新镜像的创建、维护人信息
③RUN 命令:在所基于的镜像上执行命令,并提交到新的镜像中;docker内每执行一条命令都是run开头(run make & make install、run yum -y install -y -gcc gcc-c++ make)
④CMD[“要运行的程序”,“参数1”,“参数2”]:指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令, 如果指定多条则只能最后一条被执行
⑤EXPOSE端口号:指定新镜像加载到Docker时要开启的端口
⑥ENV 环境变量 变量值:设置一个环境变量的值,会被后面的run使用(jdk环境)
⑦ADD 源文件/目录 目标文件/目录:具体识别压缩格式并且自动解压,;将源文件复制到目标文件,源文件要与dockerfile位于相同目录中,或者一个URL(地址)
⑧COPY 源文件/目录 目标文件/目录:将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中
PS:COPY与ADD的区别:COPY只能用于复制,ADD复制的同时,如果复制的对象是压缩,ADD还可以解压
⑨VOLUME [“目录"]:在容器中创建一个挂载点
⑩USER 用户名/UID:指定运行容器时的用户
⑪WORKDIR 路径:为后续的RUN、CMD、ENTRYPOINT指定工作目录(跟执行脚本一样需要到文件目录下【cd】)
⑫ONBUILD命令:指定所生成的镜像作为一个基础镜像时所要运行的命令
⑬HEALTHCHECK:健康检查

3.编写dockerfile文件-部署Nginx

编写步骤模板:
①创建一个对应的目录(mkdir nginx)
②编写dockerfile文件(最简单的方式,nginx部署脚本放进去,每条命令用run执行,环境变量使用ENV,移动到对应目录使用workdir,最后使用CMD进行启动设置)
③在nginx目录中上传nginx-1.12.2.tar.gz软件包等文件
④docker build 创建
⑤docker run 运行容器
⑥检验
内容:

FROM centos:7
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make
ADD nginx-1.15.9.tar.gz /mnt 
WORKDIR /mnt/nginx-1.15.9
#关闭debug日志
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc 
RUN ./configure --prefix=/usr/local/nginx 
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
docker build -t "nginx:v1" .

你可能感兴趣的:(docker,容器,运维)