干货分分钟带你看懂Docker

Posted 全栈IT技术前线

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货分分钟带你看懂Docker相关的知识,希望对你有一定的参考价值。

Docker 自开源以来受到了各大公司的广泛关注,或许现在互联网公司的运维体系不承载在 Docker(或 Pouch 等)之上都不好意思说自己的互联网公司。

本文会简单介绍下 Docker 的基础概念,入门级使用方式和一些使用 Docker 能大大提升效率的场景。

对 Docker 最简单并且带有一定错误的认知就是 “Docker 是一种性能非常好的虚拟机”。
正如上面所说,这是有一定错误的说法。Docker 相比于传统虚拟机的技术来说先进了不少,具体表现在 Docker 不是在宿主机上虚拟出一套硬件后再虚拟出一个操作系统,而是让 Docker 容器里面的进程直接运行在宿主机上(Docker 会做文件、网络等的隔离),这样一来 Docker 会 “体积更轻、跑的更快、同宿主机下可创建的个数更多”。

Docker 中有三个核心概念:Image、Container、Repository。

  • Image: 有领“好人卡”倾向的广大程序猿一定对 镜像 的概念不会陌生。但和 Windows 的那种 ISO 镜像相比,Docker 中的镜像是分层的,可复用的,而非简单的一堆文件迭在一起(类似于一个压缩包的源码和一个 Git 仓库的区别)。


  • Container: 容器的存在离不开镜像的支持,他是镜像运行时的一个载体(类似于实例和类的关系)。依托 Docker 的虚拟化技术,给容器创建了独立的端口、进程、文件等“空间”,Container 就是一个与宿机隔离 “容器”。容器可宿主机之间可以进行 port、volumes、network 等的通信。


  • Repository: Docker 的仓库和 Git 的仓库比较相似,拥有仓库名、tag。在本地构建完镜像之后,即可通过仓库进行镜像的分发。常用的 Docker hub 有 https://hub.docker.com/ 、 https://cr.console.aliyun.com/ 等。


历史文章请点击:


1



什么是Docker?


打开翻译输入 Docker 结果显示码头工人,没错!码头工人搬运的是集装箱,那么今天要讲的 Docker 其操作的也是集装箱,这个集装箱就静态而言就是一个应用镜像文件,就动态而言,就是一个容器。蒙了吧?好吧,上图解释。3种云模式中属于PAAS层!

【干货】分分钟带你看懂Docker


Docker 从狭义上来讲就是一个进程,从广义上来讲是一个虚拟容器,其实更专业的叫法是应用容器( Application Container ),Docker 进程和普通的进程没有任何区别,它就是一个普通的应用进程。不过是用来操作镜像文件的。所以 Docker 进程+构建的应用镜像文件就等于 Docker 容器。本文所有讲的 Docker 都是指 Docker 容器哦。


再继续下文之前我们首先要明确几个 docker 重要的基本概念吧,镜像,容器,仓库。


镜像 Docker images,就类似于 VM 虚拟机里面的快照,但是可比快照轻量化多了。快照不懂?那可以把 images 直接理解成一个文件夹。我们可以通过 ID 或者易识别的名字 +tag 来确认唯一的目标镜像。ImagesID 是一个64位的字符,但是一般我们都是使用前面12位就足够区别了。


【干货】分分钟带你看懂Docker


如图中左边红框中 redis: lates 和右边的红框中 5f515359c7f8 都唯一表示为同一个镜像。所以我们一般的镜像可以命名为类似centos: latest、centos: centos7.1.1503等等。


镜像是分层的,有基础镜像,仅仅包含操作系统,比如 centos 镜像;有中间件镜像,比如 redis 等数据库镜像;最后是应用镜像,就是指具体的应用服务了,应用镜像可以非常丰富,随时可以发布,这三者之间依次叠加。


所以当我们在使用 Docker 构建镜像的时候,每一个命令都会在前一个命令的基础上形成一个新镜像层。如下图,基础镜像就是 centos 镜像,中间件镜像就是两个红色圈,应用镜像就是紫色圈。其中 redis+centos 这样叠加组合的中间件镜像就可以供A服务或者B服务使用,这样叠加组合更加灵活。仍和一种镜像都可以从 Docker hub 公共仓库中拉取。

【干货】分分钟带你看懂Docker


