小白眼中的docker究竟是个什么东西

前言

Docker,中文名:容器引擎,别名:小鲸鱼,生于2013年3月20日,有一个法裔美籍的母亲 Solumon Hykes,父亲是谁,不得而知。虽然只有7岁,但是在 Hello World 平行宇宙中也算进入了青壮年吧,正在飞速的发展着。

Docker 这个动物选的比较有意思,是一只蓝色的鲸鱼,作为地球上最大的动物,用它来代表容器再合适不过了。不过有谁知道为什么编程技术总是和动物挂钩啊?比如 Linux 的企鹅,Python 的大蛇,Hadoop 的大象等等,有知道的小伙伴还请告知一下。

俗话说的好,“程序不逛动物园,肯定技术有点悬”,经常看到网上有人推荐编程学习方法,先学学基础,然后再看几本儿动物书就可以了,看来这些封面上的动物已经深入人心了。

先把这些动物放到一边,来看看这个 docker 究竟是什么,之前我也不知道它是什么,甚至到了现在我也不能准确的说出它是什么,我只是以一个小白的身份来学习和使用,并且把一些弄懂的知识点总结起来,方便日后查找。

关于docker的疑问

如果你之前看到 docker 时会有下面这些疑问,可以跟着文章梳理了解一下,如果你对这些问题的答案早已烂熟于胸,那么可以简单浏览下,帮我挑挑毛病,也是帮助想学习的同学们:

  1. docker 最近很火啊,它到底能用来做什么?
  2. docker 和虚拟机好像啊,难道就是轻量虚拟机吗?它们两者还有其他的区别吗?
  3. docker 教程里有 ubuntu 上安装 docker,还有 docker 上安装 linux,什么鬼,到底谁装谁啊?
  4. docker 真的这么牛吗?那开发项目必须得用上它啊,显得高端大气上档次!
  5. docker 宣称构建一次,处处运行,那它应该能跨平台吧?

作为小白我也是带着这些疑问开始慢慢了解 docker 的,特别是那个 ubuntu 上装 dockerdocker 上还能装 ubuntu,都给我整蒙圈了,通过不断学习才渐渐弄清了其中的原因。

疑问探索解答

docker 是什么

关于 docker 我们来看下常见的介绍:

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器或 Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

从这一段话中我们可以得到以下几个知识点:

  1. 它是一个容器引擎
  2. 可以用来打包应用
  3. 可以发布到 linux 或者 windows
  4. 可以实现虚拟化
  5. 采用沙箱机制,相互隔离

结合查到的资料来了解一下 docker,首先它是一个容器引擎,引擎这个词经常出现,什么游戏引擎,物理引擎,发动机引擎等等,每种引擎其实就是负责一种核心工作的模块或事物,通过封装来简化工作流程,降低工作难度,而 docker 作为容器引擎的作用当然就是生产容器了。

它的目的就是隔离应用,在隔离空间内部署自己独特的环境,需要了解的是它并不是一项新的技术,而是利用了 Linux 核心中的 cgroupsnamespace 等资源分脱机制来进行隔离,这种被称为容器的进程独立于宿主和其它的隔离的进程,是很早就存在的技术,只不过经过 docker 封装之后使用起来更加方便了。

再说打包应用,这也是 docker 迅速火起来的一个原因,因为环境部署是在太费时费力了,之前在服务器配置一个应用的运行环境,要安装各种软件,Java/Tomcat/MySQL等等。安装和配置这些东西非常麻烦,并且还存在各种版本,而当我们换另一台同样操作系统的服务器还要再配置一遍,有没有办法这些配置直接拷贝过来呢?其实这就是 docker 要做的事情,将应用与运行环境打包到一起,直接在 docker 中运行一个容器就好了,你所依赖的环境直接就装好了。

