博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019/08/02 docker镜像文件制作(01)
阅读量:3926 次
发布时间:2019-05-23

本文共 7551 字,大约阅读时间需要 25 分钟。

docker主机时运行docker容器的核心组件,但docker自身并不是容器,容器是使用内核提供的,docker本身仅是一个容器管理器,docker事实上运行在用户空间的守护进程

一方面守护运行在本机上的各容器状态
二,守护着也能接收客户端发送的请求,随意响应客户端请求,
docker的守护进程还有另外的作用,包括设置网络环境,比如提供docker0网络桥,虽然可以自定义桥的地址,但是桥的使用方式的确是由docker守护进程来完成的
如果运行容器,这些容器就运行在当前主机之上,让当前主机的docker守护进程来负责监控
除此之外还需要有一个空间,来存储本地的,镜像文件
这些镜像文件是只读的,所以可以启动多个容器,不需要把镜像文件复制,只需要为此容器添加一个读写层,因为底层都是只读的
还需要使用DM device mapper来实现联合挂载,ubuntu是unionfs(升级为AUFS高级联合文件系统)
其他的也可以支持分层存储,完成联合挂载,btrfs overlayfs2
这是在本地存储镜像文件的所谓的系统,支持联合挂载的文件系统
在这里插入图片描述
好在这种文件系统是基于grub来进行定义的,用docker自行管理,无需做其他多余的设定,一开始按照好,本地的镜像仓库可能是空的,,需要去获取镜像的时候通常可以使用dockerpull到远程的registry主机上,下载和获取,一个下载请求,是由daemon发出的,发出以后,获取,存储到本地,
远程的仓库,也可以不存镜像,支持多种驱动方式,或者多种远程存储的驱动方式,把数据存储在不同的存储设备上,、可以存在本地,也可以存在后端存储驱动(NFS,NOS,swift这种所谓的存储系统)
当用户是由docker search发出请求,这个search请求的操作,会发给index,index在索引当中,获取指定镜像文件的访问路径,而后基于这个路径,把数据取出来,响应给docker daemon,
docker同一个镜像文件,大家都可以用,每一个docker容器修改不是修改镜像文件,而是修改最上层的读写层,
而对这个容器运行来讲,对于容器的自身来讲,最起码,
(关闭容器,容器的只读层依然在仓库中,但读写层就由容器自身做保存,容器停止,还在,只是并不运行而已,可以理解为是容器自己的读写层,以后拿这个读写层和定义联合底层文件系统,照样能启动一模一样的容器)
每一个容器一般从创建开始,到停止结束。类似于此前docker - -RM选项,一停止自动删除,读写层数据就没了
为了让数据持久存储,要使用卷,这样容器仅仅当作一个程序来跑了
在这里插入图片描述为了让数据持久存储,要使用卷,这样容器仅仅当作一个程序来跑了,在docker内每一个容器通常只是跑一个程序的,一个进程和子进程,通常只是用来跑一个程序及其相关的所有进程
容器代表了生命周期,进程不运行,容器随之结束,在容器内部,如果只是为了运行单个进程,即便不是单个进程,容器要想运行,这个进程必须running,这样docker的进程才能捕捉到,一旦运行到后台去,就认为这个进程中止了,就会把对于的容器关掉,删除了,这是比较尴尬的
在这里插入图片描述
对于此前经常以守护进程运行的服务来讲,此时都应该运行在前台,这个容器只代表了程序和它代表的所依赖环境的最小化,而后打包运行起来了,不依赖整个操作系统多余的环境了,跟操作系统真正运行的交互式环境没有任何关系
它只是为了自己的运行 而创建,为了自运行而终止,不影响任何外面的内容
只需要在本地留下一些探测点,生成 的数据,这些数据通过卷来保存,而卷通常有两种形式 ,
docker 卷
绑定卷 自己指定主机上的路径,和容器中的卷路径, 而docker管理的卷则只需要指定容器中的卷路径,在主机上的路径一般而言,默认在/var/lib/docker/volumes的目录下,这就是为了持久的,持久的好处,任何卷在启动时容器内部的目录就存在, 而这里面有数据,启动后会立即自动把里面数据复制到卷上来,以确保能持久,
如果容器原来目录的就有数据,就把它指定为卷,显然它的数据要立即反应到主机目录上,所以容器启动会自动把数据复制到主机目录一份,
在容器内做的任何操作都保存在主机目录上,通过主机目录所做的任何操作,也都直接反应到容器中
部署网页站点的时候,不用部署到容器内,仍然部署到主机目录下即可
加入将来更新一个tomcat版本,把这里的镜像所启动的tomcat,在基于这个新镜像启动一个容器,更新里面的目录就是了,或者再启动另外一个卷就是,另外一个容器启动时直接复制这个容器的卷