容器 Docker containers,你可以从镜像中创建容器,这如同从快照中创建虚拟机,不过更轻量,启动更快,秒启。应用是在容器中运行的,打个比方,你首先下载了一个 Ubuntu 的镜像,然后又安装 mysql 和 Django 应用及其依赖,来完成对它 Ubutun 镜像的修改,一个个人觉得非常完美应用镜像生成了!就把这个镜像分享给大家使用,大家通过这个镜像就生成一个容器。容器启动之后就会运行 Django 服务了。



【干货】分分钟带你看懂Docker



上面也说到了,容器就是一个个独立的封闭的集装箱,但是也需要对外提供服务的,所以 Docker 允许公开容器的特定端口,在启动 Docker 的时候,我们就可以将容器的特定端口映射到宿主机上面的任意一个端口,所以,如果几个服务都需要80端口,那么容器的对外端口是80,但是映射到宿主机上面就是任意端口,就不会产生冲突,所以就不需要通过代理来解决冲突。容器对外端口与宿主机的端口映射可以通过下面的命令来完成。


启动 docker 容器

docker run -d -p 2222:22 --name 容器名 镜像名

-d 守护容器,就是后台运行,退出命令窗口容器也不会停止

-it 交互式容器 退出命令窗口容器就停止运行了

-p宿主机端口和容器端口映射

8081:80  宿主机端口:容器公开的端口



【干货】分分钟带你看懂Docker


仓库 Docker registeries,docker 仓库和存放集装箱的仓库是一样的,不过 docker 使用来存放镜像的。仓库存在公有和私有之分,公有仓库 docker hub 提供了非常多的镜像文件,这些镜像直接拉取下来就可以运行了,你也可以上传自己的镜像到 docker hub 上面。同时也可以自己搭建私有仓库用于团队项目管理。


结合前面介绍的基本概念,我们可以将 docker 的几个概念使用大致串起来,他们之间是如何运作的,也就是 Docker 的生命周期。看下图,主要是三步走。


【干货】分分钟带你看懂Docker


  1. 开发构建镜像并将镜像 push 到 Docker 仓库;

  2. 测试或者运维从 Docker 仓库拷贝一份镜像到本地;

  3. 通过镜像文件开启 Docker 容器并提供服务。


2



为啥要用 Docker?能干些啥?


这要从目前软件行业的痛点来讲起:

  1. 软件更新发布及部署低效,过程繁琐且需要人工介入;

  2. 环境一致性难以保证;

  3. 不同环境之间迁移成本太高。


有了 Docker 可以很大程度解决上面的问题。


首先,Docker 的使用简单至极,开发的角度来看就是三步走:构建,运输,运行。其中关键步骤就是构建环节,即打包镜像文件。但是测试和运维的角度来看,那就只有两步:复制,运行。有了这个镜像,那么想复制到哪运行都可以,完全和平台无关了。同时 Docker 这种容器技术隔离出了独立的运行空间,不会和其他应用争用系统资源了以及还不需要考虑应用之间相互影响,想想就开心。


其次,因为在构建镜像的时候就处理完了服务程序对于系统的所有依赖,所以在你使用的时候,你可以忽略掉原本程序的依赖以及开发语言。对测试和运维而言,更多专注于自己的业务内容上。


最后,Docker 于开发者而言提供了一种开发环境的管理办法,与测试人员而言保证了环境的同步,于运维人员提供了可移植的标准化部署流程。


所以, Docker 能干啥,总结如下:

  • 构建容易分发简单

  • 隔离应用解除依赖

  • 快速部署测完就销


Docker 是个进程级的轻量化虚拟机,和传统虚拟机有啥区别呢?


Docker 这个虚拟机超级轻量级,仅仅是一个进程而已。与传统的虚拟机比如 VM 有着巨大的差别,区别看下图:


【干货】分分钟带你看懂Docker

【干货】分分钟带你看懂Docker


我们来看一下二者的区别,因为 VM 的 Hypervisor 需要实现对硬件的虚拟化,并且还要搭载自己的操作系统,其中虚拟机操作系统占用内存是比较大的,一个操作系统有好几个G,自然在启动速度和资源利用率以及性能上有非常大的开销,如果在本地,或者个人电脑,那么影响还不是那么大,但是在云端就是一个非常大的资源浪费。