前面提到 docker 是利用了 linux 内核的一些特性,那么 windows 可以运行吗?如果你查询早期一点的资料会得到不可以的答案,或者说即使在 windows 上运行 docker,也是在中间加了一层 linux 虚拟机。而如今已经 2020 年了,windows 上可以直接安装 docker for windows 来启动提供 docker 服务,而 docker for mac 也使得 docker 运行在 mac 上不再困难,windows 很早就和 docker 进行了合作,最新的 win10 上启动 docker 甚至可以切换内核为 linux 或者 windows,很神奇吧。

说到这里你应该对 docker 有了一个简单的了解,其中有一点很重要,它和宿主机是共享内核的,这是解答上面很多疑惑的钥匙,至于虚拟化,隔离这些都很容易理解了,而这些概念在虚拟机上常常出现,所以很容易把它俩弄混。

容器与虚拟机

自从 docker 出现,容器和虚拟机的对比就没有停过,这些对比常常从启动时间、资源占用、隔离性,操作便利性等方面来进行比较,可以用搜索引擎搜一下,大概就是下面这个样子:

特性 Docker容器 VM虚拟机
启动速速 秒级 分钟级
性能 接近原生 明显弱于原生
硬盘使用 相对较小,可以自由分配 创建时分配,易造成浪费
系统支持量 支持上千个 一般几十个

造成这种差异的原因是什么?还是前面说的 docker 和宿主机是共享内核,而虚拟机是自己创建了一整套系统,虽然隔离性更强,但是也造成了资源的浪费和效率的降低。

一直想找一个例子来形象地对比一下虚拟机和容器,我强行编一个吧,比如你是一个财富自由的人,准备回老家养养牛种种菜,包个鱼塘钓钓鱼,顺便再养一窝小白兔,但是小白兔会吃你种的蔬菜,牛偶尔也会踩到小白兔,这时怎么办,把它们隔开呗。

作为一个钱花不完的人,你准备造几个“小地球”,然后把饲养的动物和种植的植物都放到各自的“地球”中放养,每个小地球都是一个密封的环境,里面有自己的太阳、月亮、空气、河流、山川等等,这种方法当然可以,只是成本有些高,一旦建立了这个小地球,它所占有的资源就定下来了,基本上与大地球隔离,但是它还要依赖大地球,还要建立在地球上,可以类比下虚拟机

因为建造小地球太费时费力了,所以你改了策略,这次不创建完全密闭的环境了,我直接造个篱笆就可以了,阳光、空气、河流我还是使用大地球的,只是在篱笆里我进行定制,做一些鱼塘、蔬菜大棚等等。由于建造篱笆非常省事,我可以批量生产,有需要了我可以直接拿来几个,放在地上就可以使用了,并且不同动物以及植物之间都有篱笆挡着,不会出现相互影响的问题了,这就有点像容器了。

虽然有些牵强,但是这个例子还是可以帮助我们了解容器和虚拟机的区别,实际上容器与虚拟机并不是对立的关系,有时为了防止容器无限制的占用物理机资源,还会现在物理机上运行虚拟机,然后在虚拟机里运行 docker,他们两者只是不同需求下的不同选择而已。

操作系统和容器到底谁安装谁

前面说过 ubuntu 上装 dockerdocker 上还能装 ubuntu 这个问题困扰了我好久,实际上 windows 可以装虚拟机,而虚拟机中有可以装 windows 这没什么好奇怪的,这里的 dokcker 指的就是 docker 引擎,或者认为是 docker 服务器。

它们确实可以相互安装,但情况是不同的,首先说 ubuntu 上装 dockerdocker 说白了还是一种软件,本质上和你在电脑上装个QQ也没有多大差别,只不过这个软件有点特殊,通过它还能下载、安装别的环境,这么说它看起来有点像应用商店了,不过他虽然提供仓库,但是不仅仅是仓库,本质上它就是一种帮助你搭建环境的软件。