如果要发布自己对应的内容,就是我们的页面资源的话,可能依然需要我们蓝绿发布,一半一半

或者做灰度

对docker而言是如何实现通信,内部的每一个容器启动起来后,就可以相当于一台虚拟机来使用了,

但docker由于使用名称空间方式,灵活度比此前的kvm多了好几项,
docker的容器模型,有4中
1.封闭式容器,closed container没有网卡,只有本地回环接口 ,不需要网络通信
2.共享主机网络名称空间 open container开放式容器,很危险
3.bridged container 桥接式容器,与kvm桥没什么本质上的不同,nat 桥,仅主机桥,隔离桥。物理桥
4.joined container 联盟式容器 相当于让两个容器共享一个网络名称空间 ,这两个容器的程序可以通过lo接口通信了,可以高效通信,mysql和httpd,虽然把容器隔离成一个个进程了,彼此也能用joined container完成交换通信的,
K8S的时候,大概是两种方式联合起来使用的,
如果创建容器没创建,默认的使用docker0桥,nat桥,能够访问网络中的主机,而访问方式是通过SNAT进行的,
所以内部的容器是无法被外部的主机访问的,除非暴露出去,把对应端口expose暴露出去,所谓暴露,在我们宿主机上做了一个DNAT规则
相当于把宿主机对应的网络接口上的某一端口,映射到容器的指向端口上,而并不一定是对等映射的,端口有可能不一样,而暴露的方式,有可能启动容器时,可以使用-p选项,来定义
-p container port (cport)随机暴露
如果要自己指定容器端口,又要固定在宿主机上,就需要 -p hport(host port 主机端口):cport(容器端口)
要固定ip地址 就需要-p hip::cport 但是端口随机的
端口也不想随机 -p hip:hport:cport
docker用的NAT网络,对真正物理机的网络性能影响还是不可忽视的,以至于K8S就完全没使用这样的通信方式,用overlaynetwork addlaynetwork来完成
在这里插入图片描述
如果两个docker主机上的容器需要通信,用NAT很麻烦,第一个容器需要先SNAT出去,第二个容器需要通过DNAT接收进来,
在这里插入图片描述
镜像文件创建有几种方式
1.基于容器创建,基于读写层做成镜像,commit就可以制作成镜像
2.基于dockerfile,来自动构建

如果镜像想要分发使用,就需要放到registry上

dockerfile镜像制作指令文件,由docker build命令,基于此镜像的指令,一层一层构建出镜像来,构建出镜像可能有N层组成,你有几个指令,就有多少层,所以尽量减少指令 的数量,这样才能确保层数少,层数越多,将来影响的性能也越大,所以docker容器在性能上还是有一些缺陷的,联合挂载使得真正的删除不是真正的删除,修改不是真修改,

如何制作docker镜像仓库,已完成私有镜像文件分发

