没有道理不介绍一下现在流行的Docker
Docker是什么
Docker是一个开发,分发和运行应用程序的开放平台。 Docker可以将应用程序与基础架构分离,以便快速交付软件。 使用Docker,可以像管理应用程序一样管理基础架构。 通过利用Docker实现快速发送,测试和部署代码,可以显着减少编写代码和在生产中运行代码之间的延迟。
- Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案
- 早期版本的Docker是基于已经成熟的Linux Container(LXC)技术实现的。自Docker 0.9版本起,Docker逐渐从LXC转移到新的libcontainer上,并且积极推动开放容器规范runc,试图打造更通用的底层容器虚拟化库。
架构
概念
docker cli命令行
Command Line Interface
操作Docker的命令行
- Docker CLI Command
- Docker Container State
另,如果只想安装client不想安装整套Docker,可以下载Docker Version Manager
image镜像
- 一个镜像是轻量的、独立的、一个包含所有需要运行它(软件、运行时、系统工具、系统库、设置)的可执行包的软件。
- 只读的模版
- 可以创建、更新现有镜像,也可以直接下载已有镜像使用
- 可以用来创建container
- 统一文件系统(union file system)技术将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,隐藏了多层的存在,在用户的角度看,只存在一个文件系统。
镜像层
- 元数据:让Docker获取运行和构建时的信息、父层的层次信息。每一层都有元数据
- 指针:指向父层、没有则代表它处于最底层
container容器
- 镜像创建的运行实例
- Docker利用容器运行应用
- 启动、开始、停止、删除
- 容器间相互隔离
- 与镜像的区别:最上面一层是可读写的
- 容器=镜像+读写层
daemon守护进程
- Docker的守护进程,也就是Server端
- clinet通过命令行与daemon通信
- 修改方式:
- 命令行(学习研究)
- 启动项(配置稳定、不常修改)
- 配置文件(定时修改)
registry注册服务器
- 镜像仓库
- Registry有很多repository
- 可以被第三方托管
repository仓库
- 是一系列拥有相同名字不同tag的镜像集合
注册服务器上存有多个仓库,每个仓库又存放了多个镜像,每个镜像有不同的标签tag
核心技术
cgroup资源限制
Control Groups是Linux内核提供的一种极致,可以根据特定的行为,把一系列系统任务及其子任务整合(或分离)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。
- 功能
- 资源限制(Resource Limiting):对进程组使用的资源总额进行限制(包括CPU、memory、IO、网络、文件等)
- 优先级分配(Prioritization):通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级
- 隔离(Isolation):为组隔离命名空间,这样一个组不会看到另一个组的进程、网络连接和文件系统
- 资源统计(Accounting):统计系统的资源使用量
- 进程控制(Control):对进程组执行挂起、恢复和重启等操作
namespace资源隔离
每个容器都有独立的命名空间,运行在其中的应用都像是在独立的操作系统环境中一样,命名空间机制保证了容器之间彼此互不影响。
- 进程命名空间
Linux通过命名空间管理进程号,对于同一进程(即同一个task_struct),在不同的命名空间中,看到的进程号不相同,每个进程命名空间有一套自己的进程号管理方法。进程命名空间是一个父子关系的结构,子空间中的进程对于父空间是可见的。新fork出的进程在父命名空间和子命名空间将分别有一个进程号来对应。
- 网络命名空间
网络命名空间为进程提供了一个完全独立的网络协议栈的视图,包括网络设备接口、IPv4和IPv6协议栈、IP路由表、防火墙规则、sockets等,这样每个容器的网络就能隔离开来。Docker采用虚拟网络设备(Virtual Network Device)的方式,将不同命名空间的网络设备连接到一起。默认情况下,容器中的虚拟网卡将同本地主机上的docker0网桥连接在一起。
- IPC命名空间
容器中进程交互还是采用了Linux常见的进程间交互方法(Interprocess Communication,IPC),包括信号量、消息队列和共享内存等。PID Namespace和IPC Namespace可以组合起来一起使用,同一个IPC命名空间内的进程可以彼此可见,允许进行交互;不同空间的进程则无法交互。
- 挂载命名空间
类似于chroot,将一个进程放到一个特定的目录执行。挂载命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中的进程所看到的文件目录彼此被隔离。
- UTS命名空间
UTS(UNIX Time-sharing System)命名空间允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个有独立主机名和网络空间的环境,就跟网络上一台独立的主机一样。默认情况下,Docker容器的主机名就是返回的容器ID
- 用户命名空间
每个容器可以有不同的用户和组id,也就是说可以在容器内使用特定的内部用户执行程序,而非本地系统上存在的用户。
大约在0.6版,privileged被引入docker。
使用该参数,container内的root拥有真正的root权限。
否则,container内的root只是外部的一个普通用户权限。
privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。
甚至允许在docker容器中启动docker容器。
通过使用隔离的用户命名空间可以提高安全性,避免容器内进程获取到额外的权限。
mount上去的文件,docker没有读写权限。
举个例子:
mount了一个文件夹,但是在docker里面就是无法访问。
相关搜索关键字:docker privileged=true
Union File System联合文件系统
联合文件系统(UnionFS)是一种轻量级的高性能分层文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果。
在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。
- Docker存储
Docker目前通过插件化方式支持多种文件系统后端。Debian/Ubuntu上成熟的AUFS(Another Union File System,或v2版本往后的Advanced Multilayered Unification File System),就是一种联合文件系统实现。AUFS支持为每一个成员目录(类似Git的分支)设定只读(readonly)、读写(readwrite)或写出(whiteout-able)权限,同时AUFS里有一个类似分层的概念,对只读权限的分支可以在逻辑上进行增量地修改(不影响只读部分的)。
Docker镜像自身就是由多个文件层组成,每一层有唯一的编号(层ID),可以通过docker history
查看多个文件层组成。
推荐将容器修改的数据通过volume方式挂载,而不是直接修改镜像内数据。
- 多种文件系统比较
Docker目前支持的联合文件系统种类包括AUFS、OverlayFS、btrfs、vfs、zfs和Device Mapper等。
- AUFS:最早支持的文件系统,对Debian/Ubuntu支持好,虽然没有合并到Linux内核中,但成熟度很高;
- OverlayFS:类似于AUFS,性能更好一些,已经合并到内核,未来会取代AUFS,但成熟度有待提高;
- Device Mapper:Redhat公司和Docker团队一起开发用于支持RHEL的文件系统,内核支持,性能略慢,成熟度高;
- btrfs:参考zfs等特性设计的文件系统,由Linux社区开发,试图未来取代Device Mapper,成熟度有待提高;
- vfs:基于普通文件系统(ext、nfs等)的中间层抽象,性能差,比较占用空间,成熟度也一般。
- zfs:最初设计为Solaris 10上的写时文件系统,拥有不少好的特性,但对Linux支持还不够成熟。
AFUS、Device Mapper应用广泛,支持成熟,生产环境考虑;OverlayFS可能具有更好的性能。
Linux网络虚拟化支持
Docker中的网络接口默认都是虚拟的接口。虚拟接口的最大优势就是转发效率极高。这是因为Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。对于本地系统和容器内系统来看,虚拟接口跟一个正常的以太网卡相比并无区别,只是它速度要快得多。
Docker的本地网络实现其实就是利用了Linux上的网络命名空间和虚拟网络设备,特别是veth pair,在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做veth pair)。
命令
images
docker create <image-id>
为指定的镜像添加了一个可读写层,构成了一个新的没有运行的容器docker run <image-id>
包含了docker create
和docker start
命令docker images
列出所有顶层镜像- 顶层:创建容器时使用的镜像、直接pull下来的镜像。每一个顶层镜像下面都隐藏了多个镜像层
docker images -a
列出所有的镜像(列出了所有的可读层)docker history
列出某一个image-id下的所有层docker rmi <image-id>
删除镜像,默认会删除unlinked的中间layer,为了安全,当有容器在引用这个images时是不可以删除的,通过-f
参数,可以强制删除--no-prune
:不删除中间layer
docker build
:根据Dockerfile文件中的FROM
指令获取到镜像,然后重复的run、update、commit。在循环中的每一步都会生成一个新的层,因此许多新的层会被创建。docker save <image-id>
创建一个镜像的压缩文件,这个文件能够在另外一个主机的Docker上使用。和export命令不同,这个命令为每一个层都保存了它们的元数据,通过docker images -tree
命令能够看到历史镜像。docker history <image-id>
递归地输出指定镜像的历史镜像
container
docker start <container-id>
为容器文件系统创建了一个进程隔离空间,每个容器只有一个进程隔离空间。docker ps
列出所有运行中的容器docker ps -a
列出所有容器docker stop <container-id>
向运行中的容器发送一个SIGTERM的系统信号,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间(默认10秒),会继续发送SIGKILL的系统信号强行KILL掉进程。- 设置超时时间:
docker stop --`
time=20 container_name`
- 设置超时时间:
docker kill
:直接发出SIGKILL的系统信号,强行终止容器中程序的运行。docker pause <container-id>
利用cgroups的特性将运行中的进程空间暂停,不保证暂停所有进程docker rm <container-id>
移除构成容器的可读写层,只对非运行态容器执行。docker commit <container-id>
将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像。docker exec <running-container-id>
会在运行中的容器执行一个新进程,进入到容器内。docker export <container-id>
创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到的内容
both
docker inspect <container-id> or <image-id>
提取出容器或者镜像最顶层的元数据
镜像加速器
阿里云加速器
针对安装了Docker for Mac的用户
右键点击桌面顶栏的 docker 图标,选择 Preferences ,在 Daemon 标签(Docker 17.03 之前版本为 Advanced 标签)下的 Registry mirrors 列表中将
加速器地址加到”registry-mirrors”的数组里,点击 Apply & Restart按钮,等待Docker重启并应用配置的镜像加速器。
Docker 中国官方镜像加速
配置Docker守护进程默认使用Docker官方镜像加速,可以默认通过官方镜像加速拉取,而无需在每次拉取时指定registry.docker-cn.com
- 在守护进程启动时传入
--registry-mirror
参数:
docker --registry-mirror=https://registry.docker-cn.com daemon
- 永久性保留更改,可以通过修改
/etc/docker/daemon.json
文件兵添加上registry-mirrors键值
1 | { |
- 修改保存后,重启Docker以使配置生效。
新手建议
参考
Difference between Docker registry and repository