再来看看 docker 上装 ubuntu,还记得之前说过的一个重点吗? docker 上安装的环境与宿主机共享内核,这就决定了他不能安装完整的系统,不管是 ubuntuCentOS 还是 RedHat,它所安装的系统仅仅包含运行库和工具链,内核还是用宿主机的,相当于在 docker 中给内核套了一个新的壳子而已。

这下应该清楚了,ubuntu 上装 docker 就是在 ubuntu 上装了一个容器软件, docker 上装 ubuntu 就是在 docker 容器中给宿主内核套上了一个新系统的壳子,使其满足应用软件的环境,配备应用软件可使用的工具链。

这么厉害的容器项目中一定要用吗

相信这种问题就是不了解容器也可以回答,肯定不是都要用啊,没有什么技术是只有优点没有缺点吧,凡是技术总有其适合的领域和场景,一味的追求最新的技术不一定符合所要开发的项目。

docker 也没有传说的那么神,它也有着这样那样的问题,比如一直津津乐道的资源伸缩机制,不像虚拟机那样创建时便规定了资源大小,即使不使用也占用着,而 docker 可以直接使用宿主资源,避免了很多浪费。但是反过来想,虚拟机规定了资源的多少,如果不够用了只影响它自己,而 docker 如果一个环境出了问题,它可以把整个物理机的资源耗完,影响机器上的所有服务。

另外,docker 建议只部署无状态的服务,它们不应该承载任何交易数据,所有数据应该保存在数据库服务器中,器随时可以停止、或者删除。当容器被删除掉,容器里的数据将会丢失,即使你要把 docker 数据放在主机来存储,它依然不能保证不丢数据,具体的细节我也在学习,有这方面经验的朋友可以发表一下见解。

docker的跨平台

先来看看跨平台的概念:

跨平台概念是软件开发中一个重要的概念,即不依赖于操作系统,也不依赖硬件环境。一个操作系统下开发的应用,放到另一个操作系统下依然可以运行。

首先要弄明白你说的跨平台指的是 docker 跨平台,还是它里边的应用使用 docker 就能跨平台了,从定义来说 docker 这个容器软件应该算是跨平台的,毕竟 LinuxWindowsMac 都有了 docker 的安装包,那么他里面的镜像运行之后的容器能跨平台吗?这还要看具体的应用,docker 没有让一个非跨平台软件变成跨平台软件的能力。

关于这一点你还要牢记前面说的,docker 中的环境与宿主机共享内核,你创建了一个自己编写的exe程序的镜像,拿到安装了 dockerubuntu 机器上显然是无法成功运行的。

基础知识点

docker的缺点

docker 的卖点是让你摆脱配置环境的困扰,但真实情况是你打包镜像的机器和系统版本,最好和你要运行的目标机器和系统版本一致,另外 docker 环境最好也一样,忽然感觉它没有那么神奇了,这不还是要求版本吗?

试想一下,你用一个高版本的 docker 服务打包,其中使用了一些新特性,然后放到低版本的 docker 服务下怎么能保证成功运行,机器配置也是一样,之前看到过一个问题 “尝试在具有 4.19 或更高内核的 Linux 系统上运行 docker official centos:6centos:5 容器,当尝试启动它时,你会发现内核和程序不兼容”。

这样看来,docker 只适合在相同环境下批量复制,使得实现自动化测试和持续的集成很方便,但还是有些问题需要注意的:

  1. docker 是基于64位系统环境的,32位环境下无法使用
  2. 隔离性相比 KVM 之类的虚拟化方案还是有些欠缺
  3. 容器随着用户进程的停止而销毁,其中的日志、打点等用户数据不便收集
  4. 网络管理相对简单,主要是基于 namespace 隔离
  5. 容器的 root 和宿主机 root 等同,这使得容器容易受到攻击

docker 的组成