先从制作dockerfile开始在这里插入图片描述
能够通过dockerfile读取的指令自动去build构建出一个镜像,dockerfile无非是一个文本 文件,里面所包含的也无非就是,dockerfile文件如何构建镜像文件的指令,
写好dockerfile文件就可以用docker build命令就可以构建镜像了
在这里插入图片描述
这个dockerfile的格式也非常简单,只有两类内容
1.#注释符
2.非#开头,都是构建指令,每一个指令都要全大写字符,虽然说并不区分字符大小写,但约定俗成,不同的指令拥有不同的参数,这个是需要精心安排的,这些指令的次序至关重要,因为build命令就是按照次序去构建的,所以正常的业务逻辑要通过命令给出次序来反应

第一个指令必须是from,构建镜像不能是凭空构建的,而要基于某个基础镜像来构建的,base image,base image是手工构建的,但是docker hub中,基础镜像来做我们所需要的镜像,

dockerfile第一行必须是from在这里插入图片描述
**如果某一个值多次引用,可以用变量,改的时候一起改,甚至可以启动镜像时传递给镜像,镜像启动完成,变量替换,从而变量能够适用多种场景
环境变量,使用ENV指令,还支持几种bash的修饰符
**
这个变量有值就是有值,没有值就是word,相当于给变量设置默认值
在这里插入图片描述
如果这个变量自身有值用word没有值就没有值
在这里插入图片描述
在这里插入图片描述
基于所谓的dockerfile做一个镜像的时候,通常需要一个所谓的工作目录
.dockerignore 这个文件就是想要忽略的文件,这个文件信息可以使用global通配符
.dockerignore可以放构建上下文的根目录
如果这个文件存在,build命令构建的时候先查这个文件,,从这个文件内容排除当前目录下的指定 文件,把其他文件在打包进去,
在这里插入图片描述FROM 指定出基础镜像
ɝ FROM指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境
ɝ 实践中,基准镜像可以是任何可用镜像文件,默认情况下,
docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件
ɰ 如果找不到指定的镜像文件,docker build会返回一个错误信息
ɝ Syntax
ɰ FROM [:] 不指明标签默认 latest 或
ɰ FROM @容器的id名称就是镜像文件的校验码
l :指定作为base image的名称;
l :base image的标签,为可选项,省略时默认为latest;在这里插入图片描述容器的id名称就是镜像文件的校验码,后面的镜像没有生成ID号所以是none在这里插入图片描述在这里插入图片描述让dockerfile作者提供本人详细信息在这里插入图片描述在这里插入图片描述
指明哪个文件打包放置在构建的目标镜像文件中,必须是从build上下文路径中的文件,不能是其父目录中的文件
因为构建命令会把当前目录当作构建时使用的跟,所以是看不见父目录的
在这里插入图片描述在这里插入图片描述
ɰ <src必须是build上下文中的路径,不能是其父目录中的文件
ɰ 如果<src是目录,则其内部文件或子目录会被递归复制,但<src目录自身不会被复制
ɰ 如果指定了多个<src,或在<src中使用了通配符,则<dest必须是一个目录,且必须以/结尾
ɰ 如果<dest事先不存在,它将会被自动创建,这包括其父目录路径

在dockerfile制作时并不要求镜像文件要存在

类似docker volume的时候挂载点可以不存在,并不要求原来定的基础镜像中一定要有这个目录,因为会自动创建,
目标目录不存在,无论是最底层的目录或者是对于父目录的每一级都会自动创建,但是如果你的源有多个,目标路径必须以斜线结尾,因为需要知道你是哪个目录的,不以斜线结尾就麻烦了

如果<src是目录,则其内部文件或子目录会被递归复制,但<src目录自身不会被复制,是直接复制里面的文件

如果指定了多个<src,或在<src中使用了通配符,则<dest必须是一个目录,无论存在不存在,都必须以/结尾,不存在会自动创建

如果<dest事先不存在,它将会被自动创建,这包括其父目录路径

