简介
Docker简介
Docker 提供了一个可以运行你的应用程序的封套(envelope),或者说容器。它原本是 dotCloud 启动的一个业余项目,并在前些时候开源了。它吸引了大量的关注和讨论,导致 dotCloud 把它重命名到 Docker Inc。它最初是用 Go 语言编写的,它就相当于是加在 LXC(LinuX Containers,linux 容器)上的管道,允许开发者在更高层次的概念上工作。
Docker 扩展了 Linux 容器(Linux Containers),或着说 LXC,通过一个高层次的 API 为进程单独提供了一个轻量级的虚拟环境。Docker 利用了 LXC, cgroups 和 Linux 自己的内核。和传统的虚拟机不同的是,一个 Docker 容器并不包含一个单独的操作系统,而是基于已有的基础设施中操作系统提供的功能来运行的。
Docker类似虚拟机的概念,但是与虚拟化技术的不同点在于下面几点:
- 虚拟化技术依赖物理CPU和内存,是硬件级别的;而docker构建在操作系统上,利用操作系统的containerization技术,所以docker甚至可以在虚拟机上运行。虚拟化系统一般都是指操作系统镜像,比较复杂,称为“系统”;而docker开源而且轻量,称为“容器”,单个容器适合部署少量应用,比如部署一个redis、一个memcached。
- 传统的虚拟化技术使用快照来保存状态;而docker在保存状态上不仅更为轻便和低成本,而且引入了类似源代码管理机制,将容器的快照历史版本一一记录,切换成本很低。
- 传统的虚拟化技术在构建系统的时候较为复杂,需要大量的人力;而docker可以通过Dockfile来构建整个容器,重启和构建速度很快。更重要的是Dockfile可以手动编写,这样应用程序开发人员可以通过发布Dockfile来指导系统环境和依赖,这样对于持续交付十分有利。
- Dockerfile可以基于已经构建好的容器镜像,创建新容器。Dockerfile可以通过社区分享和下载,有利于该技术的推广。
Docker 会像一个可移植的容器引擎那样工作。它把应用程序及所有程序的依赖环境打包到一个虚拟容器中,这个虚拟容器可以运行在任何一种 Linux 服务器上。这大大地提高了程序运行的灵活性和可移植性,无论需不需要许可、是在公共云还是私密云、是不是裸机环境等等。
Docker也是一个云计算平台,它利用Linux的LXC、AUFU、Go语言、cgroup实现了资源的独立,可以很轻松的实现文件、资源、网络等隔离,其最终的目标是实现类似PaaS平台的应用隔离。
Docker 由下面这些组成:
- Docker服务器守护程序(server daemon),用于管理所有的容器。
- Docker命令行客户端,用于控制服务器守护程序。
- Docker镜像:查找和浏览 docker 容器镜像。
Docker特性
一次封装到处运行,很好的说明了Docker的跨平台和强移植性。
Docker容器与传统虚拟机技术的特性对比
特 性 Docker容器 传统虚拟机 启动速度 秒级 分钟级
硬盘使用 一般为MB 一般为GB 性能 接近原生系统 相对弱于 系统支持量 单机支持上千个容器 一般几十个
Docker容器与传统虚拟机技术的不同之处
Docker容器是在操作系统层面上实现虚拟化,直接复用本机本地的操作系统,因此更加轻量级,性能方面也更加高效。
Docker三个基本概念
Docker 包括三个基本概念
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
理解了这三个概念,就理解了 Docker 的整个生命周期。
Docker 镜像 Docker 镜像就是一个只读的模板。 例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。 镜像可以用来创建 Docker 容器。 Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
Docker 容器 Docker 利用容器来运行应用。 容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。 可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
Docker 仓库
Docker仓库(Repostory)类似于代码的仓库(与svn、git、maven等概念类似)是Docker用来集中存放镜像文件的场所。
根据所存储的镜像是否公开分享,Docker仓库又分为:
- 1.公开仓库
- 2.私有仓库
顾名思义,公开仓库就是公共开放的镜像存储的地方,目前最大的公开仓库是Dokcer Hub (registry.hub.docker.com),存放了大量的镜像可供下载使用,国内的公开仓库有aliyun(acs-public-mirror.oss-cn-hangzhou.aliyuncs.com)。私有仓库是内部使用的私有不对外开放的仓库,用户可以内部自行搭建,内部分享镜像,方便快捷的分享专属环境的镜像文件。
Docker功能特点
虽然Docker提供了很多功能,但这里只列出了一些主要功能,如下所示:
- 轻松快捷的配置
- 提高工作效率
- 应用隔离
- 云集
- 路由网
- 服务
- 安全管理
- 轻松快捷的配置
这是Docker的一个主要功能,可帮助我们轻松快速地配置系统。
可以在更少的时间和精力的情况下部署代码。 由于Docker可以在各种各样的环境中使用,基础架构不再要求与应用程序的环境相关联。
- 提高工作效率
通过放宽技术配置和应用的快速部署。 毫无疑问,它节约了时间提高了生产率。 Docker不仅有助于在孤立环境中执行应用程序,而且还减少了资源。
- 应用隔离
Docker提供用于在隔离环境中运行应用程序的容器。 每个容器独立于另一个容器,并允许执行任何类型的应用程序。
- 云集(Swarm)
它是Docker容器的集群和调度工具。 Swarm使用Docker API作为其前端,这有助于我们使用各种工具来控制它。 它还可以将Docker主机集群控制为一个虚拟主机。 这是一个用于启用可插拔后端的自组织引擎组。
- 路由网
它将可用节点上已发布端口的传入请求路由到活动容器。 即使节点上没有任务正在运行,此功能也可以实现连接。
- 服务
服务是允许指定集群内的容器状态的任务列表。 每个任务表示一个应该运行的容器的一个实例,并且Swarm在节点之间调度它们。
- 安全管理
它允许将保密数据保存到云群(swarm)中,然后选择给予服务访问某些保密数据。
它包括一些重要的命令给引擎,如保密数据检查,保密数据创建等。
Docker架构
Docker遵循客户端 - 服务器架构。 其架构主要分为三个部分。
- 客户端(Client):Docker提供命令行界面(CLI)工具,客户端与Docker守护进程交互。客户端可以构建,运行和停止应用程序。客户端还可以远程与Docker_Host进行交互。
- Docker_Host:它包含容器,映像和Docker守护程序。它提供完整的环境来执行和运行应用程序。
- 注册表(Registry):它是全局映像库。可以访问并使用这些映像在Docker环境中运行应用程序。
如下图所示:
Docker守护进程
这是一个用于监听Docker API请求的进程。 它还管理Docker对象,如:映像,容器,网络等。守护进程还可以与其他守护进程通信以管理Docker服务。
Docker客户端
Docker客户端是许多Docker用户与Docker进行交互的主要方式。当使用docker run这样的命令时,客户端将这些命令发送到docker d,然后将其运行。docker命令使用Docker API。
Docker注册管理
Docker注册表用于存储Docker映像。Docker提供Docker Hub和Docker Cloud,这是任何人都可以使用的公共注册表。Docker配置为默认在Docker Hub上查找映像。
当我们使用docker pull或docker run命令时,从配置的注册表中提取所需的映像。 当使用docker push命令时,映像被推送到配置的注册表中。
Docker安装(Redhat6.5)
一、下载依赖包(使用能联网的节点)
- 依赖包已经下载好就跳过这步
- 使用有网络的节点
1.安装downloadonly插件使用yum下载rpm包
# yum install yum-plugin-downloadonly
使用方法:
yum install --downloadonly(只下载不安装) --downloaddir=rpm包下载的目录 安装的组件名
2.下载docker需要的依赖包
2.1配置Fedora EPEL源
# yum install http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
2.2 添加hop5.repo源
# cd /etc/yum.repos.d
# wget http://www.hop5.in/yum/el6/hop5.repo
2.3下载依赖包
# mkdir /usr/local/docker
# yum install --downloadonly --downloaddir=/usr/local/docker docker-io
这一步会报错找不到对应的rpm包;原因是对应的rpm包的版本号改变了,复制没有下载的rpm包的包名(不带版本号),进入下面的网址:
http://mirrors.aliyun.com/epel/6/x86_64/
找到对应的包名的rpm包,比如这里提示lxc-1.0.8-1.el6.x86_64.rpm包下载失败,在上面的网址中找到lxc-1.0.9-1.el6.x86_64.rpm,复制链接地址,http://mirrors.aliyun.com/epel/6/x86_64/lxc-1.0.9-1.el6.x86_64.rpm
# cd /usr/local/docker
# wget http://mirrors.aliyun.com/epel/6/x86_64/lxc-1.0.9-1.el6.x86_64.rpm
就可以下载对应的包了
2.4下载device-mapper-libs,不下载后面启动docker会报错
# mkdir /usr/local/docker/device-mapper-libs
# yum install --downloadonly --downloaddir=/usr/local/docker/device-mapper-libs device-mapper-libs
2.5 将整个docker目录拷贝到需要安装docker的离线的节点上的/usr/local/src目录下
二、安装docker(离线节点)
1.安装docker
# cd /usr/local/docker
# rpm -ivh lxc-libs-1.0.11-1.el6.x86_64.rpm
# rpm -ivh lua-alt-getopt-0.7.0-1.el6.noarch.rpm
# rpm -ivh lua-filesystem-1.4.2-1.el6.x86_64.rpm
# rpm -ivh lua-lxc-1.0.11-1.el6.x86_64.rpm
# rpm -ivh lxc-1.0.11-1.el6.x86_64.rpm
# rpm -ivh docker-io-1.7.1-2.el6.x86_64.rpm
2.运行docker -d命令报错如下:
docker: relocation error: docker: symbol dm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02 with link time reference
2.1解决如下
# cd /usr/local/docker/device-mapper-libs
# yum -y install device-mapper*
3.再次运行docker -d命令,报错如下:
FATA[0000] Error mounting devices cgroup: mountpoint for devices not found
3.1解决如下:
# vi /etc/fstab
#在结尾添加
none /sys/fs/cgroup cgroup defaults 0 0
#重启
# reboot
4.再次运行docker -d;放到后台运行
# mkidr /usr/local/docker
# cd /usr/local/docker
# nohup docker -d >null &
# tail -f nohup.out
服务方式运行docker:
service docker start
停止
service docker stop
如果没有报错信息,就说明安装成功!
Docker部署tomcat
查找服务器的tomcat信息
# docker search tomcat
载下来官方的镜像Starts最高的那个
由于网络问题可能下载不了,可用通过国内镜像下载,如下:
docker pull registry.docker-cn.com/library/tomcat
查看docker所有的镜像
docker images
在docker中启动tomcat
如下命令会运行Tomcat,并将容器的8080端口暴露到宿主机器的8080端口:
docker run -p 8080:8080 registry.docker-cn.com/library/tomcat
访问tomcat:http://172.16.16.212:8080/
扩展Dockerfile
本文示例中,创建了一个简单的Dockerfile,如下:
FROM tomcat:7-jre7
MAINTAINER "Craig Trim <craigtrim@gmail.com>"
用如下命令构建镜像:
$ sudo docker build -t craig/tomcat .
演进方向
Docker已经推出了5年,在这5年中它极大的改变了互联网产品的架构,推进了新的产品开发、测试和运维方法。但是它自身也在激烈变化中。特别是最近2年随着Docker开源项目的不断演化,Docker内部结构发生了翻天覆地的变化。作为一个容器平台的使用者,可以不用关注具体的Docker演进细则,但是必须明白Docker的衍化会对自己的PaaS平台带来什么样的影响(如果您对Docker技术细节不关注,你可以直接看第2章和最后两章)。本文材料来自于Docker社区,对Docker最近几年的变化趋势做出了总结。同时在结尾处给出了基于k8s PaaS平台在底层容器上选型建议。
Docker这几年的架构演进方向:
1、原有引擎功能下沉入containerd,containerd向着独立于Docker 作为通用容器运行时工具方向演进
2、swarm功能整合入引擎,swarmkit模块不断弱化,最终将被引擎吸收
3、引擎内部功能不断解藕出新模块,同时新功能不断加入Docker 引擎。
一言以蔽之:containerd核心化,引擎集群化。
背景
Docker公司在集群管理服务编排工具竞争上落败
Docker公司在2015年Docker 1.9推出了自己的集群管理服务编排工具swarm,刚开始swarm作为一个独立的工具,在Docker 引擎之外。但是从Docker 1.12开始Docker公司将swarm整合入了Docker引擎。至此Docker swarm作为一个完整的服务编排工具和谷歌主导、红帽支持的kubernetes社区直接冲突。于此同时Docker公司在2015开启了自己的商业化之路,开源社区为了避免Docker公司商业化过程中将Docker沦为绑架社区的工具,所以顺势推出了多个Docker替代方案例如rkt。kubernetes社区推出了CRI-O标准,只要是遵从此标准的容器运行时都可以被K8s支持。一时间Docker大有被主流社区抛弃之势!经过2年和K8s的竞争时间来到2017年,Docker swarm已经在事实上彻底落败,Kubernetes社区已经成为开源项目中热度最高的项目。为了应对如此多的不利因素,Docker公司在2017年将自己主导的containerd捐献给CNCF基金会(k8s是旗下的子项目);并且将更多的Docker引擎的功能下沉到Containerd中。借此避免自己在开源社区中被边缘化。
容器世界的标准化不断推进
Docker公司在2013念推出Docker后,极大的颠覆了这个行业,也推进了业务容器化过程。2015 Docker公司主导之下社区推出了容器的第一个行业标准OCI标准(开放容器协议)。彼时Docker公司推出了第一个OCI标准的容器运行时runc。runc作为第一个oci标准运行时(runtime),只是一个参考实现,仅仅承担容器与主机之间的交互。容器运行状态检查、监控,容器生命期管理,io管理、信号传递等一些列容器运行必不可少的功能却“无处安放”。所以Docker公司将Containerd定位为一个生产环境下的OCI 标准运行时。它承担了runc所缺少的大部分容器运行必要功能:生命期管理,io管理,信号管理。在2017年的时候OCI v1标准发布,Docker公司将Docker镜像格式捐献给了OCI协议。所以在2017年发布的Containerd1.0中存储管理这些原来由引擎承担的功能也进入了Containerd(网络管理功能,在https://containerd.io路线图中被列为roadmap,但是在2016年12月份Containerd的主要维护者投票中,网络功能不被列入containerd的功能范畴 而继续交给上层完成,在github containerd的readme中2017 1月12日正式将网络部分功能从containerd 维护范畴中删除**)。
Containerd
Containerd在Docker 1.11中才正式出现,刚开始时0.x版本;2017年才推出了1.x标准。如上文所说,Container d作为一个生产环境可用的Oci 实现,它利用了OCI 运行时和镜像格式.下图展现了Containerd对自己在社区中地位作出了诠释
可以看到Containerd作为PaaS工具的通用容器运行时适配层,它利用已有的oci运行时(Containerd使用runc作为运行时,在windows上则是hcsshim),屏蔽底层操作系统的差异;为Paas提供通用的容器支撑。从这个图可以看到Containerd计划支持所有现有应用广泛的Paas平台工具。现在可以确认的是AWS ECS,k8s,Docker上使用containerd。Mesos和cloud foundry今天(2018年9月)尚未确定。
Containerd 1.x的架构图
从此架构图可以清楚的看到Containerd对上提供grpc接口方式的api,而Metric api是度量功能使用的。所有的编排工具容器适配层都可以使用grpc api作为containerd的客户端,使用containerd操作容器。
Distribution用于容器镜像的pull和push动作(这部分出现在Containerd中完全是因为oci v1标准推出Docker公司将自己镜像格式贡献了出去,所以containerd理所当然需要对镜像进行管理了)。Bundle(在docker的语景里是容器运行的目录集)子系统用于容器存储管理它的作用就是原来的graphdriver,它提供将容器镜像拆解成容器运行时刻需要的Bundle。Runtime子系统用于容器执行和监控,就是它直接操作runtime,传递和接收信号(signal),中转fifo,记录日志。Content、Metadata和Snapshots是存储管理组建,Excutor和Supervisor是执行体组建。整个系统通过Event事件驱动。
根据github上containerd的介绍containerd项目工作内容集中在如下几个领域上:
- 执行:容器创建、运行、停止、暂停、恢复,exec,信号传递、和删除。
- cow 文件系统支持:在overlay,aufs和其他cow文件系统上内置了存储功能
- 度量系统
- 发布:容器镜像的pull和push,镜像的管理和获取
下面内容不作为containerd项目的工作范畴:
- 网络:网络的创建和管理由高层来完成
- build:镜像的构建
- volumes:volume管理:mounts,bind等针对volume的功能应该有高层来完成
- logging
此处需要说明一下网络曾经作为containerd社区争论的焦点。但是在16年年底的社区维护者投票中多数人支持网络不留在containerd中,因为按照大多数维护者的认识网络过于复杂,而且网络设置常常需要跨越节点。这部分功能由containerd的客户端(Docker Engine 或K8s)做更合适。
这里顺便介绍一下Containerd版本兼容规则:Containerd同一个大版本下的连续两个小版本是兼容的。例Containerd1.1.0和1.2.0却是兼容的,1.0.0和1.2.0却不保证兼容。
Docker的演进
可以看到在Docker1.11之前,没有containerd模块,由libcontainer直接操作主机os接口。
下图介绍了在Docker 1.11--Docker 17.10之间的docker架构
从图3-2看到这一时期的Docker架构变化就是引入了Containerd和runc,由Containerd完成容器生命期管理。
下图列出了Docker 17.11(Docker 17.12为真正的stable版)开始的架构
需要注意的一点图网络部分并不在containerd中,仍然在docker engine里。
Docker架构演进大事记
- Docker 1.9 推出swarm,作为独立工具,用于集群管理和服务编排
- Docker 1.11 推出containerd和runc。
- Docker 1.12 swarm进入引擎
- Docker 17.06 引擎社区更名为moby,docke r社区版本更名为docker-ce(类似于红帽的fedora和rhel)
- Docker 17.12 Docker正式引入containerd 1.0
- Docker 18.06 正式在engine里加入了buildkit,在设置一个环境变量后可以使用buildkit完成docker build过程。
Docker 18.06.1正式将containerd 1.1引入docker。
k8s社区对Docker 17.03之后版本态度
在Docker 17.03后Docker因为moby和containerd等原因版本变动比较大,我们可以看到k8s r11发布后的2018年9月仍然没有将Docker 17.03以后(不含)版本作为k8s的兼容Docker版本。从社区的讨论来看社区已经推荐将containerd直接对接cri,完成k8s的集成。见https://github.com/kubernetes/kubernetes/issues/42926,其中cpuguy83(此人为moby社区的主要维护者)推荐直接使用containerd替代docker 17.03以后的版本对接k8s。本来docker在k8s社区中的兼容性测试由k8s sig-node 工作组完成,但是通过k8s讨论可以看到sig-node并没有计划做docker 17.03以后docker的兼容性测试。
最新消息是2018年9月27日k8s出r12 rc的时候,kubeadm里已经加入了对docker18.06的支持,且完成了ci测试。12 rc 文档里将docker17.12,18.03,18.06之后列入支持表。但在k8s中 sig-node工作组负责底层容器接口,docker在k8s版本的兼容性测试本应由此工作组完成,但是sig-node对于docker 17.03版本以后docker版本的态度依然冷淡,一直未列入明确的工作计划中。sig-node工作组两位主席是谷歌和红帽的,它们对于cri更感兴趣。在2018年5月,sig-node和containerd社区共同完成了cri-containerd合入containerd1.1的工作,并发布了containerd 整合到kubenetes的GA。完成此部分工作后,k8s驱动containerd的结构更简单明确。下图介绍了docker,containerd在k8s上的架构图:
从上面两幅图我们可以看到containerd1.1在k8s上拥有更简单的结构图,驱动更为简单。而且根据k8s社区的测试,直接使用containerd替代docker可以获得容器启动时间、内存消耗和cpu消耗减少的红利。上述结论来自于:
https://kubernetes.io/blog/2018/05/24/kubernetes-containerd-integration-goes-ga/
docker-manager是老的kubelet介入docker的方式。 cri从k8s 1.6开始正式进入k8s cri直接介入containerd是从18年4月,containerd1.1开始
PaaS平台选型建议
如果你正在对基于k8s的PaaS平台进行生产环境选型,我建议你使用Docker17.03,因为它成熟稳定且k8s r9,r10和r11做过稳定、兼容性测试。如果你喜欢尝试新事物,我建议你跳过Docker17.03之后,直接在kublet上使用containerd1.1。如果你喜欢docker新版本,那么你可以尝试docker18.06,因为Docker17.12是Docker变化最剧烈的一个版本稳定性不好说,且kuberadm中r12 rc里加入了对18.06的支持所以用最新的好了。而且更关键的一点docker 18.06.1使用containerd 1.1,它支持一个特性:上层容器控制平台的namespace隔离,简单点说就是docker和k8s均可以在同一个节点上操作同一个containerd,且相互隔离不可见。如此可以预留选择传统k8s+docker组合时刻,保留将来切换成k8s+containerd组合的可能性,进而为自己的框架保持演进的灵活性。
附录
FAQ
替换Redhat的yum源
yum install pam-devel
#This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. Setting up Install Process Nothing to do
使redhat 默认自带的 yum 源需要注册,才能更新。因此,需要替换掉redhat的yum源。
1.检查是否安装yum包
查看RHEL是否安装了yum,若是安装了,那么又有哪些yum包:
[root@localhost ~]# rpm -qa |grep yum
yum-metadata-parser-1.0-8.fc6
yum-3.0.1-5.el5
yum-rhn-plugin-0.4.3-1.el5
yum-updatesd-3.0.1-5.el5
2 删除redhat自带的yum包
卸载上面显示的所有yum包:
[root@localhost ~]# rpm -qa|grep yum|xargs rpm -e --nodeps(不检查依赖,直接删除rpm包)
再用
[root@localhost ~]# rpm -qa |grep yum
[root@localhost ~]#
查看,无信息显示表示已经卸载完成。
3.下载新的yum包。使用Centos6.5(64位)的yum包
wget http://mirrors.163.com/centos/6/os/x86_64/Packages/python-urlgrabber-3.9.1-11.el6.noarch.rpm
wget http://mirrors.163.com/centos/6/os/x86_64/Packages/yum-metadata-parser-1.1.2-16.el6.x86_64.rpm
wget http://mirrors.163.com/centos/6/os/x86_64/Packages/yum-3.2.29-81.el6.centos.noarch.rpm
wget http://mirrors.163.com/centos/6/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.30-41.el6.noarch.rpm
安装yum软件包
注意:单个的安装包可能会依赖其它包(例如yum和yum-fastestmirror会相互依赖),所以我们可以把所有这些包放在一起,用一行命令将它们同时安装即可:
# rpm -ivh yum-metadata-parser-1.1.2-16.el6.x86_64.rpm yum-3.2.29-81.el6.centos.noarch.rpm yum-plugin-fastestmirror-1.1.30-41.el6.noarch.rpm
4.更换yum源。使用163的源
# cd /etc/yum.repos.d/
# wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
# vi CentOS6-Base-163.repo
编辑文件,把文件里面的$releasever全部替换为版本号,即6.5 最后保存!
可以使用命令 :%s/$releasever/6/g
5.清理yum缓存
yum clean all #清除原有缓存
yum makecache #重建缓存,以提高搜索安装软件的速度
6.测试
sudo yum seach git
7.更新系统
sudo yum update
注:这一步可能需要很久,如果不愿意等,可以先不进行。
linux配置域名解析服务器
https://jingyan.baidu.com/article/6525d4b17a6648ac7d2e94f8.html