Docker是一个用于开发、打包、运行应用的开放平台。Docker使得我们能够将我们的应用从基础设施中分离出来。基础设施就是指的服务器等基础硬件设施,怎么理解分离呢?就像Java一样,我们写的Java程序可以借助Java虚拟机实现一次编写、处处运行。而对于Docker,则可以实现一次构建,处处运行。
通过使用Docker,我们可以像管理我们的应用一样管理基础设施,可以快速完成代码的打包、测试、部署,从而显著缩短编写代码和交付到生产环境的周期。
Docker平台
Docker提供了在被称为容器的松散隔离环境中打包并运行应用的能力。Docker提供的隔离性和安全性使得在一个主机上可以同时运行多个容器。容器是轻量级的,并且包含运行应用所需要的所有东西,所以不需要依赖于当前主机上安装的东西,因此也就实现了将应用与基础设施分离的功能。我们工作时可以很轻松的分享镜像,需要注意的是:要确保每个使用这个镜像的人都按相同的方法使用。
Docker提供了工具和平台来管理容器的生命周期:
我们可以用Docker做什么?
快速、一致的交付我们的应用
Docker简化了开发的生命周期,允许开发者在标准化的环境中使用本地容器来提供应用程序和服务。容器对于持续集成和持续交付(CI/CD)工作流非常有用。
考虑下面的案例场景:
响应式部署和扩展
Docker基于容器的平台允许高度可移植的工作负载。Docker容器可以运行在开发者的本地电脑,可以运行在数据中心的物理主机或虚拟主机,或者混合环境中。
Docker天然的可移植性和轻量级特性使得动态管理工作负载非常容易,可以根据业务需要,几乎实时性的对应用和服务进行扩展和缩减。
在相同的硬件上运行更多的工作负载
Docker是轻量级和快速的。它为基于管理程序的虚拟机提供了一套可行的、经济划算的替代方案,因此,我们可以使用更多的计算能力来实现我们的业务目标。Docker非常适合高密度环境和中小型部署,使用Docker,我们可以使用更少的资源做更多的事。
Docker架构
Docker使用客户端/服务端架构(也就是B/S架构)。Docker客户端向Docker守护进程下达指令,守护进程完成构建、运行和分发容器的繁重工作。Docker客户端和守护进程可以运行在同一个操作系统上,或者也可以使用Docker客户端连接到远程的守护进程。Docker客户端和守护进程使用REST API通过unix套接字或网络接口进行通信。另一种Docker客户端是Docker compose,它可以实现一组容器在一起工作。
Docker守护进程(dockerd)
Docker守护进程监听Docker API请求并管理镜像、容器、网络、卷等Doker对象。一个守护进程也可以和其他守护进程进行通信来管理Docker服务。
Docker客户端(docker)
Docker客户端是Docker用户与Docker进行交互的主要途径。当使用像 docker run 这样的Docker命令时,Docker客户端将命令发给守护进程,守护进程执行收到的命令。实际上,Docker客户端命令就是调用的Docker API,一个Docker客户端可以与多个守护进程进行通信。
Docker仓库(registry)
Docker仓库是用来存储镜像的。Docker Hub是一个所有人都可以使用的公共仓库,Docker默认是去Docker Hub上查找镜像的。用户也可以搭建自己的私有仓库(例如使用Harbor、JFrog等仓库管理工具)。
Docker对象
当使用Docker的时候,实际上就在创建和使用Docker对象,例如:镜像、容器、网络、卷、插件等对象。这一节主要简要介绍Docker的这些对象。
镜像
镜像是一个只读的模板,它包含创建一个容器的说明。通常,一个镜像是基于其他镜像的,并进行一些额外的定制。例如:我们可以基于ubuntu来构建一个镜像,在这个镜像里安装Apache服务器和我们自己的应用,然后进行一些配置来确保应用可以运行。
我们可能使用自己构建的镜像,也可能仅仅使用别人发布在仓库里的镜像。要构建自己的镜像,需要使用简单的语法来创建Dockerfile文件,在这个文件里定义创建镜像和运行镜像的步骤。Dockerfile文件里的每个指令都会给镜像创建一个层。当修改了Dockerfile并重新构建镜像时,只有那些改变的层才会被重新构建。与其他虚拟化技术相比,这是使镜像如此轻量级、小型和快速的部分原因。
容器
容器是镜像的可运行实例。我们可以使用Docker API或CLI命令来创建、启动、运行、移动、删除容器。我们可以将一个容器连接到一个或多个网络,可以给容器附加存储,甚至可以基于容器当前的状态创建一个新的镜像。
默认情况下,一个容器和其他的容器以及它所在的主机是相对隔离的。我们可以控制容器的网络、存储以及底层子系统与其他容器以及它所在的主机的隔离程度。
容器由它的镜像以及在创建或启动它时提供给它的任何配置选项定义。当容器被删除后,任何没有存储在持久化存储中的对于容器状态的修改将会消失。
docker run命令使用案例:
下面的命令运行了一个Ubuntu容器,附加了交互到本地命令行会话,然后运行了/bin/bash。
docker run -i -t ubuntu /bin/bash
当运行这个命令时,将发生下面的情况(假设使用的是默认的镜像仓库配置)。
底层技术
Docker是使用Go语言编写的,它使用了Linux内核的一些特性来实现它的功能。Docker使用了一种叫做名称空间(namespaces)的技术来实现容器之间的隔离,当运行一个容器时,Docker就会为这个容器创建一组的名称空间。
这些名称空间提供了一个隔离层,容器的每一层运行在独立的名称空间中,并且访问权限也仅限于那一层名称空间。