前面一直在说初学 docker 时的疑问,接下来看看 docker 究竟都包括哪些内容,docker 这个容器引擎实际上是一个客户端/服务器应用程序,客户端负责与守护的服务进程进行对话,而服务进程负责构建、运行和分发 docker 容器。
docker 客户端和服务进程可以在同一系统上运行,也可以进行远程访问,通过网络接口使用 RESTful API 进行通信。

使用 docker 时常常要接触三个概念:镜像(Image)、容器(Container)和仓库(Repository)。简单来说镜像就是我们的想要打包的程序机加上程序运行环境,打包出来的一个文件,相当于程序安装包。当镜像运行起来我们就得到了容器,镜像与容器的关系就类似于类和对象的关系。仓库就是存放镜像的地方,与代码的仓库 Github 很像,docker 镜像也有一个常用的仓库叫 Docker Hub,方便人们直接下载镜像来运行。

运行一个镜像

Hello world 常常被拿来新知识的入门和开头,今天我们用这个例子来做一下收尾吧,首先你得有 docker 环境,说人话就是你得装了 docker 软件,之前不是一直说 docker 就是一个软件吗,你想用它当然得安装了,这类教程很多,假设你已经安装完了,

我们在一台 CentOS 上操作使用一下 docker,查询下系统版本和 docker 版本:

1
2
3
4
5
6
7
8
9
[root@remote-os ~]# lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.7.1908 (Core)
Release: 7.7.1908
Codename: Core
[root@remote-os ~]# docker --version
Docker version 19.03.7, build 7141c199a2
[root@remote-os ~]#

首先下载 hello world 镜像,使用 docker image pull hello-world 命令

1
2
3
4
5
6
[root@remote-os ~]# docker image pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
Status: Image is up to date for hello-world:latest
docker.io/library/hello-world:latest

查看本地镜,使用 docker image ls 命令,发现 hell-world 镜像已经在本地了

1
2
3
4
5
6
7
8
[root@remote-os ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest adafef2e596e 3 weeks ago 73.9MB
registry latest 708bc6af7e5e 6 months ago 25.8MB
hello-world latest bf756fb1ae65 7 months ago 13.3kB
wurstmeister/zookeeper latest 3f43f72cb283 18 months ago 510MB
hyper/docker-registry-web latest 0db5683824d8 3 years ago 599MB
[root@remote-os ~]#

下载完成之后直接使用 docker container run hello-world 命令运行就可以了,这个镜像运行打印完直接就退出了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@remote-os ~]# docker container run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

如果不想退出,运行的镜像应该是能提供某种服务的,比如前面一直说的 ubuntu,它可以在 docker 中运行起来,直接使用 docker container run -it ubuntu bash 命令就行,这里为什么我们不先下载呢?实际上如果你指定的镜像在本地没有的话会自动下载,不需要手动下载完再运行。

1
2
3
4
5
6
7
8
9
10
11
[root@remote-os ~]# docker container run -it ubuntu bash
root@0577050677ac:/# cat /etc/issue
Ubuntu 20.04 LTS \n \l

root@0ecfed0920aa:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@0ecfed0920aa:/# ll home/
total 8
drwxr-xr-x 2 root root 4096 Apr 15 11:09 ./
drwxr-xr-x 1 root root 4096 Jul 31 16:23 ../
root@0ecfed0920aa:/#

可以看到上面的操作,我们又进入了 ubuntu 系统,成功运行了镜像,现在得到了一个容器,可以通过 docker container ls 命令查看,还可以通过 docker container rm [containerID] 命令来删除容器。

总结

  • docker 软件可以运行在windowslinuxmac
  • docker 容器与宿主机共享一个系统内核,如果依赖内核版本的应用最好保证物理机系统版本一致
  • docker 容器与虚拟机并不是对立的,有时候会放在一起配合使用
  • docker 有自己的镜像仓库,可以直接下载安装,使用起来相当方便,因为网络原因,如果想快速搭建最好提前准备好镜像文件

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

海纳百川有容乃大,壁立千仞无欲则刚~

2020-8-1 00:31:35

Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客