咱们很多时候做事情的时候不会考虑与事情本身无关的问题,比如造飞机的不会考虑飞机是否要潜水,对于我们目前很多移动互联网的应用来说,很少会涉及到对操作系统的部分,其实我们主要关心的是应用的本身,而 VM 虚拟机的上层是运行的运行时库和应用,整个虚拟机的空间是非常的庞大,但是容器化技术 Docker 技术的出现后,省去了操作系统这一层,多个容器之间相互隔离且共用了宿主操作系统和运行时库。


所以 Docker 应用容器相对于 VM 有以下几个优点:


  • 启动速度快,容器启动本质就是一个开启一个进程而已,因此都是秒启,而 VM 通常要更久

  • 资源利用率高,一台普通 PC 可以跑成百上千个容器,你跑十个 VM 试试。

  • 性能开销小, VM 通常需要额外的 CPU 和内存来完成 OS 的功能,这一部分占据了额外的资源


所以很多移动互联网的应用或者云计算的后端节点都可以用 Docker 来替换物理机器或者虚拟机。比如腾讯地图的很多后台服务基本上都迁移 Docker 部署了。


3



Docker 是个啥架构?底层又是用的啥技术?


前面说了那么多,始终还是雾里看花。下面就详细介绍一下技术架构,底层又是用的啥技术来实现上述那么多优点的?


Docker 技术架构图:

【干货】分分钟带你看懂Docker


从 Docker 依赖的底层技术来看,Docker 原生态是不能直接在Windows平台上运行的,只支持 Linux 系统,原因是 Docker 依赖 Linux kernel 三项最基本的技术,namespaces 充当隔离的第一级,是对 Docker 容器进行隔离,让容器拥有独立的 hostname,ip,pid,同时确保一个容器中运行一个进程而且不能看到或影响容器外的其它进程;Cgroups 是容器对使用的宿主机资源进行核算并限制的关键功能。


比如 CPU,内存,磁盘等,union FS 主要是对镜像也就是 image 这一块作支持,采用 copy-on-write 技术,让大家可以共用某一层,对于某些差异层的话就可以在差异的内存存储,Libcontainer 是一个库,是对上面这三项技术做一个封装。


Docker engine 用来控制容器 container 的运行,以及镜像文件的拉取。



4



Docker 咋装呢?Docker 怎么用呢?

也可以参照以前的文章《》,现在Docker也支持Win10系统,大家有兴趣也可以就行相关内容的查找!


安装之前,我们首先确保自己的 Linux 系统内核版本高于3.10,并且系统是64位,才能体验 Docker 哦。


通过 uname -ir 查看是否满足要求。

【干货】分分钟带你看懂Docker


1. 安装
Docker 的安装是非常便捷的,在 macOS、ubuntu 等下面都有一键式安装工具或者脚本。更多可以参考 Docker 官方教程[1]。
安装后 Terminal 中敲下 docker,有使用说明出来的话大多情况下说明已经安装成功了。

2. 寻找基础镜像
DockerHub 等网站都提供了众多镜像,一般情况下我们都会从它那找个镜像作为基础镜像,然后再进行我们的后续操作。
这里我们以 Ubuntu 基础镜像为例,配置一个 node 环境。
因为 “链路太长” 的原因,国内访问 Docker Hub 可能会比较慢,可以使用国内众多厂商提供的镜像加速器。
【干货】分分钟带你看懂Docker

