Docker 容器概念

不玩虚的, 当然更畅快

docker 与虚拟机(vm)对比:

lark_01_vm_vs_docker

  1. 虚拟机运行在虚拟硬件上, 应用运行在虚拟机内核上。而 docker daemon 是宿主机上的一个进程, 应用只是 docker daemon 的一个子进程, 换句话说, 应用直接运行在宿主机内核上。
  2. 虚拟机需要特殊硬件虚拟化技术支持, 因而只能运行在物理机上。docker 没有硬件虚拟化, 因而可以运行在物理机、虚拟机, 甚至 docker 容器内(嵌套运行)。
  3. 因为没有硬件虚拟化及多运行一个 Linux 内核的开销, 应用运行在 docker 上比虚拟机上更轻、更快。

那么, 使用 docker 和直接在宿主机上运行一个程序有什么区别呢?答案是 docker 容器使用 cgroup 名字空间实现了 CPU, 内存, 网络, 文件系统等资源隔离。了解 chroot 的同学可以认为 docker 就是一个更优雅的 chroot。

说到隔离, docker 容器的文件系统在哪里呢? 答案就是镜像。

docker 镜像

镜像描述了 docker 容器运行的初始文件系统, 包含运行应用所需的所有依赖。即可以是一个完整的操作系统, 也可以仅包含应用所需的最小 bin/lib 文件集合。

一个问题: 假设一个 docker 容器文件系统大小为 10GiB, 创建 10 个容器需要多少磁盘空间?
100 GiB?错,还是只要 10 GiB!因为 docker 镜像和容器采用分层文件系统结构, 每个容器包含一层薄薄的可写层, 只读部分是共享的。

docker 镜像存储引擎有 aufs, devicemapper, overlay 等多种实现, 请看 devicemapper 实现示意图如下:

lark_01_dm_container

镜像是只读的, 创建容器时只是在镜像上面新建一个可写层, 不需要复制整个文件系统, 因而可以实现毫秒级创建。

镜像存储在镜像 hub。每个镜像有一个 tag, 如 registry.hub.docker.com/library/ubuntu:14.04。镜像完整 tag 不仅包含镜像名字, 还指明了镜像从哪里来, 要到哪里去, 就像一个 URL。没错, registry.hub.docker.com 就是官方 docker 镜像 hub 的地址。使用官方 library 镜像时, 可省略前缀, 如以上镜像 tag 可简写为 ubuntu:14.04

docker 为运行应用而生

有了镜像,如何创建容器?docker 不加载 kernel (不同于 vm), 也不执行 init (不同于 vm 和 lxc)。“你不执行应用, 空跑一个 kernel 或者 init 有什么意义?”,docker 说。docker 容器为运行应用而生, 要创建 docker 容器, 必须指定镜像 tag 和启动应用的命令行 (或者镜像设置了默认命令行)。

so, 创建一个 docker 容器的命令行如下:

sudo docker create -ti --name test ubuntu:14.04 bash

这只是创建了容器, 还没有运行, 要运行容器, 执行:

sudo docker start test

通常我们把这两条命令合并成一条, 即 docker run:

sudo docker run -dti --name test ubuntu:14.04 bash

在宿主机上看一下我们刚刚运行的 bash 命令的进程树:

$pstree -sa 21811systemd --switched-root --system --deserialize 21  └─docker daemon ... ...      └─bash

没错, 它只是 docker daemon 的一个子进程.

应用即 docker 主进程

attach 到容器内的应用, 本例中即为 bash 命令行:

sudo docker attach test

ps -ef 看一下:

$sudo docker attach test

root@47c90c3dcbfa:/# ps -efUID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  0 17:05 ?        00:00:00 bashroot        18     1  0 17:11 ?        00:00:00 ps -ef

加上 ps 自己, 容器中只有两个进程。 bash 在容器内 PID 为 1, 即是容器主进程。主进程退出后, 容器即自动退出。还是那句话, 容器为运行应用而生, 应用都退出了, 容器留着还有什么用。

手动停止容器:

sudo docker stop test

删除容器:

sudo docker rm test

注意: 删除容器后在镜像上创建的可写层文件系统也将被删除, 所以日志、配置、数据等需要持久保存的文件需要挂接到外部储存。

docker 有多轻

俗话说前人栽树, 后人乘凉, 我们通常是基于一个已有的镜像创建应用镜像。为了演示镜像有多轻,我们可以从 0 开始创建一个镜像。

