系列文章介绍
本文是《Docker必知必会系列》第一篇,原文发布于个人博客:悟尘纪。
此系列文章共包括如下章节:
- 一、Docker基础入门及架构介绍
- 二、基于 Dockerfile 构建并运行镜像
- 三、基于 Docker-registry/Nexus3 搭建本地仓库
- 四、Docker 网络原理、分类及容器互联配置
- 五、Docker 数据持久化存储与性能调优
- 六、基于多阶段构建减小镜像体积降低复杂度
- 七、Docker Compose 入门实践
- 八、Kubernetes 入门实践
- 附录1、Docker 常用命令及示例
- 附录2、Dockerfile 参考及最佳实践
- 附录3、Docker-compose 命令使用指南
- 附录4、Docker-compose 配置文件编写
部分内容翻译自 Docker官方文档 或参考 《Docker — 从入门到实践》,非常感谢原作者。
一、Docker 概述
Docker是供开发人员和系统管理员 使用容器构建,运行和共享应用程序的平台。使用容器来部署应用程序称为容器化。
Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的快速交付,测试和部署代码的方法,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
容器化越来越受欢迎,是因为容器:
- 灵活:即使最复杂的应用程序也可以容器化。
- 轻量级:容器利用并共享主机内核,在系统资源方面比虚拟机更加有效。
- 可移植性:可以在本地构建,部署到云并在任何地方运行。
- 松散耦合:容器高度封装并自给自足,可以在不破坏其他容器的情况下更换或升级它们。
- 可扩展:可以方便的在数据中心内增加并自动分发容器副本。
- 安全:容器将积极的约束和隔离应用于流程,而无需用户方面的任何配置。
镜像(Image)和容器(Container)
从根本上讲,一个容器不过是一个正在运行的进程,并对其应用了一些附加的封装功能,以使其与主机和其他容器隔离。容器隔离的最重要方面之一是每个容器都与自己的专用文件系统进行交互。该文件系统由Docker 镜像提供。镜像包括运行应用程序所需的一切:代码或二进制文件、运行时、依赖项以及所需的任何其他文件系统对象。
容器与虚拟机
容器在 Linux 本机上运行,并与其他容器共享主机的内核。它运行一个离散的进程,占用的内存不比任何其他可执行文件多,从而使其轻巧。
相比之下,虚拟机(VM)运行一个完整的 ”Guest操作系统“,通过虚拟机监控程序对主机资源进行虚拟访问。一般来说,VM 除了应用程序逻辑所消耗的开销之外,还会产生很多开销。
我可以将 Docker 用于什么
快速,一致地交付您的应用程序
Docker 通过允许开发人员使用容器让应用程序和服务在本地标准化环境中工作,从而简化了开发生命周期。容器非常适合持续集成和持续交付(CI / CD)工作流程。
响应式部署和扩展
Docker 容器可以在开发人员的本地笔记本电脑上,数据中心中的物理或虚拟机上,云提供商上或混合环境中运行。其可移植和轻量级的特性还使您可以轻松地动态管理工作负载,并根据业务需求指示实时扩展或关闭应用程序和服务。
在同一硬件上运行更多工作负载
Docker 轻巧快速。它相对于虚拟机提供了可行且经济高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合高密度环境和中小型部署,让您可以用更少的资源做更多的事情。
二、Docker 安装及运行
1、获取 Docker
Docker 分为 CE 和 EE 两大版本。Docker CE 分为 stable
、 test
和 nightly
三个更新频道。官方网站上有各种环境下的 安装指南,可以根据自己的情况进行安装。
2、镜像加速
一般国内在使用过程中拉取 Docker 镜像十分缓慢,可以配置 Docker 国内镜像加速。各个免费镜像站测试结果可到 docker-practice/docker-registry-cn-mirror-test 查看。推荐使用阿里云免费镜像加速器(需登录),稳定可靠。
对于使用 macOS 的用户,在任务栏点击 Docker Desktop 应用图标 -> Perferences
,在左侧导航菜单选择 Docker Engine
,在右侧参考如下内容编辑 json 文件(记得修改成您选择的加速地址):
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
修改完成之后,点击 Apply & Restart
按钮,Docker 就会重启并应用配置的镜像。执行 $ docker info
,如果从结果中看到了如下内容,说明配置成功。
Registry Mirrors:
https://xxxxxx.mirror.aliyuncs.com
3、小试牛刀
以下命令运行一个ubuntu
容器,以交互方式附加到本地命令行会话,然后运行/bin/bash
。
docker run -i -t ubuntu /bin/bash
当您运行此命令时,会发生以下情况(假设您使用的是默认仓库配置):
- 如果您在
ubuntu
本地没有该镜像,则 Docker 会将其从已配置的仓库中拉出,就像您已docker pull ubuntu
手动运行一样。 - Docker 会创建一个新容器,就像您通过
docker container create
命令手动运行一样。 - Docker 将一个可读写的文件系统分配给容器,作为其最后一层。这允许运行中的容器在其本地文件系统中创建或修改文件和目录。
- Docker 创建了一个网络接口以将容器连接到默认网络,因为您未指定任何网络选项。默认情况下,容器可以使用主机的网络连接到外部网络。
- Docker 启动容器并执行
/bin/bash
。因为容器是交互式运行的,并且已附加到您的终端(由于-i
和-t
标志),所以您可以在终端进行交互操作并查看日志。 - 当您键入
exit
以终止/bin/bash
命令时,容器将停止但不会被删除。您可以重新启动或删除它。
三、Docker 架构介绍
Docker 使用客户端-服务器架构。Docker 客户端(client
) 与 守护进程(Docker daemon
) 进行对话,该守护进程 完成了构建、运行和分发 Docker 容器的繁重工作。Docker 客户端和守护进程可以在同一系统上运行,或者您可以将 Docker 客户端连接到远程 Docker 守护进程。Docker 客户端和守护进程在 UNIX 套接字或网络接口上使用 REST API 进行通信。
Docker 守护进程
Docker 守护进程(dockerd
)侦听 Docker API 请求并管理 Docker 对象,例如 images(镜像),containers(容器),networks(网络)和 volume(卷)。守护进程还可以与其他守护进程通信以管理 Docker 服务。
Docker 客户端
Docker 客户端(docker
)是许多 Docker 用户与 Docker 交互的主要方式。当您使用诸如docker run
之类的命令时,客户端会将这些命令发送到 dockerd
,以执行这些命令。该docker
命令使用 Docker API。Docker 客户端可以与多个守护进程通信。
Docker 仓库
Docker 仓库存储 Docker 镜像。Docker Hub 是任何人都可以使用的官方公共仓库,并且 Docker 配置为默认在 Docker Hub 上查找镜像。您甚至可以运行自己的私人仓库。如果使用 Docker 数据中心(DDC),则其中包括 Docker 可信仓库(DTR)。
使用 docker pull
或 docker run
命令时,所需的镜像将从配置的仓库中提取。使用 docker push
命令时,会将镜像推送到配置的仓库。
Docker 对象
使用 Docker 时,您正在创建和使用镜像(Image),容器(Container),网络(Network),卷(Volume),插件(Plugin)和其他对象。本节是其中一些对象的简要概述。
Images(镜像)
镜像是一个只读模板(不包含任何动态数据,其内容在构建之后也不会被改变 ),其中包含创建 Docker 容器的说明。通常,一个镜像基于另一个镜像,并带有一些额外的配置。 例如,你可以建立一个基于 ubuntu 镜像的镜像,安装 ubuntu Apache HTTP Server 和你的应用程序,以及运行你的应用程序所需的配置细节。
您可以创建自己的镜像,也可以仅使用其他人创建并在仓库中发布的镜像。要构建自己的镜像,您可以使用简单的语法创建一个 Dockerfile
,以定义创建镜像并运行它所需的步骤。Dockerfile
中的每条指令都会在镜像中创建一个层。更改 Dockerfile
并重建镜像时,仅重建那些已更改的层。与其他虚拟化技术相比,这是使镜像如此轻巧,小型和快速的部分原因。
Containers (容器)
容器是镜像的可运行实例。您可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。您可以将容器连接到一个或多个网络,将存储附加到该网络,甚至根据其当前状态创建新镜像。
默认情况下,容器与其他容器及其主机之间的隔离程度相对较高。您可以控制容器的网络、存储或其他基础子系统与其他容器或与主机的隔离程度。
容器由其镜像以及在创建或启动时为其提供的任何配置选项定义。删除容器后,未存储在持久性存储中的状态更改将消失。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 Volume(数据卷)、或者挂载宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)进行读写,其性能和稳定性更高。
Service (服务)
服务允许跨多个 Docker 守护进程调度容器,这些守护进程以多个管理者和工作者的集群模式协同工作。集群的每个成员都是一个 Docker 守护进程,并且所有守护进程都使用 Docker API 进行通信。
服务允许您定义所需的状态,例如在任何给定时间必须可用的服务副本数。默认情况下,该服务在所有工作节点之间实现负载平衡。对于使用者而言,Docker 服务似乎是一个单独的应用程序。Docker Engine 在 Docker 1.12 及更高版本中支持集群模式。
四、Docker 底层技术
Docker用Go编写,并利用Linux内核的多个功能来交付其功能。底层核心技术包括命名空间(Namespaces)、控制组(Control groups)、Union 文件系统(Union file systems)和容器格式(Container format)。
命名空间(namespaces)
Docker使用一种称为 namespaces
的技术来提供称之为容器的隔离工作区。运行容器时,Docker会为该容器创建一组命名空间。通过命名空间隔离容器之间彼此不受影响,且其访问权限也仅限于该命名空间。
Docker Engine 在Linux 上使用以下命名空间:
- **
pid
命名空间:**进程隔离(PID:Process ID)。 - **
net
命名空间:**管理网络接口(NET:Networking)。 - **
ipc
命名空间:**管理对IPC资源的访问(IPC:InterProcess Communication)。 - **
mnt
命名空间:**管理文件系统挂载点(MNT:Mount)。 - **
uts
命名空间:**隔离内核和版本标识符。(UTS:Unix Timesharing System)。
控制组(cgroups)
Linux上的 Docker 引擎依赖一种称为控制组 (cgroups
)的技术。控制组为应用程序限制一组特定的资源。控制组允许Docker Engine将可用的硬件资源共享给容器,并有选择地实施限制和约束。例如,可以限制特定容器可用的内存。
CGroups 全称control group,用来限定一个进程的资源使用,由Linux 内核支持,可以限制和隔离Linux进程组 (process groups) 所使用的物理资源 ,比如cpu,内存,磁盘和网络IO,是Linux container技术的物理基础。
联合文件系统(UnionFS)
UnionFS文件系统,是通过创建层来操作的文件系统,这使得它们非常轻量级和快速。 Docker Engine 使用 UnionFS
为容器提供分层构建块。 Docker Engine 可以使用多个 UnionFS
变体,包括 AUFS
、 btrfs
、 vfs
和 DeviceMapper
。
Union File System,简称UnionFS,他是一种为Linux 、FreeBSD 和NetBSD 操作系统设计的,把其他文件系统联合到一个联合挂载点的文件系统服务。
容器格式(Container format)
Docker Engine 将namespaces
、cgroups
和 UnionFS
组合成一个称为容器格式的包装器。 默认的容器格式是 libcontainer
。