3.拉取基础镜像
利用 docker pull 命令即可从相关 hub 网站上拉取镜像到本地。同时在拉的过程中就能看到是按照多个 “层” 去拉镜像的。
> docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
c448d9b1e62f: Pull complete
0277fe36251d: Pull complete
6591defe1cd9: Pull complete
2c321da2a3ae: Pull complete
08d8a7c0ac3c: Pull complete
Digest: sha256:2152a8e6c0d13634c14aef08b6cc74cbc0ad10e4293e53d2118550a52f3064d1
Status: Downloaded newer image for ubuntu:18.04
执行 docker images 即可看到本地所有的镜像。
> docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
ubuntu                   18.04               58c12a55082a        44 hours ago        79MB
4. 创建一个 Docker 容器
docker create 命令通过镜像去创建一个容器,同时吐出容器 ID。
> docker create --name ubuntuContainer ubuntu:18.04
0da83bc6515ea1df100c32cccaddc070199b72263663437b8fe424aadccf4778
用 docker start 即可运行改容器。
> docker start ubuntuContainer
用 docker ps 即可查看运行中的 container。
> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9298a27262da        ubuntu:18.04        "/bin/bash"         4 minutes ago       Up About a minute                       ubuntuContainer
用 docker exec 即可进入该 container。
> docker exec -it 9298
root@9298a27262da:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@9298a27262da:/# exit
用 docker run 可以一步到位创建并运行一个容器,然后进入该容器。
> docker run -it --name runUbuntuContainer ubuntu:18.04 /bin/bash
root@57cdd61d4383:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@57cdd61d4383:/#
# docker ps 可以查到已经成功运行了 runUbuntuContainer
> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
57cdd61d4383        ubuntu:18.04        "/bin/bash"         9 seconds ago       Up 8 seconds                            runUbuntuContainer
9298a27262da        ubuntu:18.04        "/bin/bash"         9 minutes ago       Up 6 minutes                            ubuntuContainer
5. 在容器里安装 Node 环境
进入容器之后一切操作和普通环境一致,我们安装个简单的 node 环境。
> apt-get update
> apt-get install wget
> wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

#
安装完之后可能当前 session 读不到 nvm 命令,可以 exit 之后再进入终端环境
> nvm install 8.0.0
> node -v
6. commit 容器,创建新镜像
和 Ghost 装 Windows 一样,很多时候,我们期望能定制自己的镜像,在里面安装一些基础环境(比如上文中的 node),然后制作出自己要的基础镜像。这个时候 docker commit 就派上用场了。
> docker commit --author "rccoder" --message "curl+node" 9298 rccoder/myworkspace:v1
sha256:68e83119eefa0bfdc8e523ab4d16c8cf76770dbb08bad1e32af1c872735e6f71

#
通过 docker images 就能看到新制作的 rccoder/myworkspace 就躺在这里了
>docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
rccoder/myworkspace      v1              e0d73563fae8        20 seconds ago      196MB
接着,试一下我们新创建的镜像?
> docker run -it --name newWorkSpace rccoder/myworkspace:v1 /bin/bash
root@9109f6985735:/# node -v
8.0.0
看起来没问题。

7. push 镜像到 docker hub
镜像制作好了,怎么共享出去让别人使用呢?这里以 push 到 docker hub 为例。
第一步是先去 docker hub 注册一个账号,然后在终端上登录账号,进行 push。
> docker login
> docker push rccoder/myworkspace:v1
The push refers to repository [docker.io/rccoder/myworkspace]
c0913fec0e19: Pushing [=>                                                 ]  2.783MB/116.7MB
bb1eed35aacf: Mounted from library/ubuntu
5fc1dce434ba: Mounted from library/ubuntu
c4f90a44515b: Mounted from library/ubuntu
a792400561d8: Mounted from library/ubuntu
6a4e481d02df: Waiting
8. 是时候使用 Dockerfile 了
用 Docker 进行持续集成?相比在了解 Docker 之前肯定听过这个事情,那就意外着需要从某个地方拷贝代码,然后执行(对,听上去有点 travis-ci[2] 的那种感觉)。
是时候该 Dockerfile 出场了!
Dockerfile 是一个由一堆命令+参数构成的脚本,使用 docker build 即可执行脚本构建镜像,自动的去做一些事(同类似于travis-ci 中的 .travis.yml)。

Dockerfile 的格式统统为:
# Comment
INSTRUCTION arguments

必须以 FROM BASE_IMAGE 开头指定基础镜像 。这里我们以基于上面的 rccoder/myworkspace:v1 作为基础镜像,然后在根目录创建 a 目录为例。
Dockerfile 如下:
FROM rccoder/myworkspace:v1
RUN mkdir a
然后执行:
> docker build -t newfiledocker:v1 .
Sending build context to Docker daemon  3.584kB
Step 1/2 : FROM rccoder/myworkspace:v1
---> 68e83119eefa
Step 2/2 : RUN mkdir a
---> Running in 1127aff5fbd3
Removing intermediate container 1127aff5fbd3
---> 25a8a5418af0
Successfully built 25a8a5418af0
Successfully tagged newfiledocker:v1

