Docker 工作原理及容器化简易指南

Docker 非常棒! 它使软件开发者无需担心配置和依赖性,在任何地方打包,发送和运行他们的应用程序。而在与 kubernetes 相结合后,它使应用集群部署和管理变得更方便。这使得 Docker 深受软件开发者的喜爱,越来越多的开发者开始使用 Docker。

那么 Docker 到底是什么?

它是构建、测试、部署和发布容器化应用的平台。称其为平台是因为 Docker 其实是一套用于管理与容器相关的所有事物的工具。作为 Docker 的核心,接下来我们将深入探讨容器。

什么是容器?

容器提供了在计算机上的隔离环境中安装和运行应用程序的方法。在容器内运行的应用程序仅可使用于为该容器分配的资源,例如:CPU,内存,磁盘,进程空间,用户,网络,卷等。在使用有限的容器资源的同时,并不与其他容器冲突。您可以将容器视为简易计算机上运行应用程序的隔离沙箱。

这个概念听起来很熟悉,有些类似于虚拟机。但它们有一个关键的区别:容器使用的一种非常不同的,轻量的技术来实现资源隔离。容器利用了底层 Linux 内核的功能,而不是虚拟机采用的 hypervisor 的方法。换句话说,容器调用 Linux 命令来分配和隔离出一组资源,然后在此空间中运行您的应用程序。

虚拟机与容器的区别

开始之前,我们来做一些基础知识的储备:

1.虚拟机:虚拟化硬件
虚拟机 Virtual Machine 指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。在实体计算机中能够完成的工作在虚拟机中都能够实现。

在计算机中创建虚拟机时,需要将实体机的部分硬盘和内存容量作为虚拟机的硬盘和内存容量。每个虚拟机都有独立的 CMOS、硬盘和操作系统,可以像使用实体机一样对虚拟机进行操作。在容器技术之前,业界的网红是虚拟机。

虚拟机技术的代表,是 VMWare 和 OpenStack。更多请参看百科虚拟机

2.容器:将操作系统层虚拟化,是一个标准的软件单元

  • 随处运行:容器可以将代码与配置文件和相关依赖库进行打包,从而确保在任何环境下的运行都是一致的。
  • 高资源利用率:容器提供进程级的隔离,因此可以更加精细地设置 CPU 和内存的使用率,进而更好地利用服务器的计算资源。
  • 快速扩展:每个容器都可作为单独的进程予以运行,并且可以共享底层操作系统的系统资源,这样一来可以加快容器的启动和停止效率。

3.区别与联系

  • 虚拟机虽然可以隔离出很多「子电脑」,但占用空间更大,启动更慢。虚拟机软件可能还要花钱,例如VMWare
  • 容器技术不需要虚拟出整个操作系统,只需要虚拟一个小规模的环境,类似「沙箱」;
  • 运行空间,虚拟机一般要几 GB 到 几十 GB 的空间,而容器只需要 MB 级甚至 KB 级;

我们来看一下对比数据:

特性虚拟机容器
隔离级别操作系统级进程
隔离策略Hypervisor(虚拟机监控器)Cgroups(控制组群)
系统资源5 ~ 15%0 ~ 5%
启动时间分钟级秒级
镜像存储GB - TBKB - MB
集群规模上百上万
高可用策略备份、容灾、迁移弹性、负载、动态

与虚拟机相比,容器更轻量且速度更快,因为它利用了 Linux 底层操作系统在隔离的环境中运行。虚拟机的 Hypervisor 创建了一个非常牢固的边界,以防止应用程序突破它,而容器的边界不那么强大。

物理机部署不能充分利用资源,造成资源浪费。虚拟机方式部署,虚拟机本身会占用大量资源,导致资源浪费,另外虚拟机性能也很差。而容器化部署比较灵活,且轻量级,性能较好。

我们快速来看下两个这样的功能:

Namespaces

简单的讲就是,Linux namespace 允许用户在独立进程之间隔离 CPU 等资源。进程的访问权限及可见性仅限于其所在的 Namespaces 。因此,用户无需担心在一个 Namespace 内运行的进程与在另一个 Namespace 内运行的进程冲突。甚至可以同一台机器上的不同容器中运行具有相同 PID 的进程。同样的,两个不同容器中的应用程序可以使用相同的端口。

Cgroups

Cgroups 允许对可用资源设置限制和约束。例如,您可以在一台拥有 16 G 内存的计算机上创建一个 Namespace ,限制其内部进程可用内存为 1 GB。

到这,您可能已经猜到 Docker 的工作原理了。当您请求 Docker 运行容器时,Docker 会在您的计算机上设置一个资源隔离的环境。然后 Docker 会将打包的应用程序和关联的文件复制到 Namespace 内的文件系统中,此时环境的配置就完成了。之后 Docker 会执行您指定的命令运行应用程序。

简而言之,Docker 通过使用 Linux namespace 和 cgroup(以及其他一些命令)来协调配置容器,将应用程序文件复制到为容器分配的磁盘,然后运行启动命令。Docker 还附带了许多其他用于管理容器的工具,例如:列出正在运行的容器,停止容器,发布容器镜像等许多其他工具。

 