创建一个文件夹 hello-lark, 进入文件夹, 添加一个 Dockerfile 内容如下:

FROM scratchCOPY Dockerfile hello.c hello /

Dockerfile 描述如何创建镜像:

  • FROM scratch 表示从 0 开始, 即从一个空白文件系统开始创建镜像。
  • COPY Dockerfile hello.c hello / 表示将本地 Dockerfilehello.chello 3 个文件复制到镜像内根目录下。

hello.c 和 hello 是我们的应用源码及编译后的二进制文件。
添加 hello.c 文件内容如下:

#include <stdio.h>

int main(int argc, char* argv[]) {  printf("Hello, Lark!\n");  return 0;}

静态编译之:

gcc -static hello.c -o hello

执行 docker build 创建镜像:

$sudo docker build -t hello-lark:1.0 .Sending build context to Docker daemon 881.2 kBStep 1 : FROM scratch ---> Step 2 : COPY Dockerfile hello.c hello / ---> b52b3bd2799cRemoving intermediate container bc5dcd332026Successfully built b52b3bd2799c

镜像在本地仓库打包和存储, 不能直接看到实体文件。但是可以导出为一个 tar 包:

sudo docker save -o ../hello-lark.tar hello-lark:1.0

看看有多大:

$ll -h ../hello-lark.tar -rw-r--r-- 1 root root 870K Apr 12 13:41 ../hello-lark.tar

仅有 870K, 差不多就是 hello 这个二进制文件的大小。

docker 有多快

这个镜像能跑吗?我们马上运行看看:

$time sudo docker run --name hello --rm hello-lark:1.0 /helloHello, Lark!

real  0m0.486suser  0m0.078ssys 0m0.016s

可看到, 这条命令一共经历了容器创建、运行、停止、销毁 4 个过程,共耗时不到 0.5 秒。--rm 表示容器结束后自动删除容器。

如果只是创建:

$time sudo docker create --name hello hello-lark:1.0 /hello16449a07a0f1377336a879f8136ec7369e07520da1f4a7516128b8d3ba314008

real  0m0.075suser  0m0.064ssys 0m0.017s

不到 0.1 秒。毫秒级创建绝非虚言。

当然, 只是 hello world 并没有什么用, 我们打一个 busybox 进去, 镜像大小只有 2MB, 然而已经具备一个基本的 linux shell 环境.

sudo docker run -ti --rm lark-box:1.0 sh

docker 的好处

简单说: 标准化交付,微服务编排,提升资源利用率

  1. 校准化交付

    docker 将应用及其所有依赖打包到镜像内, 包括二进制文件(包括底层基础库), 静态配置文件, 环境变量等。剥离了应用对操作系统和环境的依赖, 松耦合 。只需要拉取镜像, 启动容器即可完成应用部署, 方便 。毫秒级创建销毁容器,从而可以实现快速部署、快速迁移、快速扩容缩容,一键快速回滚 (只依赖应用启动时间)。docker 镜像制定了应用交付标准, 开发人员对应用及其运行环境完全可控,并 有效避免各种环境问题踩坑

  2. 微服务编排

    单机部署多应用时,应用之间完全解耦,可以任意部署编排, 完美支持微服务编排的需求。多个 C 应用混布时, docker 化实现 C 依赖隔离, 避免依赖冲突。

  3. 提升资源利用率

    docker 是轻量级的解决方案, 不做虚拟化, 不运行多余的 kernel 和 init 进程, 能有效提升资源利用率。

时间: 2024-09-06 02:26:26

Docker 容器概念的相关文章

Docker Swarm 中最重要的概念- 每天5分钟玩转 Docker 容器技术(94)

从主机的层面来看,Docker Swarm 管理的是 Docker Host 集群.所以先来讨论一个重要的概念 - 集群化(Clustering). 服务器集群由一组网络上相互连接的服务器组成,它们一起协同工作.一个集群和一堆服务器最显著的区别在于: 集群能够像 单个 系统那样工作,同时提供高可用.负载均衡和并行处理. 如果我们部署应用和服务时选择的是多个独立的服务器而非集群,资源的整体利用率则很难达到最优,因为我们无法提前知道如何分布这些应用才能达到资源利用的最大化.而且,应用使用资源的趋势是

初识Docker,概念-架构-相关术语