#
新建基于 newfiledocker 的容器并在终端中打开,发现里面已经有 a 文件夹了。
> docker docker run -it newfiledocker:v1 /bin/bash
root@e3bd8ca19ffc:/# ls
a  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
借助 Dockerfile 的能力,Docker 留下了无限的可能。



5


怎么用 Docker 完成持续集成、自动交付、自动部署?

这年头见面不聊点自动化什么的,持续什么的,都不好意思。所以,咱们也要了解一下持续集成,自动交付,自动部署。但是上面说了这么多,没发现 Docker 有那三样功能啊,是的,Docker 是没有这个功能,但是你在完成上述三样自动化的步骤都是依赖 Docker 的。Docker 是这些流程实现的基础,就如同软件开发,软件代码才是根本,开发工具是辅助。所有搭建一个完整的自动化流程还需要 github+jenkins+ registry 三样帮助。


持续集成和自动部署的原理如下图所示:

【干货】分分钟带你看懂Docker


  1. RD 推送代码到 git 仓库或者 svn 等代码服务器上面,git 服务器就会通过 hook通知 jenkins;

  2. jenkine 克隆 git 代码到本地,并通过 dockerFile 文件进行编译;

  3. 打包生成一个新版本的镜像并推送到仓库 ,删除当前容器 ,通过新版本镜像重新运行。


而在整个过程中 RD 只需要敲入三个命令 Git add * ;Git commit –m “”;Git push即可完成持续集成、自动交付、自动部署。后面通过案例实际演示这个过程的神奇!


Docker 还可以很方便的自动扩容哦,一般的自动扩容的两种方式,一种就是Docker 容量扩大,另一种就是 Docker 节点数扩充。第一种就修改配置文件即可,第二种通过简单的拷贝,运行就完成了节点的扩容。




总结


1. 多环境的部署切换
业务开发中往往需要区分开发环境与线上环境,利用 Docker 能原封不动的将开发环境中的 代码与环境原封不动无污染的 迁移到线上环境,配合一定的自动化流程即可实现自动的发布。

2. 前端云构建
因为 node_modules 的蛋疼问题,同一个仓库下不同人开发往往会遇到不同的人使用不同的 包版本 且自己根本不知道与别人不一样,最终导致发布之后产生线上问题。利用 Docker 可以在云端新建容器,远程无污染、低成本构建代码,实现不同人用的一定是同一个版本。

3. 复杂环境一键配置
某些场景下可能会配一些超级复杂的环境(比如:大一同学配 Java 环境),这个时候可以利用 Docker 对环境配置做封装,直接生成镜像,让大家低成本使用。

4. 持续集成单元测试
类似于 travis-ci 这种。

5. 同应用多版本隔离、文件隔离
比如这个项目依赖 node 6,那个项目依赖 node 8(只是举例子,硬盘够大的话还是建议通过 nodeinstall[4] 解决);同一台服务器上跑了 100 个 wordpress 程序(可以用 Docker 建立隔离开,防止互相污染)。

6. 省钱

Docker 虽好,可不要贪杯哦!虽然 Docker 具有超轻量化,但是不建议一台机器上面部署太多的应用,同时部署的时候一定要差异化部署,什么意思呢,就是将大量计算的,和内存需要大的,IO 操作频繁的对系统资源需求不一致的部署到同一台宿主机上。


本文讲述的 Docker 使用只是 Docker 整个使用的非常小的一部分,其中最主要的 Docker 镜像构建,就有很多内容可以学习探索,比如构建镜像需要的 Dockerfile 文件。对于测试和运维,我们只需要懂得如何使用 Docker 即可,怎么制作镜像主要还是由开发来完成。


如果本文有帮助到您,欢迎打赏或转载分享!您的分享就是我的动力!【干货】分分钟带你看懂Docker

——————————————

往期文章







——————————————

每日一技



【每日一技】

以上是关于干货分分钟带你看懂Docker的主要内容,如果未能解决你的问题,请参考以下文章

一分钟带你看懂公有云和私有云的区别

一篇文章带你看懂计算机系统监控与可观测性发展史(干货)

5分钟带你看懂 prettier + eslint 搭配(vscode)

十分钟带你看懂比特币的运行原理

一文带你看懂PaddleHub

还不懂?这里10分钟教你看懂 Docker 和 K8S