Docker学习之基本概念
二、概念
1.镜像
2.容器
3.仓库
0. 找到一个科普文,很形象,易理解,摘自
https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484574&idx=1&sn=9ce4589efc377ba0f93e7513969164d9&chksm=ebd7459fdca0cc893f64895f536277bd4a024721b022382875197e87cc727495e4dd458ea337&token=221324962&lang=zh_CN&scene=21#wechat_redirect
小笔记:
①容器技术docker的思考方式是,将环境一起打包镜像,避免部署时的环境问题。
在什么情况下我们需要自己构建镜像那?
(1)当我们找不到现有的镜像,比如自己开发的应用程序
(2)需要在镜像中加入特定的功能
docker构建镜像(制作镜像)有两种方式:docker commit命令与Dockerfile构建文件 参考https://www.cnblogs.com/it-peng/p/11388240.html
- docker提供了很多基础镜像,你可以在基础镜像的基础上commit新东西,生成新镜像提交上去。同时,docker使用了镜像分层的技术,新的commit会产生新的层,可以复用一部分老的层。这样一来制作新镜像的速度还是挺快的。
- docker还可以使用dockfile。Dockerfile是由一系列命令和参数构成的脚本。简单来说:Dockerfile是镜像的源码。dockerfile记录了镜像的制作步骤,即描述一个镜像是如何构建出来的。
使用docker build命令就可以根据dockfile文件构建镜像,docker会按照里面的步骤一步步把镜像构建好。在真正的项目中,是把dockerfile也放在项目的源码中,一起提交。这样只要有源码,就知道怎么打镜像了。而且从dockerfile中还可以知道项目的依赖环境和运行方式。所以,dockerfile其实是提供了项目运行起来的环境信息。
最佳实践:
一般来说,本地开发可以在IDE中进行,但是不输到集成测试环境中的时候,一般就根据dockerfile打出镜像部署。这样很多环境问题在测试环境就能暴露出来。厕所见测试环境通过之后,生产环境一般直接用打好的镜像直接部署。这里其实不用担心镜像会比较大的问题, 其实在网络好的情况下,下载一个镜像一般来说比重新打一个镜像更快,所以最终部署都是基于镜像去部署,不会重新打镜像了。
所以整个项目的开发流程大概就是:本地调试OK,在测试环境打镜像测试,没问题后推送到仓库,再不输到生产环境。
二、基本概念
摘自:https://zhuanlan.zhihu.com/p/39171987和上面的科普文
Docker的三个基本概念
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
简单来说,
镜像、容器、仓库的概念可以类比代码、进程、github
镜像有点像代码,容器有点像进程。代码是存放在硬盘上的东西,而把代码运行起来,就回行程一个进程,进程才是跑起来的程序。
所以镜像是存在硬盘上的东西,镜像运行起来,就形成了一个容器,容器才是真正跑起来的程序。只不过在docker中,我们可以进入容器,做一些操作,然后再把容器中的改动提交形成一个新的镜像。
(
A container image is a tar file containing tar files. Each of the tar file is a layer. Once all tar files have been extract into the same location then you have the container's filesystem.
This can be explored via Docker. Pull the layers onto your local system.
)
仓库呢?写好的代码会提交到githun上面进行保存和管理,方便在其他地方也能下载代码。镜像仓库也是类似,制作好的镜像,就把它放到镜像仓库,方便其他人直接用镜像部署。
详细一点,
镜像(Image)
操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。
现在重新理解一下我们使用一个linux系统的过程。我们开机的时候,linux内核会先启动,然后挂载root文件系统作为用户空间;而Docker镜像就相当于是一个root文件系统,每开一个就有了一个独立的用户空间。
Docker设计时,就充分利用Union FS的技术,将其设计为分层存储的架构。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
关于镜像再详细一点可以参考https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484674&idx=1&sn=e3ea5efe00fde6ebd3c73d5bf2155813&chksm=ebd74403dca0cd15bb3f5e288f28ce2058f8031ee18c2912cec05d886552c24e6e8d8e5ff1ce&token=1676899695&lang=zh_CN###rd
容器(Container)
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的类,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。
前面讲过镜像使用的是分层存储,容器也是如此。
按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
所谓“绑定宿主目录”,就是在run一个container的时候使用-v命令把宿主机的存储目录映射进container。我们可以这样理解,image是分层存储的,我们每做一次修改就会在原本的Image存储层上多搭一层,记录这个更改;而新搭的这层是静态、且可以持久化存储的。Container也是相同额存储架构,但是每次修改新搭的一层是动态的,而且并不是持久化存储的;当容器被remove,或者重启计算机(内存断电)之后,container没了,相应的这些容器存储层也没了。因此要尽量保持容器存储层无状态化,所有的contain里产生的数据(比如container里的程序的运行结果)都要通过挂载宿主目录直接写进宿主硬盘里。
仓库(Repository)
我们可以把构建后的镜像上传到服务器,从而可以在任何地方使用到这个镜像。
一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。
如果不给出标签,将以latest作为默认标签。
最常使用的Registry公开服务是官方的Docker Hub ,这也是默认的Registry,并拥有大量的高质量的官方镜像,网址为:http://hub.docker.com/ 。
Registry和Repository关系:
Repository是镜像仓库,用于存储具体的docker镜像,起到的是仓库存储的租用。比如Tomcat下面有很多版本的镜像,他们共同组成了Tomcat的Repository,各个版本通过标签(Tag)来区分,不给标签就默认以latest为默认标签。
Registry就是docker的注册服务器,作用是管理镜像仓库,起到的是服务器的作用,比如官方的Docker Hub,它是开源的。
Registry上有很多的Repository,Redis、Tomcat等等的Repository组成了Registry