介绍Docker概念与平台架构,相关术语 Docker的历史 诞生 Docker 是Docker.Inc 公司开源的一个基于 LXC技术之上构建的Container容器引擎,基于Google 公司推出的 Go语言实现的云开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护.而且居然只有 1W 行就完成了这些功能.如果想尝试一下的话可以看 官方介绍了.   D

通过Docker容器运行持续集成/持续部署

本文讲的是通过Docker容器运行持续集成/持续部署,[编者的话] 对于Docker主流的应用场景:持续集成和持续部署(CI/CD)大家也许并不陌生.这篇文章从独特的视角阐述了如何利用各种云平台构建属于自己的CI/CD容器,笔者还自己扩展了Gitlab CI引擎,对CI感兴趣的同学对这个文章应该很感兴趣. 我曾经使用Docker了一段时间,在过去的一年里伴随着众多的Docker容器涌入,帮助用户们更容易的部署Docker容器到生产环境中.一些工具是第三方公司提供,当然也包括Docker公司自己的

Docker 容器内存监控原理及应用_docker

Docker 容器内存监控 linux内存监控 要明白docker容器内存是如何计算的,首先要明白linux中内存的相关概念. 使用free命令可以查看当前内存使用情况. [root@localhost ~]$ free total used free shared buffers cached Mem: 264420684 213853512 50567172 71822688 2095364 175733516 -/+ buffers/cache: 36024632 228396052 Sw

Docker容器配置Nginx实例分享_docker

作为目前最火的应用,Docker 确实存在着其独到之处,无论是程序猿还是运维都应该听说过 Docker 的大名,Docker 已经走过了许多的坑,目前最新版本是 v1.11.0 版本,应该说是完全能承载开发使用和运维监控,这款工具能帮助我们高效的打包.发布和运行承载着应用程序的容器系统.而且收集日志.帮助 App 的快速开发都有很大作用. 容器和虚拟机,经常是被拿出来对比的两款产品,实际上两者有着根本的差别,虚拟机是完全模拟了一台真实计算机,在上面运行的系统可能或者不可能知道自己运行在虚拟化环境

【实战】Docker容器资源管理

本文讲的是[实战]Docker容器资源管理,[编者的话]本文作者是Red Hat的软件工程师 - Marek Goldmann,这篇文章详细介绍了Docker容器的资源管理,总共分了三大部分:CPU.内存以及磁盘IO.作者通过实践举例给读者勾勒出一幅清晰明了的Docker资源管理的画卷. 在这篇博客文章中,我想谈谈Docker容器资源管理的话题.我们往往不清楚它是怎样工作的以及我们能做什么不能做什么.我希望你读完这篇博客文章之后,可以帮助你更容易理解有关Docker资源管理的内容. 注意:我们假

初识docker—容器连接

连接容器 在使用 Docker 部分, 我们谈到了如何通过网络端口来访问运行在 Docker 容器内的服务.这是与docker容器内运行应用程序交互的一种方法.在本节中,我们打算通过端口连接到一个docker容器,并向您介绍容器连接概念. 网络端口映射 在使用docker部分,我们创建了一个python应用的容器. $ sudo docker run -d -P training/webapp python app.py 注:容器有一个内部网络和IP地址(在使用Docker部分我们使用docke

10张图带你深入理解Docker容器和镜像

本文讲的是10张图带你深入理解Docker容器和镜像,[编者的话]本文用图文并茂的方式介绍了容器.镜像的区别和Docker每个命令后面的技术细节,能够很好的帮助读者深入理解Docker. 这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(container)和镜像(image)之间的区别,并深入探讨容器和运行中的容器之间的区别. 当我对Docker技术还是一知半解的时候,我发现理解Docker的命令非常困难.于是,我花了几周的时间来学习Docker的工作原理,更确切地说,是关于Doc

微容器:更小的,更轻便的Docker容器

本文讲的是微容器:更小的,更轻便的Docker容器,[编者的话]本文介绍了微容器的概念和好处,并用一些例子介绍了如何构建微镜像,从scratch到Alpine Linux,并推荐了一些已有的基础微镜像,方便为几乎所有主流语言的应用构建微镜像.本文也指出了构建微镜像的基本原理:将构建时依赖和运行时依赖分开,构建时所用的镜像包含所有构建所用的工具,它可以比较大,但运行时的基础镜像应该仅包含运行时依赖.使用微容器,no going back! Docker 使你能把你的应用和应用的依赖打包到一个良好的