可以把我盖好的房子复制一份,做成“镜像”,放在我的背包里。
。想搬家时,等我到了另一片空地,就用这个“镜像”,复制一套房子,摆在那边,拎包入住,而不用再次搬石头、砍木头、画图纸、盖房子
。
那个放在包里的“镜像”,就是Docker镜像
我可以有多个镜像呀
!我的背包,就是Docker仓库
。
负责对Docker镜像进行管理的,是Docker Registry服务(类似仓库管理员)。Docker Registry服务对镜像的管理是非常严格的。最常使用的Registry公开服务,是官方的Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。
。我在空地上,用神功造好的房子,就是一个Docker容器
公司往往是通过为每个开发人员提供一台或者多台虚拟机【虚拟机可以模拟出运行需要的硬件,相当于一个完整的OS,然后在这个系统上安装和运行各种软件】来充当开发测试环境
。开发测试环境一般负载较低,大量的系统资源都被浪费在虚拟机本身的进程上了。Docker容器没有任何CPU和内存上的额外开销,很适合用来提供公司内部的开发测试环境。而且由于docker镜像可以很方便的在公司内部分享,这对开发环境的规范性也有极大的帮助
。
传统虚拟机占内存等资源很多
,启动运行起来很慢,所以Docker应运而生容器虚拟化的是操作系统而不是硬件【与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动 。】,容器之间是共享同一套操作系统资源的【Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例。或者换句话说,容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。】
。
虚拟机 (VM) 是一个物理硬件层抽象
,用于将一台服务器变成多台服务器。 管理程序允许多个 VM 在一台机器上运行。每个 VM 都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此 占用大量空间 。而且 VM 启动也十分缓慢
。】一台主机可以同时运行几千个Docker容器
)。此外,它占的空间很小,虚拟机一般要几GB到几十GB的空间,而容器只需要MB级甚至KB级。容器编排器可以根据需求和负载向上和向下扩展软件应用程序中的各个组件
。这可以节省成本,因为组件仅在需要时运行。扩展还提高了可靠性,因为 容器编排器可以为应用程序的高需求部分分配足够的资源
。要运行应用程序,容器会加载容器镜像。容器镜像是一个静态文件,其中包含在 IT 基础架构上运行进程的可执行代码
。有针对不同用例的容器镜像,例如数据库、Web 服务器、操作系统等。容器镜像存储库是容器镜像的公共访问点,这使得它们可供开发人员使用,他们可以使用这些镜像加载容器。如果你想让应用程序使用容器,你可以确保你使用的任何 OCI 映像都可以在你的基础架构上运行,即使你的基础架构发生了变化用Docker后:打包镜像发布测试,都是一键运行
。 Docker比VM快(因为VM要虚拟化出运行需要的硬件,然后在这个硬件上去跑服务),所以容器性能开销极低。
把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样
。】多个 Docker 容器可以共享
这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的
,并共享一些公共文件
。这样就能尽量降低磁盘用量,并能更快地下载镜像。容器化软件 Docker 容器基于开放式标准,能够在所有主流 Linux 版本、Microsoft Windows 以及包括 VM、裸机服务器和云在内的任何基础设施上运行
。在任何环境中都能够始终如一地运行【Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码在我机器上没问题啊” 这类问题;】。有没有想起来咱们的Java的跨平台特性呀。容器赋予了软件独立性,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。】迁移方便
可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间
。】虚拟机与Docker容器两者可以和谐共存。虚拟机更擅长于彻底隔离整个运行环境。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而 Docker 通常用于隔离不同的应用 ,例如前端,后端以及数据库。
是一种轻量级的“虚拟机”
。Docker也是一个开源的应用容器引擎【Docker本身并不是容器,它是工具,是开源的应用容器引擎
】。【Docker:提供了标准的应用打包方式,是一个容器化的平台
】
基于 Linux 内核 提供的 CGroup 功能和 namespace 来实现的,以及 AUFS 类的 UnionFS 等技术
,使用沙箱机制对进程进行封装隔离,属于操作系统层面的虚拟化技术
。 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器
】不同的镜像放在不同的容器中
由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器
。【每个容器间是相互隔离
的,每个容器都有自己的一个专属于自己的文件系统】Docker 赋予应用的隔离性不仅限于进程或者容器之间彼此隔离,还独立于底层的基础设施
。Docker 默认提供最强的隔离,因此 应用出现问题,也只是单个容器的问题,而不会波及到整台机器
。为 Linux 内核容器功能的一个用户空间接口
。它将应用软件系统打包成一个软件容器(Container),内含应用软件本身的代码,以及所需要的操作系统核心和库。通过统一的名字空间和共用 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。
LXC 技术主要是借助 Linux 内核中提供的 CGroup 功能和 namespace 来实现的,通过 LXC 可以为软件提供一个独立的操作系统运行环境。Docker 运行过程也就是去仓库把镜像拉到本地,然后用一条命令把镜像运行起来变成容器
。所以,我们也常常将 Docker 称为码头工人或码头装卸工,这和 Docker 的中文翻译搬运工人如出一辙。stopped【created、Exited】、running【Up】、Paused、deleted【看不见,删了就没了,看不见这个状态名字】
我想安装一个xxx,那么我从client发一个docker pull xxx给docker daemon,docker daemon接收到docker pull xxx之后,先在Docker_Host本机内寻找有没有xxx镜像,有,直接docker run xxx实例化出容器并运行。没有就去远程仓库拉来镜像然后实例化出容器
Docker的守护进程运行在主机上
,客户端通过Socket访问Docker,当DockerServer接收到Docker-Client的指令就会执行这个命令
如果要把容器作为开发机使用,需要解决的是远程登录容器和容器内进程管理问题
。Docker可以实现,项目的代码(的jar包或者war包)带上项目运行所需要的环境,一起打个包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,这个打出来的比较齐全的包叫做镜像
【容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。】镜像本质上是一个分层的、静态文件、构建完之后只读的文件系统。镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。所有的应用,直接打包docker镜像,就可以直接跑起来!
)docker镜像就相当于一个模板(咱们Java中的全局唯一的Class模板),可以通过这个镜像模板来创建容器服务(或者说通过这个镜像可以创建多个容器),最终服务运行或者说项目运行就是在容器中的。本质上那些按照镜像创建出来的多个容器都是通过镜像来进行运行的。
就相当于是一个root文件系统【除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。】
【操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统
。】。比如官方镜像ubuntu:16.04就包含了完整的一套
Ubuntu16.04最小系统的root文件系统。
UnionFS (联合文件系统)
: Union文件系统( UnionFS)是一种分层、 轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加 ,同时可以将不同目录挂载到同一个虚拟文件系统下
(unite several directories into a single virtual filesystem)。Union 文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。【分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像
】镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层
。 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。起始于一个基础镜像层
,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层
。只读
的,当容器启动时, 一个新的可写层
被加载到镜像的顶部!。这一层就是我们通常说的容器层
,容器之下的都叫镜像层!我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境
。】容器是一个轻量级、可移植的计算环境,具有独立运行所需的所有必要文件
。容器化是使应用程序可作为容器运行的过程
。容器就是镜像运行起来提供服务器的东西
容器进程运行于属于自己的独立的 命名空间
。镜像使用的是分层存储,容器也是分层存储。【容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。】镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等
。】。其实就可以把容器看作是一个简易的linux系统容器化软件适用于基于 Linux 和 Windows 的应用,在任何环境中都能够始终如一地运行
但是存在一个问题
,就是咱们的数据此时如果都在容器中,如果咱们删除容器数据就跟着一块没了。所以需要数据持久化到本地,所以容器之间可以有一个数据共享的技术可以将Docker容器中产生的数据同步到本地,这就是卷技术
,来实现目录的挂载,将我们容器内的目录挂载到Linux上面
数据卷就是宿主机中的一个目录或文件,没个啥,只是这个得跟容器的目录或者文件来通过-v参数进行映射,来实现容器内数据的持久化和同步操作,容器之间可以数据共享
)如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务
。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。所以说:镜像仓库是 Docker 用来集中存放镜像文件的地方类似于我们之前常用的代码仓库【通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。】
。端口映射【中间通过docker-proxy完成,你可以netstat -tulpn】
。相当于把宿主机开放的映射端口XXX当一个中介来顶替8080。原来http://localhost:8080就变成了http://localhost:XXX
并且我们只要安装了docker,就会有一个网卡
一个Docker 容器一般会分配一个独立的Network Namespace
。一个Network Namespace 提供了一份独立的网络环境,包括网卡,路由,iptable 规则等都与其他Network Namespace 隔离
。相当于VMware 中的桥接模式,与宿主机在同一个网络中,但是没有独立IP地址
。如果启动容器的时候使用host 模式,那么这个容器将不会获得一个独立的Network Namespace ,而是和宿主机共用一个Network Namespace
。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口.此时容器不再拥有隔离的、独立的网络栈。不拥有所有端口资源一个Docker 容器一般会分配一个独立的Network Namespace
。一个Network Namespace 提供了一份独立的网络环境,包括网卡,路由,iptable 规则等都与其他Network Namespace 隔离
。这个container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享
。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围等 。可以在一定程度上节省网络资源,容器内部依然不会拥有所有端口。使用none 模式,docker 容器有自己的network Namespace ,但是并不为Docker 容器进行任何网络配置。也就是说,这个Docker 容器没有网卡,ip, 路由等信息
。这种网络模式下,容器只有lo 回环网络,没有其他网卡。该容器将完全独立于网络,用户可以根据需要为容器添加网卡。此模式拥有所有端口。(none网络模式配置网络)特殊情况下才会用到,一般不用
容器使用独立network Namespace,并连接到docker0虚拟网卡。通过docker0网桥以及iptables nat表配置与宿主机通信,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上
。当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上
。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备
。
使用 docker run -p 时,docker实际是在iptables做了DNAT规则,实现端口转发功能
。可以使用iptables -t nat -vnL 查看。使用“--link”以及自定义网络
来解决docker0的缺点,但是–link用起来不方便,所以用自定义网络,自定义的网络docker都已经帮我们维护好了对应的关系,很方便Docker 是管理容器的最流行的工具,Docker创造了一个很好用的工具来处理容器也叫 Docker【Docker 可以轻松地构建容器镜像,从 Docker Hub 中拉取镜像,创建、启动和管理容器。实际上,当你用 Docker 运行一个容器时实际上是通过 Docker 守护程序、containerd 和 runc 来运行它。】
docker version //显示docker的版本信息,安装好docker,用docker version查看
docker info //显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help
docker images //查询所有本机的主机上的镜像
REPOSITORY:镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像的id
CREATED:镜像的创建时间
SIZE:镜像的大小
一个Docker镜像,咱们是通过run命令将镜像变成一个容器
】
进入正在运行的容器:docker exec [-it] 容器id 命令。eg:docker exec -it 07abshcbcns /bin/bash
镜像是一层一层的,脚本是一个个的命令,每个命令都是一层
)FROM #基础镜镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建时需要运行的命令
ADD #步骤: tomcat镜像,这个tomcat压缩包! 添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOST #保留端口配置
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile 这个时候就会运行ONBUILD 的指令。触发指令。
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量!
每一个内置命令运行时都会产生一个临时容器,这个临时容器是可以被复用的【构建镜像1的过程中由于会执行dockerfile的内置命令产生了ABC三个临时容器,要是别人构建自己的镜像时也会用到AB临时容器,就会显示Using cache...,那不就方便的很了嘛】
,复用的原因就是Docker的镜像分层,内置命令执行一步就相当于汉堡包加上一层。官方文档:https://docs.docker.com/compose/compose-file/
一键启动整个项目
(编排、打包多个/微服务环境)用来批量容器编排。轻松管理容器
**(定义运行多个容器)Docker Compose安装使用步骤
单机多容器部署工具,通过yml文件定义多容器部署规则
】用来定义整个服务(所需要的环境),需要的环境
。(以前都是单个docker run启动容器,但是有了docker-compose之后,通过docker-compose编写yaml配置文件、可以一键启动或者停止所有服务
)version: "3.9" # optional since v1.27.0
services:
web: #服务1
images: #本服务下载镜像用的(images镜像)是
build: .#本服务用的,build生成的命令
restart:always
environment: #环境配置,里面是键值对
depends_on:
- ppp #代表依赖顺序,就比如说,咱们web项目是不是依赖数据库呀,那这里就给咱们web服务依赖一个db,表示得先启动db才能正确或者成功启动咱们的web项目
ports: #暴露的端口8000,对应的是咱们容器内的端口5000
- "8000:5000"
volumes: #挂载的数据卷到哪里
- .:/code
- logvolume01:/var/log
links: #连接到Redis服务,所以docker启动时会根据配置文件先启动redis服务再启动web服务
- redis
redis: #服务2
image: redis
xxx1: #服务3
...
xxx2: #服务4
...
...
volumes: #挂载,用来容器间数据共享和持久化的
logvolume01: {} #全局配置
networks:
configs:
如果想要将Docker应用于具体的业务实现,是存在困难的——编排、管理和调度等各个方面,都不容易。于是,人们迫切需要一套管理系统,对Docker及容器进行更高级更灵活的管理。就在这个时候,K8S出现了。
。
Docker、Podman 的目标不是容器的编排,编排可以使用更加专业的 Kubernetes、OpenShift、Rancher 等
Deployment部署脚本文件各个参数解析
:https://blog.csdn.net/hhf799954772/article/details/121425425】kubectl是kubenetes命令行工具,提供指令,跟docker中的各个命令开始最前面的那个docker一样,带头大哥或者说开头大哥
基于容器的集群管理平台
,它的全称,是kubernetes。一个K8S系统,通常称为一个K8S集群(Cluster)
。
涉及到的这些容器,随时可以创建,也可以随时销毁。还能够在不停机的情况下,随意变大,随意变小,随意变强,随意变弱,在性能和功耗之间动态平衡。5G时代,核心网采用微服务架构,也是和容器完美搭配——单体式架构(Monolithic)变成微服务架构(Microservices),相当于一个全能型变成N个专能型。每个专能型,分配给一个隔离的容器,赋予了最大程度的灵活。
。Docker将原有单一架构的 Docker Engine 拆分成多个模块,其中 Docker daemon 部分捐赠给 CNCF【作为 CNCF 的托管项目,containerd 必须符合 CRI 标准】,containerd 形成
kubelet将弃用 Docker 支持,并将在未来的版本中完全移除
。但由于 Docker 几乎已经成为容器技术的代名词,而且 K8s 已经使用 Docker 多年,该公告在传播时很快“变味了”,“kubelet 将弃用 Docker 支持
”被简化为更吸人眼球的东西 “K8s 将弃用”Docker”
。
其实只是“弃用 dockershim ”,也就是dockershim搬出kubelet,并不是“弃用 Docker”的软件产品。
在 Kubernetes 包括一个名为 dockershim 的组件,使它能够支持 Docker
。但 Docker 由于比 Kubernetes 更早,没有实现 CRI,所以这就是 dockershim 存在的原因,dockershim 支持将 Docker 被硬编码到 Kubernetes 中
。随着容器化成为行业标准,Kubernetes 项目增加了对额外运行时的支持,比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器。因此 dockershim 成为了 Kubernetes 项目中的一个异类,对 Docker 和 dockershim 的依赖已经渗透到云原生计算基金会(CNCF)生态系统中的各种工具和项目中,导致代码脆弱。2022 年 4 月 dockershim 将会从 Kubernetes 1.24 中完全移除。今后 Kubernetes 将取消对 Docker 的直接支持,而倾向于只使用实现其容器运行时接口的容器运行时,这可能意味着使用 containerd 或 CRI-O。这并不意味着 Kubernetes 将不能运行 Docker 格式的容器。containerd 和 CRI-O 都可以运行 Docker 格式(实际上是 OCI 格式)的镜像,它们只是无需使用 docker 命令或 Docker 守护程序
。如果K8s直接使用containerd来操作容器,那么它就是一个独立于Docker的工作环境,两者都无法访问对方管理的容器和镜像
。换句话说,使用docker ps命令将不会看到K8s中运行的容器。这对一些人来说可能需要花一点时间来适应并使用新工具crictl,但用于查看容器和镜像的子命令仍然是相同的,例如ps,images等,不难适应(如果你一直在用kubectl管理K8s,这个没有影响)。Docker 仍然可以以其他形式与 K8s 共存
。
由于容器镜像格式已经标准化(OCI规范,Open Container Initiative),Docker镜像在K8s中仍然可以正常使用,不需要改变原有的开发测试和CI/CD流程
。我们仍然可以拉取 Docker Hub,或者编写一个 Dockerfile 来打包应用程序。官方文档:https://docs.docker.com/get-docker/
官方手册:https://docs.docker.com/engine/
构建一个自己的centos;(创建一个tomcat镜像https://www.bilibili.com/video/BV1og4y1q7M4?p=30&spm_id_from=pageDriver)
https://javaguide.cn/tools/docker/docker-in-action.html
云原生技术社区
Tony老师
K8S中文社区
Java基基老师的Docker容器部署相关文章
码农翻身老师