1 Docker底层实现
docker底层主要是通过cgroup和namespace两种技术实现,cgroup实现资源限额, namespace实现资源隔离。
在容器内部执行ps之后出现两个进程在运行,一个是我的服务,另外一个是我刚刚执行的ps,已经看到容器内部进程已经跟我们的宿主机中的服务完全隔离开了。这其实就是对被隔离应用的进程空间做了隔离,使得这些进程空间下的进程只能看到重新计算之后的进程编号,这就是linux的namespace机制,linux底层是通过clone()函数实现,而当在docker中创建进程时就可以通过指定参数返回一个全新的进程空间,这样的话的就做到了pid为1的目的,其实你到宿主机上查看下,这个docker中运行的服务,在宿主机上存在着同样的进程,只不过这个进程的pid是真实的pid。
Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等.
进入容器内部/sys/fs/cgroup/文件夹下面,里面包含了很多子目录,通过这些目录中的文件内容就可以实现对各种资源的限制。
看到这里,再品一下,容器就是一个进程而已。
2 什么是Docker?
Docker是一个开源的应用容器引擎,它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到安装了任何 Linux 发行版本的机器上。Docker基于LXC来实现类似VM的功能,可以在更有限的硬件资源上提供给用户更多的计算资源。与同VM等虚拟化的方式不同,LXC不属于全虚拟化、部分虚拟化或半虚拟化中的任何一个分类,而是一个操作系统级虚拟化。
Docker是直接运行在宿主操作系统之上的一个容器,使用沙箱机制完全虚拟出一个完整的操作,容器之间不会有任何接口,从而让容器与宿主机之间、容器与容器之间隔离的更加彻底。每个容器会有自己的权限管理,独立的网络与存储栈,及自己的资源管理能,使同一台宿主机上可以友好的共存多个容器。
Docker借助Linux的内核特性,如:控制组(Control Group)、命名空间(Namespace)等,并直接调用操作系统的系统调用接口。从而降低每个容器的系统开销,并实现降低容器复杂度、启动快、资源占用小等特征。
3 Docker和虚拟机的区别?
虚拟机Virtual Machine与容器化技术(代表Docker)都是虚拟化技术,两者的区别在于虚拟化的程度不同。
- 举个例子
- 服务器:比作一个大型的仓管基地,包含场地与零散的货物——相当于各种服务器资源。
- 虚拟机技术:比作仓库,拥有独立的空间堆放各种货物或集装箱,仓库之间完全独立——仓库相当于各种系统,独立的应用系统和操作系统。
- Docker:比作集装箱,操作各种货物的打包——将各种应用程序和他们所依赖的运行环境打包成标准的容器,容器之间隔离。
- 基于一个图解释
- 虚拟机管理系统(Hypervisor)。利用Hypervisor,可以在主操作系统之上运行多个不同的从操作系统。类型1的Hypervisor有支持MacOS的HyperKit,支持Windows的Hyper-V以及支持Linux的KVM。类型2的Hypervisor有VirtualBox和VMWare。
- Docker守护进程(Docker Daemon)。Docker守护进程取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理Docker容器。
- vm多了一层guest OS,虚拟机的Hypervisor会对硬件资源也进行虚拟化,而容器Docker会直接使用宿主机的硬件资源
- 基于虚拟化角度
- 隔离性 由于vm对操作系统也进行了虚拟化,隔离的更加彻底。而Docker共享宿主机的操作系统,隔离性较差。
- 运行效率 由于vm的隔离操作,导致生成虚拟机的速率大大低于容器Docker生成的速度,因为Docker直接利用宿主机的系统内核。因为虚拟机增加了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在Hypervisor虚拟的CPU上的;另外一方面是由于计算程序本身的特性导致的差异。虚拟机虚拟的cpu架构不同于实际cpu架构,数值计算程序一般针对特定的cpu架构有一定的优化措施,虚拟化使这些措施作废,甚至起到反效果。
- 资源利用率 在资源利用率上虚拟机由于隔离更彻底,因此利用率也会相对较低。
4 Docker的架构?
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
- Docker 客户端(Client) : Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
- Docker 主机(Host) :一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看着一个代码控制中心,用来保存镜像。
5 Docker镜像相关操作有哪些?
# 查找镜像
docker search mysql
# 拉取镜像
docker pull mysql
# 删除镜像
docker rmi hello-world
# 更新镜像
docker commit -m="update test" -a="pdai" 0a1556ca3c27 pdai/ubuntu:v1.0.1
# 生成镜像
docker build -t pdai/ubuntu:v2.0.1 .
# 镜像标签
docker tag a733d5a264b5 pdai/ubuntu:v3.0.1
# 镜像导出
docker save > pdai-ubuntu-v2.0.2.tar 57544a04cd1a
# 镜像导入
docker load < pdai-ubuntu-v2.0.2.tar
6 Docker容器相关操作有哪些?
# 容器查看
docker ps -a
# 容器启动
docker run -it pdai/ubuntu:v2.0.1 /bin/bash
# 容器停止
docker stop f5332ebce695
# 容器再启动
docker start f5332ebce695
# 容器重启
docker restart f5332ebce695
# 容器导出
docker export f5332ebce695 > ubuntu-pdai-v2.tar
# 容器导入
docker import ubuntu-pdai-v2.tar pdai/ubuntu:v2.0.2
# 容器强制停止并删除
docker rm -f f5332ebce695
# 容器清理
docker container prune
# 容器别名操作
docker run -itd --name pdai-ubuntu-202 pdai/ubuntu:v2.0.2 /bin/bash
7 如何查看Docker容器的日志?
#例:实时查看docker容器名为user-uat的最后10行日志
docker logs -f -t --tail 10 user-uat
#例:查看指定时间后的日志,只显示最后100行:
docker logs -f -t --since="2018-02-08" --tail=100 user-uat
#例:查看最近30分钟的日志:
docker logs --since 30m user-uat
#例:查看某时间之后的日志:
docker logs -t --since="2018-02-08T13:23:37" user-uat
#例:查看某时间段日志:
docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37" user-uat
#例:将错误日志写入文件:
docker logs -f -t --since="2018-02-18" user-uat | grep error >> logs_error.txt
8 如何启动Docker容器?参数含义?
[root@pdai docker-test]# docker run -itd pdai/ubuntu:v2.0.1 /bin/bash
- -it 可以连写的,表示 -i -t
- -t: 在新容器内指定一个伪终端或终端。
- -i: 允许你对容器内的标准输入 (STDIN) 进行交互
-
9 如何进入Docker后台模式?有什么区别?
第一种:docker attach
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 38 minutes ago Up 2 seconds 22/tcp, 80/tcp jolly_kepler
[root@pdai ~]# docker attach f5332ebce695
root@f5332ebce695:/# echo 'pdai'
pdai
root@f5332ebce695:/# exit
exit
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
看到没,使用docker attach进入后,exit便容器也停止了。
第二种:docker exec
[root@pdai ~]# docker exec -it f5332ebce695 /bin/bash
Error response from daemon: Container f5332ebce69520fba353f035ccddd4bd42055fbd1e595f916ba7233e26476464 is not running
[root@pdai ~]# docker restart f5332ebce695
f5332ebce695
[root@pdai ~]# docker exec -it f5332ebce695 /bin/bash
root@f5332ebce695:/# exit
exit
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 42 minutes ago Up 8 seconds 22/tcp, 80/tcp jolly_kepler
注意:
我特意在容器停止状态下执行了docker exec,是让你看到docker exec是在容器启动状态下用的,且注意下错误信息;
- 推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。