docker containers
与虚拟机相比,容器更轻量且速度更快,因为它利用了 Linux 底层操作系统在隔离的环境中运行。虚拟机的 hypervisor 创建了一个非常牢固的边界,以防止应用程序突破它,而容器的边界不那么强大。另一个区别是,由于 Namespace 和 Cgroups 功能仅在 Linux 上可用,因此容器无法在其他操作系统上运行。此时您可能想知道 Docker 如何在 macOS 或 Windows 上运行? Docker 实际上使用了一个技巧,并在非 Linux 操作系统上安装 Linux 虚拟机,然后在虚拟机内运行容器。


让我们利用目前为止学到的所有内容,从头开始创建和运行 Docker 容器。如果你还没有将 Docker 安装在你的机器上,可以参考这里安装 Docker 。在这个示例中,我们将创建一个 Docker 容器,下载一个用 C语言写的 Web 服务,编译并运行它,然后使用浏览器访问这个 Web 服务。

我们将从所有 Docker 项目开始的地方从创建一个 Dockerfile 开始。此文件描述了如何创建用于运行容器的 Docker 镜像。既然我们还没有聊到镜像,那么让我们看一下镜像的官方定义

镜像是一个可执行包,其包含运行应用程序所需的代码、运行时、库、环境变量和配置文件,容器是镜像的运行时实例。

简单的讲,当你要求 Docker 运行一个容器时,你必须给它一个包含如下内容的镜像:

  1. 包含应用程序及其所有依赖的文件系统快照
  2. 容器启动时的运行命令。


在 Docker 的世界,使用别人的镜像作为基础镜像来创建自己的镜像是十分普遍的。例如,官方 reds Docker 镜像就是基于 Debian 文件系统快照(rootfs tarball),并安装在其上配置 Redis。

在我们的示例中,我们选择 Alpine Linux 为基础镜像。当您在 Docker 中看到 “alpine” 时,它通常意味着一个精简的基本镜像。 Alpine Linux 镜像大小只有约为5 MB!

在您的计算机创建一个新目录(例如 dockerprj),然后新建一个 Dockerfile 文件。

umermansoor:dockerprj$ touch Dockerfile


将如下内容粘贴到 Dockerfile

# Use Alpine Linux rootfs tarball to base our image on
FROM alpine:3.9 

# Set the working directory to be '/home'
WORKDIR '/home'

# Setup our application on container's file system
RUN wget http://www.cs.cmu.edu/afs/cs/academic/class/15213-s00/www/class28/tiny.c \
&& apk add build-base \
&& gcc tiny.c -o tiny \
&& echo 'Hello World' >> index.html

# Start the web server. This is container's entry point
CMD ["./tiny", "8082"]

# Expose port 8082
EXPOSE 8082 


这个 Dockerfile 包含创建镜像的内容说明。我们创建镜像基于 Alpine Linux(rootfs tarball),并将工作目录设置为 /home 。接下来下载,编译并创建了一个用 C 编写的简单 Web 服务器的可执行文件,然后指定在运行容器时要执行的命令,并将容器端口 8082 暴露给主机。

现在,我们就可以构建镜像了。在 Dockerfile 的同级目录运行 docker build 命令:

umermansoor:dockerprj$ docker build -t codeahoydocker .


如果这个命令成功了,您将看到:

Successfully tagged codeahoydocker:latest


此时我们的镜像就创建成功了,该镜像主要包括:

  1. 文件系统快照(Alpine Linux 和 我们安装的 Web 服务)
  2. 启动命令(./tiny 8092

image

 


既然成功构建了镜像,那么我们可以使用如下命令运行容器。

umermansoor:dockerprj$ docker run -p 8082:8082 codeahoydocker:latest


让我们了解下这里发生了什么。

通过 docker run 命令,我们请求 Docker 基于 codeahoydocker:latest 镜像创建和启动一个容器。-p 8082:8082 将本地的 8082 端口映射到容器的 8082 端口(容器内的 Web 服务器正在监听 8082 端口上的连接)。打开你的浏览器并访问 localhost:8082/index.html 。你将可以看到 Hello World 信息。

 

tiny-container
最后我想补充一点,虽然 Docker 非常棒,而且对于大多数项目来说它是一个不错的选择,但我们并非处处都要使用它。在我的工作中,Docker 与 Kubernetes 结合使用,可以非常轻松地部署和管理后端微服务,我们不必为每个服务配置新的运行环境。另一方面,对于性能密集型应用程序,Docker 可能不是最佳选择。我经手的其中一个项目必须处理来自移动游戏客户端的 TCP 长连接(每台机器1000个),这时 Docker 网络出现了很多问题,导致无法将它用于该项目。

希望上面这些内容有用。

这篇文章由  Umer Mansoor 撰写,可以在  Facebook 或  Twitter 上关注并留下评论。

原文链接:What Are Containers? A Simple Guide to Containerization and How Docker Works(翻译:郭旭东)

http://dockone.io/article/8788

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值