举个例子,以运行httpd的bbox为例在这里插入图片描述在这里插入图片描述

把这写网页打包到目标镜像文件,放在?data/html
docker文件后缀名是固定的
一定要加斜线/,不加斜线就创建/data/html这个文件了。html不是目录了
在这里插入图片描述在这里插入图片描述
就叫dockerfile,构建docker文件的上下文,就相当于根目录
有三步,每一个指令都会构建一个镜像层的,最终构成的是由三层构成的,所以指令越少越好,每一层 都带一个ID
在这里插入图片描述
使用dockerfile build命令完成构建镜像,可以直接加上tag,所属仓库的标签和镜像文件名在这里插入图片描述
如果不给tag,就是none在这里插入图片描述
打一个标签,先写镜像ID 后写标签在这里插入图片描述
这就是如何把一个文件,打包到一个新镜像里在这里插入图片描述
打包也可以用另外的方式,比如有目录,把文件放到当前目录下,现在bbox下又目录而没有这个文件了,打算把data中的内容,制定到dockerfile所定义的目标镜像中在这里插入图片描述
现在需要把data目录复制到,目标系统的data目录中,
因为当你指定的源是一个目录的时候,会把目录中的文件,递归复制到目录下,但不包含目录本身
在这里插入图片描述
当你去复制目录的时候,不会复制目录本身,但会复制目录下的文件,注意目录层次结构不要出错在这里插入图片描述
复制文件的指令除了copy还有add
add多出一个功能,支持复制tar文件,支持复制url为文件路径
在这里插入图片描述操作准则
ɰ 同COPY指令
ɰ 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为;如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/(下载下来以后改名)

ɰ 如果是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;(tar必须是本地文件系统不能是url)

ɰ 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到;

编辑一个本地url试试

在这里插入图片描述
把这个文件下载扔到repos.d在这里插入图片描述
现在就下载成功了 在这里插入图片描述
可以直接跑起来看看在这里插入图片描述
这就是如何add文件到docker镜像的在这里插入图片描述
workdir工作目录的,这个并不是你的构建工作目录,而是给build,copy和add设定工作目录的
当某些命令执行之前先cd到目录中去,这个目录应该构建下的子目录

在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径

l 另外,WORKDIR也可调用由ENV指定定义的变量
ɰ 例如
WORKDIR /var/log
l WORKDIR $STATEPATH
在这里插入图片描述
镜像启动以后,默认就有一个卷,之前需要用-v指定卷,想要自动拥有一个卷,由docker管理的卷,构建镜像的时候,自动把网页路径关联到主机卷上在这里插入图片描述在这里插入图片描述
VOLUME 直接给挂载路径
或 ɰ VOLUME [""]放在一个中括号中,多个卷用逗号隔开
镜像中指明挂载点,不能确保每个人运行镜像都在这个目录

**

把/data.html当做卷的挂载点**在这里插入图片描述
再次构建在这里插入图片描述
run新构建出的镜像在这里插入图片描述
但是这个文件的内容却映射到在这里插入图片描述在这里插入图片描述在这里插入图片描述
是的这样的镜像起来后直接拥有卷,但是这种是docker管理的卷在这里插入图片描述在这里插入图片描述在这里插入图片描述
expose指定要暴露的端口,不指协议,默认是tcp
在这里插入图片描述在这里插入图片描述
再去构建一个镜像在这里插入图片描述
根据镜像启动容器在这里插入图片描述
**定义了expose但是并没有暴露出去,可以暴露但是并没有真正做到暴露
**在这里插入图片描述
要想暴露,需要-P选项,代表所有expose指定端口都暴露出来在这里插入图片描述
现在就可以看到暴露端口了,镜像中想要暴露的端口,必须要加-P在这里插入图片描述
expose可以根据自己需要来定义在这里插入图片描述在这里插入图片描述
定义环境变量的
Syntax
ENV <key变量名> 空格 变量值(一次定义一个变量)
或 ɰ ENV = 空格 = …(申明多个变量,)
尽量能一条指令完成的就完成,因为一条指令一层,层次多了,性能就下降

