虚拟化(virtualization)技术是一个通用的概念,在不同领域有不同的理解。计算机领域一般是指计算虚拟化,或通常说的服务器虚拟化。维基百科的定义是:“在计算机技术中,虚拟化是一种资源管理技术”,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用比原本的组态更好的方式来应用这些资源。”
从大类上分,虚拟化技术可分为基于硬件的虚拟化和基于软件的虚拟化。其中,真正意义上的基于硬件的虚拟化技术不多见,这里仅列出基于软件的虚拟化。
基于软件的虚拟化从对象所在层次可以分为应用虚拟化和平台虚拟化。应用虚拟化指的是一些模拟设备或诸如Wine这样的软件,平台虚拟化又可分为如下几类:
- 完全虚拟化:虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户操作系统无须进行修改。例如VMware Workstation、VirtualBox等。
- 硬件辅助虚拟化:利用硬件(主要是CPU)辅助支持处理敏感指令来实现完全虚拟化的功能,客户操作系统无须修改,例如VMware Workstation,KVM;
- 部分虚拟化:只针对部分硬件资源进行虚拟化,客户操作系统需要进行修改。现在有些虚拟化技术的早期版本仅支持部分虚拟化。
- 超虚拟化化:部分硬件接口以软件的形式提供给客户机操作系统,客户操作系统需要进行修改,如Xen;
- 操作系统级虚拟化:内核通过创建多个虚拟的操作系统实例来隔离不同的进程。容器相关技术即在这个范畴。操作系统虚拟化最大的特点就是不需要额外的supervisor支持。Docker虚拟化方式之所以有众多优势,跟操作系统虚拟化技术自身的设计和实现是分不开的。
Dokcer以及其他容器技术都属于操作系统虚拟化这个范畴,操作系统虚拟化最大特点是不需要额外的supervisor的支持。传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层,Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,相比而言,更加轻量级。Docker和传统的虚拟化方式不同之处如下图1所示。
图 1 Docker和传统的虚拟化方式的不同之处
2.Docker介绍:
Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议的开源。
简单来说,可以把Docker容器理解为一种轻量级的沙盒,每个容器内运行着一个应用,不同的容器相互隔离,容器之间也可以通过网络互相通信。容器的创建和停止十分快速,几乎跟创建和终止原生应用一致;另外,容器自身对系统资源的额外需求也十分有限,远远低于传统虚拟机。很多时候,甚至直接把容器当作应用本身也没有任何问题。
Docker的构想是要实现“Build,Ship and Run Any App,Anywhere”,即通过对应用的封装、发布、部署、运行生命周期进行管理,达到应用组件级别的“一次封装,导出运行”。这里的应用组件,既可以是一个Web应用、一个编译环境,也可以是一套数据库平台服务,甚至是一个操作系统或集群。
Docker从17.03版本之后分为CE(Community Edition:社区版)和EE(EnterpriseEdition:企业版),学习使用社区版。
1.1Docker容器虚拟化的好处
举个简单例子,假设用户基于常见的LAMP(linux+Apache+MySql+PHP)组合来构建网站,按照传统的做法,首先需要安装Apache、MySQL和PHP以及它们各自运行所依赖的环境;之后分别对他们进行配置(包括创建合适的用户、配置参数等);经过大量的操作后,还需要进行功能测试,看是否工作正常;如果不正常,则进行调试追踪,这意味着更多的时间代价和不可控的风险。可以想像,如果应用数目变多,事情会变得更加难以处理。
更可怕的是,一旦需要服务器迁移,往往需要对每个应用都进行重新部署和调试。这些“体力活”极大降低用户工作效率和开发热情,究其根源,是这些应用直接运行在底层操作系统上,无法保证同一份应用在不同的环境中行为一致。
Docker提供了一种更为聪明的方式,通过容器来打包应用、解耦应用和运行平台。这意味着迁移的时候,只需要在新的服务器上启动需要的容器就可以了,无论新旧服务器是否是同一类型的平台。这将节省大量宝贵时间,降低部署过程中出现的风险。
1.2Docker在开发和运维中的优势
(1)更快速的交付和部署
使用Docker,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成之后,测试和运维人员可以直接使用完全相同的环境来部署代码。只要是开发测试过的代码,就可以确保在生产环境无缝运行。Docker可以快速创建和删除容器,实现快速迭代,节约开发、测试、部署的大量时间。
(2)更高效的资源利用
运行Docker容器不需要额外的虚拟化管理程序的支持,与传统的虚拟机方式相比,Docker的性能要提高1~2个数量级。
(3)更简单的更新管理
使用Dockerfile,只需要小小的配置修改,就可以替代以往大量的更新工作。所有修改都以增量的方式被分发和更新,从而实现自动化并且高效的容器管理。
1.2Docker核心概念
1.2.1镜像(Image)
Docker镜像类似于虚拟机镜像,可以将它理解为一个只读模版。镜像是创建容器的基础。
镜像举例:一个镜像可以是只包含一个基本的操作系统环境,也可以在操作系统里安装一个Apache应用程序,以此当做一个镜像。
1.2.2容器(Container)
Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。容器是从镜像创建的应用运行实例,可以启动、开始、停止、删除,而容器之间是相互隔离、互不可见的。
可以把容器看作一个简易版的linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。
因为镜像自身是制度的,容器从镜像启动的时候,会在镜像的最上层创建一个可写层。
1.2.3仓库(Repository)
Docker仓库类似于代码仓库,是Docker集中存放镜像文件的场所。Docker仓库分为Public和Private两种方式。
目前最大的公共仓库是官方提供的Docker Hub,其中存放着数量庞大的镜像供用户下载。国内腾讯、阿里也提供了仓库本地源,提供稳定访问。
Docker支持用户在本地网络内创建一个只能自己访问的私有仓库。
1.2.4仓库注册服务器(Registry)
仓库注册服务器是存放仓库的地方。
3.Docker安装(针对CentOS)
在新主机上首次安装DockerEngine-Community之前,需要设置Docker仓库。之后,便可以从仓库安装和更新Docker。
2.1安装步骤
(1)安装所需的软件包
(yum-utils提供了yum-config-manager)
(device mapper存储驱动程序需要device-mapper-persisitent-data和lvm2)
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
为了获得较快下载速度,可以设置稳定的仓库:
[设置阿里云的仓库镜像]
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[设置清华大学源的仓库镜像]
sudo yum-config-manager \
--add-repo \
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
本次设置为清华镜像
(2)安装Docker Engine-Community
要安装特定版本的 Docker Engine-Community,请在存储库中列出可用版本,然后选择并安装:
列出并排序您存储库中可用的版本。此示例按版本号(从高到低)对结果进行排序。
yum list docker-ce --showduplicates | sort -r
执行以下命令将安装最新版本的DockerEngine-Community和containerd。
sudo yum install docker-ce docker-ce-cli containerd.io
如果启用了多个 Docker 仓库,则在未在 yum install 或 yum update 命令中指定版本的情况下,进行的安装或更新将始终安装最高版本,这可能不适合您的稳定性需求。
执行以下命令将安装指定版本的DockerEngine-Community
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
本次实验安装版本为20.10.7:
sudo yum install docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io
通过其完整的软件包名称安装特定版本,该软件包名称是软件包名称(docker-ce)加上版本字符串(第二列),从第一个冒号(:)一直到第一个连字符,并用连字符(-)分隔。例如:docker-ce-18.09.1。
4Docker启动及检测是否安装成功
- 启动Docker
sudo systemctl start docker
执行上述命令,若报如下错误:
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
解决参考博客:
https://blog.youkuaiyun.com/zhangbeizhen18/article/details/85239758
(2)测试是否成功
sudo docker run hello-world
执行上述命令,若报如下错误:
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp 54.161.109.204:443: connect: network is unreachable.
See 'docker run --help'.
docker在本地没有找到hello-world镜像,也没有从docker仓库中拉取镜像,出项这个问题的原因:是应为docker服务器再国外,我们在国内
无法正常拉取镜像,所以就需要我们为docker设置国内阿里云的镜像加速器;
需要修改配置文件/etc/docker/daemon.json 如下
{
"registry-mirrors": ["https://alzgoonw.mirror.aliyuncs.com"]
}
参考文档:https://blog.youkuaiyun.com/wireless911/article/details/88989620
(若按上述仍无法运行成功,检查虚拟机是否可以上网)
执行成功后,如下图:
- 卸载docker
删除安装包:yum remove docker-ce(若有指定版本,执行yum remove docker-ce-<version>)
删除镜像、容器、配置文件等内容:rm -rf /var/lib/docker
5Docker基本操作
5.1镜像基本操作
5.1.1获取镜像
docker pull NAMT:[TAG]
(1)命令说明:NAME:镜像仓库名称,TAG是镜像的标签(往往用来表示版本信息),若不明确指定TAG,则默认会选择latest标签,会下载仓库最新版本的镜像。
举例:docker pull ubuntu:15.10
注意:1)一般来说,镜像的latest标签意味着该镜像的内容会跟踪最新版本的变更而变化,内容是不稳定的。因此,从稳定性上考虑,不要在生产环境中忽略镜像的标签信息或使用默认的latest标记的镜像。2)在不同的镜像仓库服务器的情况下,可能会出现镜像重名的情况,严格的讲,镜像的仓库名称中还应该添加仓库地址(即registry,注册服务器)作为前缀,只是默认使用的是官方Docker Hub服务,该前缀可以忽略。例如:docker pull ubuntu:15.10相当于docker pull registry.hub.com/ubuntu:15.10,从非官方的仓库下载,只需在仓库名称前指定完整的仓库地址,例如从网易蜂巢的镜像源来下载ubuntu:15.10镜像,则使用:docker pull hub.c.163.com/public/ubuntu:15.10
- pull命令支持的选项包括
-a,--all-tags=true|false
-q
(3)有时需要使用镜像代理服务来加速Docker镜像获取过程,可以在Docker启动配置中增加—registry-mirror=proxy_URL指定镜像代理服务地址。
5.1.2查看镜像信息
(1)使用images命令列出镜像
docker images或docker image ls
(2)images命令支持选项
-a|--all=true[false]:列出所有镜像文件,包括临时文件,默认为否。
--digests=true|false:列出镜像的数字摘要值,默认为否。
(3)使用tag命令添加镜像标签
docker tag 已有镜像:标签名 新的镜像:标签名
(4)使用inspect命令查看详细信息
docker inspect ubuntu:15.10
若只想查看其中的一项内容时,可以使用-f来指定,例如,获取镜像的Architecture:
docker inspect -f {{“.Architecture”}} ubuntu:15.10
(5)使用history命令查看镜像历史
docker history ubuntu:15.04
5.1.3搜寻镜像
本节主要介绍Docker镜像的search子命令,使用docker search命令可以搜索Docker Hub官方仓库中的镜像。语法为:
docker seaerch [option] keyword。支持的命令选项主要包括:
-f|--filter fiter:过滤输出内容
例子:docker search –filter=is-official=true nginx
--format string:格式化输出内容
--limit int:限制输出结果个数
--no-trunc:不截断输出结果
5.1.4删除和清理镜像
(1)删除镜像命令docker rmi或docker image rm
举例:docker rmi myubuntu:latest|docker image rm myubuntu:latest
(2)支持选项:
-f,-force:强制删除镜像,即使有容器依赖它
-no-prune:不要清理未带标签的父镜像
(3)注意:1)当同一个镜像拥有多个标签的时候,docker rmi命令指示删除了该镜像多个标签中的特定标签而已,并不影响镜像文件,但当镜像只剩下一个标签的时候就要小心了,此时再使用docker rmi命令会彻底删除镜像(镜像文件的所有层)。2)当有某个镜像存在的容器时,镜像文件默认是无法被删除的,若要强制删除,加-f选项,否则,报如下错误:
(4)清理镜像
docker image prune
5.1.5创建镜像
创建镜像的方法主要有三种形式:1)基于已有镜像的容器创建;2)基于本地模版导入;3)基于Dockerfile创建
- 基于已有镜像的容器创建
举例:先启动一个镜像,并在其中进行创建一个文件的操作
docker run -it ubuntu:15.10 /bin/bash
touch test
exit
然后执行docker commit -m “Added a new file” -a “gzw” 1095f4bb81e0 test:0.1
执行上述命令之后,使用docker images可以列出刚被通过commit方式提交的镜像,如下图红线所示
2.基于本地模版导入
3.基于Dockerfile创建
5.1.6存出和载入镜像
(1)存出镜像
如果要导出镜像到本地,可以使用docker save命令,该命令支持-o、-output参数,指定导出镜像到指定文件中
举例:
docker save -o ubuntu_15.10.tar ubuntu:15.10
执行如上命令,用户就可以通过复制ubuntu_15.10.tar文件将该镜像分享给他人。
(2)载入镜像
可以使用docker load将导出的tar文件再导入到本地镜像库。支持-i、-input选项,从指定文件中读入镜像内容。
例如,从ubuntu_15.10导入镜像到本地镜像列表,如下所示:
docker load -i ubuntu_15.10.tar或
docker load < ubuntu_15.10.tar
5.1.7上传镜像
使用docker push命令上传镜像到仓库,默认上传到Docker Hub官方仓库,使用如下命令:
docker push user/test:latest
第一次上传时,会提示输入登录信息或进行注册,之后登录信息会记录到本地~/.docker目录下。
6操作容器
容器是镜像的一个运行实例,与镜像不同的是,镜像是静态的只读文件,而容器是带有运行时需要的可写文件层,同时,容器中的应用进程处于运行状态。
实质上,虚拟机是模拟运行的一整套操作系统(包括内核、应用运行态环境和其他系统环境)和跑在上面的应用。Docker容器就是独立运行的一个或者一组应用,以及它们必需的运行环境。
6.1 创建容器
6.1.1新建容器
使用docker create命令新建一个容器,该命令新建的容器处于停止状态,可以使用docker start命令来启动它。
6.1.2启动容器
使用docker start命令启动一个已经创建的处于终止状态的容器。
6.1.3新建并启动容器
docker run
- 当使用上述命令创建并启动容器时,Docker在后台运行的标准操作包括:
检查本地是否存在指定的镜像,不存在就从公有仓库下载;
- 利用镜像创建一个容器,并启动该容器;
- 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层;
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去;
- 从网桥的地址池配置一个IP地址给容器;
6)执行用户指定的应用程序;
7)执行完毕后容器被自动终止。
(2)常用参数
-i:打开容器输入
-t:分配一个伪终端到容器的输入
-d:以守护进程方式运行docker容器
(3)查看容器输出
docker logs 容器ID|容器名称
6.2停止容器
(1)暂停容器和解除暂停容器
docker pause 容器ID|容器名称
docker unpause 容器ID|容器名称
- 终止容器
使用docker stop 容器ID|容器名称
该命令会首先向容器发送SIGTERM信号,等待一段超时时间后(默认10s),再发SIGKILL信号来终止容器。
6.3进入容器
docker attach 容器ID|容器名称
docker exec -it 容器ID|容器名称 命令
举例:docker exec -it ubuntu:15.10 /bin/bash
6.4删除容器
docker rm 容器ID|容器名称
使用上述命令只能删除已经处于终止或退出状态的容器,如果要删除一个运行中的容器,可以添加-f参数。
6.5导入和导出容器
6.5.1导出容器
导出容器,是指导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态。之后,可将导出的tar文件传输到其他机器上,然后再通过导入命令导入到系统中,实现容器的迁移。
docker export -o 导出的tar文件名 容器名|容器ID
6.5.2导入容器
通过导出的tar文件又可以使用docker import命令导入变成镜像。
docker import 要导入的tar文件名 – REPOSITORY:TAG
6.5.3回顾
之前在5.1.6节存储和载入镜像一节中,介绍了使用docker save和docker load命令来导出、导入镜像文件。实际上,既可以使用docker load命令来导入镜像存储文件到本地镜像库,也可以使用docker import命令来导入一个容器快照到本地镜像库。这两者的区别在于:容器快照文件将丢弃所有的历史记录,而镜像存储文件将保存完整记录,体积更大。
6.6查看容器
6.6.1查看容器详情
docker container inspect 容器ID|容器名
6.6.2查看容器内进程
docker top 容器ID|容器名
6.7其他常用容器命令
6.7.1查看端口映射
docker container port 容器ID|容器名
6.7.2查看变更
docker container diff 容器ID|容器名
该命令可以显示出容器相较于镜像发生变化的文件目录,具体如下:
符号 | 描述 |
A | 创建了文件或目录 |
D | 删除了文件或目录 |
C | 修改了文件或目录 |
7Docker数据管理
在生产环境中使用Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这些涉及容器的数据管理操作。在docker容器中的管理数据主要有两种方式:
(1)数据卷(DataVolumes):容器内数据直接映射到本地主机环境;
(2)数据卷容器(DataVolumeContainers):使用特定容器维护数据卷。
7.1数据卷
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似linux上的挂载。
7.1.1数据卷的特性:
(1)数据卷可以在容器之间共享和重用,容器间传递数据会变得高效与方便;
(2)对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
(3)对数据卷的更新不会影响镜像
(4)卷会一直存在,直到没有容器使用,可以安全卸载它。
7.1.2创建数据卷
Docker提供了volume子命令来管理数据卷,如下命令可以快速在本地创建一个数据卷:
docker volume create -d locat test
8端口映射
前面内容都是对单个容器的管理操作,在实践中,经常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。
8.1端口映射实现容器应用
当容器中运行一些网络应用,要让外部访问这些应用时,可以通过- P或-p参数来指定端口映射。
使用-P标记时,Docker会随机映射一个49000—49900的端口到内部容器开放的网络端口。
使用-p则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有:IP:HostPort:ContainerPort|IP::ContainerPort|HostPort:ContainerPort
(1)举例:映射到指定地址的指定端口:
docker run -d -p 127.0.0.1:5432:5432 postgres:11
(2)举例:映射到指定地址的任意端口:
docker run -d -p 127.0.0.1::5432 postgres:11
(3)举例:映射所有接口地址:
docker run -d -p 5432:5432 postgres:11