Docker快速入门—Docker简介
Docker快速入门——Docker简介
一、Docker简介
1、Docker简介
Docker是Docker Inc公司开源的一项基于Ubuntu LXC技术构建的应用容器引擎,源代码托管在GitHub上,完全基于go语言开发并遵守Apache2.0协议开源。Docker可以让开发者打包应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux版本机器上,也可以实现虚拟化。Docker容器完全使用沙箱机制,容器相互之间不会有任何接口,并且容器性能开销极低。
Docker最初是在Ubuntu 12.04上开发实现的,RedHat从RHEL6.5开始对Docker 进行支持。
Docker最初基于LXC实现,从0.7版本后开始去除LXC,转而使用自行开发的libcontainer。从1.11开始,进一步演进为使用runC和containerd。
Docker官网:http://www.docker.com
Github Docker源码:https://github.com/docker/docker
2、Docker引擎
Docker引擎是一个客户端服务器应用程序,包含如下三个组件:
A、服务器,是一种称为守护进程并且长时间运行的程序。
B、用于指定程序可以用来与守护进程通信的REST API接口。
C、命令行界面(CLI)工具的客户端。
Docker引擎组件的流程如下:
3、Docker的优点
Docker优点如下:
A、更高效地利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
B、更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而Docker容器应用直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间,大大节约了开发、测试、部署的时间。
C、一致的运行环境
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些bug并未在开发过程中被发现。而Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性。
D、持续交付和部署
使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过Dockerfile来进行镜像构建,并结合持续集成(Continuous Integration) 系统进行集成测试;而运维人员则可以直接在生产环境中快速部署镜像,甚至结合持续部署(Continuous Delivery/Deployment)系统进行自动部署,而且使用Dockerfile使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署镜像。
E、更轻松的迁移
由于Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
F、更轻松的维护和扩展
Docker使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker团队同各个开源项目团队一起维护了一大批高质量的官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
4、Docker与虚拟机
虚拟机是一个运行在宿主机上的完整的操作系统,虚拟机运行自身操作系统会占用较多的CPU、内存、硬盘资源。Docker不同于虚拟机,只包含应用程序以及依赖库,基于libcontainer运行在宿主机上,并处于一个隔离的环境中,使得Docker更加轻量高效,启动容器只需几秒钟内完成。由于Docker轻量、资源占用少,使得Docker可以轻易的应用到构建标准化的应用中。但Docker目前还不够完善,缺点如下:
A、隔离效果不如VM,共享宿主机操作系统的一些基础库等。
B、网络配置功能相对简单,主要以桥接方式为主。
C、查看日志也不够方便灵活。
二、Docker架构
1、Docker架构简介
Docker架构遵循C/S架构,分为客户端、Docker主机、Docker镜像仓库三部分。
客户端(Client):Docker提供命令行界面(CLI)工具,客户端与Docker守护进程交互。当使用docker命令时,客户端将相应Docker命令发送到Docker 主机的Docker守护进程进行运行,客户端可以构建,运行和停止应用程序。客户端还可以远程与Docker_Host进行交互。
Docker主机:包含容器、镜像和Docker守护程序,提供完整的环境来执行和运行应用程序。Docker守护进程是一个用于监听Docker API请求的进程。 它还管理Docker对象,如:映像,容器,网络等。守护进程还可以与其他守护进程通信以管理Docker服务。
镜像仓库(Registry):全局镜像仓库,可以访问并使用镜像在Docker环境中运行应用程序。Docker镜像仓库用于存储Docker镜像。Docker提供Docker Hub和Docker Cloud,是任何人都可以使用的公共镜像仓库。Docker配置为默认在Docker Hub上查找映像。当使用docker pull或docker run命令时,从配置的镜像仓库中提取所需的镜像;当使用docker push命令时,镜像被推送到配置的镜像仓库中。
2、Docker镜像
Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建后也不会被改变。
Docker充分利用Union FS 的技术,将其设计为分层存储的架构。Docker镜像是由一组文件系统组成,或是由多层文件系统联合组成。Docker镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己本层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到文件,但是实际上文件会一直跟随镜像。因此,在构建镜像时需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征使得镜像的复用、定制变的更为容易,可以使用构建好的镜像作为基础层,然后进一步添加新的层以定制自己所需的内容,构建新的镜像。
3、Docker容器
Docker镜像是静态的定义,Docker容器是Docker镜像运行时的实体。Docker容器可以被创建、启动、停止、删除、暂停等。
Docker容器的实质是进程,但与直接在宿主执行的进程不同,Docker容器进程运行于属于自己的独立的命名空间。因此Docker容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户ID空间。Docker容器内的进程是运行在一个隔离的环境里,使得容器封装的应用比直接在宿主运行更加安全。Docker容器也是使用分层存储,每一个Docker容器运行时,以镜像为基础层,在其上创建一个当前容器的存储层。容器存储层的生存周期和容器一样,容器消亡时容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
按照Docker最佳实践的要求,Docker容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作都应该使用数据卷(Volume)、或者绑定宿主目录,在数据卷或宿主目录位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行后,数据却不会丢失。
4、Docker镜像仓库(Registry)
Docker镜像仓库(Registry)默认的Registry是Docker公司运营提供的公共镜像仓库即Docker Hub。但本地访问Docker Hub速度通常很慢,因此需要一个本地的私有仓库只供局域网内使用。
三、Docker安装指南
1、Mac平台安装
Homebrew的Cask已经支持Docker for Mac:
加速器配置使用网易的镜像地址:http://hub-mirror.c.163.com。
在任务栏点击Docker for mac应用图标->Perferences... ->Daemon ->Registry mirrors。
在列表中填写加速器地址。修改完成后,点击 Apply & Restart 按钮,Docker就会重启并应用配置的镜像地址。
通过docker info来查看是否配置成功。
2、Linux平台安装
Docker运行在RHEL7上,要求系统为64位、系统内核版本为3.10以上。
Docker运行在 RHEL6.5 或更高的版本要求系统为64位、系统内核版本为2.6.32-431或者更高版本。
本文使用RHEL7.3安装Docker。
安装Docker:sudo yum install docker
启动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.
查看错误信息:systemctl status docker.service
错误原因:SELinux不支持Docker服务
解决方法:编辑sudo vim /etc/sysconfig/docker
1 | OPTIONS='--selinux-enabled=false --log-driver=journald --signature-verification=false' |
运行示例:sudo docker run hello-world
3、Windows平台安装
Win7、Win8需要利用docker toolbox来安装,国内可以使用阿里云的镜像来下载,
Docker ToolBox下载地址:
http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/
Docker ToolBox是一个工具集,主要包含:
A、Docker CLI客户端,用来运行docker引擎创建镜像和容器
B、Docker Machine,用于在Windows的命令行中运行docker引擎命令
C、Docker Compose,用来运行docker-compose命令
D、Kitematic,Docker的GUI版本
E、Docker QuickStart shell,配置好Docker的命令行环境
F、Oracle VM Virtualbox,虚拟机
下载完成后直接点击安装,安装成功后,会出现三个图标:
点击Docker QuickStart图标来启动Docker Toolbox终端。
如果系统显示User Account Control窗口来运行VirtualBox,选择 Yes。
对于Win10专业版系统,Docker有专门的的安装包,需要开启Hyper-V。
Win10专业版系统Docker下载地址:
https://store.docker.com/editions/community/docker-ce-desktop-windows
4、Docker镜像加速器安装
Docker使用daemon.json文件作为Docker服务的配置文件,Linux操作系统使用/etc/docker/daemon.json,Windows操作系统使用%programdata%\docker\config\daemon.json来配置Docker服务。如果相应目录下不存在daemon.json文件,需要创建。
1 | { |
网易的镜像地址:http://hub-mirror.c.163.com。
四、Docker核心技术
1、隔离性
为了实现每个用户实例之间相互隔离,硬件虚拟化方法的解决方案是VM,而LXC的解决方案是container,即kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace将container的进程、网络、消息、文件系统、UTS(UNIX Time-sharing System)和用户空间隔离开。
A、pid namespace
不同用户的进程通过pid namespace隔离开,且不同namespace中可以有相同pid。所有的LXC进程在Docker中的父进程为Docker进程,每个lxc 进程具有不同的namespace。同时由于允许嵌套,因此可以很方便的实现 Docker in Docker。
B、net namespace
通过pid namespace,每个namespace中的pid能够相互隔离,但网络端口还共享host的端口。网络隔离是通过net namespace实现的,每个net namespace有独立的network devices,IP addresses,IP routing tables,/proc/net目录。通过net namespace,每个container的网络就能隔离开来。Docker默认采用veth的方式将container中的虚拟网卡同host上的一个 docker bridge:docker0连接在一起。
C、ipc namespace
container中进程交互采用linux常见的进程间交互方法(interprocess communication - IPC),包括常见的信号量、消息队列和共享内存。然而与VM不同,container的进程间交互还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息——每个IPC 资源有一个唯一的32位 ID。
D、mnt namespace
mnt namespace允许不同namespace的进程看到的文件结构不同,每个namespace中的进程所看到的文件目录就被隔离开了。每个namespace 中的container在/proc/mounts的信息只包含所在namespace的mount point。
E、uts namespace
UTS(UNIX Time-sharing System)namespace允许每个container拥有独立的hostname和domain name,使其在网络上可以被视作一个独立的节点而非Host上的一个进程。
F、user namespace
每个container可以有不同的user和group id,可以在container内部用container内部的用户执行程序而非Host上的用户。
2、可配额/可度量
cgroups实现了对资源的配额和度量。cgroups使用非常简单,提供类似文件的接口,在/cgroup目录下新建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid 写入该文件,即可实现对该进程的资源控制。groups可以限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系统的资源,每个子系统的详细说明如下:
有序列表blkio子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
cpu子系统使用调度程序为cgroup任务提供cpu的访问。
cpuacct:产生cgroup任务的cpu资源报告。
cpuset:如果是多核心的cpu,cpuset子系统会为cgroup任务分配单独的 cpu和内存。
devices允许或拒绝cgroup任务对设备的访问。
freezer暂停和恢复cgroup任务。
memory设置每个cgroup的内存限制以及产生内存资源报告。
net_cls标记每个网络包以供cgroup方便使用。
ns名称空间子系统。
3、便携性
AUFS(Another Union FS)是一种Union FS,支持将不同目录挂载到同一个虚拟文件系统下的文件系统。AUFS支持为每一个成员目录设定readonly、readwrite和whiteout-able权限。同时AUFS里有分层的概念,对readonly 权限的branch可以逻辑上进行修改(增量地,不影响readonly部分的)。
通常Union FS有两个用途,一是可以实现不借助LVM、RAID将多个disk 挂到同一个目录下;一个是将一个readonly的branch和一个writeable的 branch联合在一起(Live CD可以允许在OS image不变的基础上允许用户在其上进行一些写操作)。
典型的启动Linux运行需要两个FS:bootfs + rootfs
bootfs(boot file system)主要包含bootloader 和 kernel,bootloader 主要是引导加载kernel,当boot成功后kernel被加载到内存中后bootfs就被 umount。 rootfs(root file system)包含的就是典型Linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。
不同的linux发行版,bootfs基本是一致的,但rootfs会有差别,因此不同的发行版可以共用bootfs。
典型的Linux在启动后,首先将rootfs设置为readonly,进行一系列检查,然后将其切换为readwrite供用户使用。在Docker中,初始化时也是将rootfs 以readonly方式加载并检查,然而接下来利用union mount的方式将一个 readwrite文件系统挂载在readonly的rootfs之上,并且允许再次将下层的 FS(file system)设定为readonly,并且向上叠加,readonly和writeable组成的结构构成一个container的运行时态,每一个FS被称作一个FS层。
基于AUFS的特性,每一个对readonly层文件/目录的修改都只会存在于上层的writeable层中。由于不存在竞争,多个container可以共享readonly的FS层。所以Docker将readonly的FS层称作image-——对于container 而言整个rootfs都是read-write的,但事实上所有的修改都写入最上层的 writeable层中,image不保存用户状态,只用于模板、新建和复制使用。
上层的image依赖下层的image,因此Docker中把下层的image称作父image,没有父image的image称作base image。因此想要从一个image 启动一个container,Docker会先加载image本身和依赖的父images以及 base image,用户的进程运行在writeable的layer中。所有parent image 中的数据信息以及ID、网络和lxc管理的资源限制等具体container的配置,构成一个Docker概念上的container。
4、安全性
Docker的安全特性包括三个方面:
A、由kernel namespaces和cgroups实现的Linux系统固有的安全标准;
B、Docker Deamon的安全接口;
C、Linux本身的安全加固解决方案,例如AppArmor,SELinux;