第一种格式中,之后的所有内容均会被视作其的组成部分,因此,一次只能设置一个变量;

ɝ 第二种格式可用一次设置多个变量,每个变量为一个"="的键值对,如果中包含空格,可以以反斜线()进行转义,也可通过对加引号进行标识;另外,反斜线也可用于续行;

ɝ 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能

定义好env可以在copy和add,以及commit,run等指令中引用在这里插入图片描述

在这里插入图片描述
再次重新构建在这里插入图片描述
基于这个镜像跑起来,repo文件也在在这里插入图片描述在这里插入图片描述
run表示运行命令的,cmd也表示执行命令,但是又本质的不同,
如果想要目标镜像安装某个程序包或者添加一个用户账号之类的,
启动之后执行完了
应该构建的时候执行,需要用run
镜像启动以后的命令cmd,指定镜像启动以后,默认执行什么程序
在这里插入图片描述在这里插入图片描述RUN
ɝ 用于指定docker build过程中运行的程序,其可以是任何命令
dockerile中的任何一个指令都会在一个新的image文件层上执行,因此,当需要运行多个命令行,建议将其定义在同一个RUN指令时可以减少image文件的层数
run cmd1 &&cmd2 &&cmd3 第一个成功执行第二个,指定命令的格式有两种
ɝ Syntax
ɰ RUN 或 运行多个命令
ɰ RUN ["", “”, “”] 命令有参数

ɝ 第一种格式中,通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop 命令停止容器时,此进程接收不到SIGTERM信号;(dockerfile运行的时候不会运行命令本身,而是以bash作为 解释器来运行 ,等于shell的子命令,可以利用shell命令展开,通配符替换。如果不用shell子命令这些功能都不支持)

ɝ 第二种语法格式中的参数是一个JSON格式的数组,其中为要运行的命令,后面的为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起(不会以shell的子进程来运行),因此常见的shell操作如变量替换以及通配符(?,* 等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。(可以把executable写成shell)

RUN ["/bin/bash", “-c”, “”, “”] 以这个shell作为父进程来运行此程序

希望镜像运行过程中自动添加用户账号在这里插入图片描述

当构建镜像后,就用这个添加用户
在这里插入图片描述
写在不同的行中需要些续航符在这里插入图片描述在这里插入图片描述
基于新的镜像来启动容器在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

转载地址:http://ockgn.baihongyu.com/

你可能感兴趣的文章
FreeSql接入CAP的实践
查看>>
浅析 EF Core 5 中的 DbContextFactory
查看>>
听说容器正在吃掉整个软件世界?
查看>>
真实经历:整整一年了,他是这样从程序员转型做产品经理的
查看>>
netcore一键部署到linux服务器以服务方式后台运行
查看>>
还在犹豫是否迁移.NET5?这几个项目已经上线了!
查看>>
被 C# 的 ThreadStatic 标记的静态变量,都存放在哪里了?
查看>>
ASP.NET Core使用HostingStartup增强启动操作
查看>>
结合控制台程序和K8S的CronJob完成定时任务
查看>>
WPF开发的实用小工具 - 快捷悬浮菜单
查看>>
.Net orm 开源项目 FreeSql 2.0.0
查看>>
IdentityServer4系列 | 简化模式
查看>>
小试YARP
查看>>
如何使用 C# 中的 HashSet
查看>>
api-hook,更轻量的接口测试工具
查看>>
一个情怀引发的生产事故(续)
查看>>
如何在 C# 中使用 RabbitMQ
查看>>
一套标准的ASP.NET Core容器化应用日志收集分析方案
查看>>
如何使用 C# 扩展方法
查看>>
C#如何回到主线程,如何在委托指定线程执行
查看>>