镜像、容器、镜像仓库是 Docker 中最核心的三个概念,组成了 Docker 的整个生命周期。
(镜像、容器、镜像仓库三者运行关系)
1、镜像
镜像是 Docker 的核心元素质疑,作为容器运行的基础,Docker Hub 官网提供了庞大的镜像库,便于使用者下载使用。在运行容器之前,必须在本地拥有相应的镜像。如果本地镜像不存在,系统将从默认的镜像仓库中下载,通过是 Docker Hub 公共服务器,也可以切换到国内或者公司搭建的仓库。但是因为网络等因素,直接从官网拉取镜像会比较慢,可以通过国内的代理进行加速。当今主流的云服务提供商都可以提供镜像仓库服务,我一直比较经常使用的是阿里云的仓库。
在拉取镜像的时候,只要给出镜像的名字和标签就可以从官方仓库中找到对应的镜像。其中命令格式如下:
docker image pull <repository>:<tag>
但是在拉取的过程中,要注意:
- 没有在仓库名称侯指定 tag,则默认拉全 latest 的镜像
- 从第三方或者自建的私有仓库拉取镜像,是需要按照下面的命令来拉取
docker pull registry.cn-alibaba.aliyun.com/image:tag1
docker pull 192.196.163.66:8080/image
接下来我们看镜像创建的方法:
- 基于已有的容器进行镜像创建,使用 commit
- 基于本地的模板导入镜像,使用 import
- 基于 Dockerfile 创建镜像,使用 build
但是一般在我们实际研发的过程中,都是使用 Dockerfile 的方式来创建镜像。
Dockerfile 是一个文本格式的配置文件,它用给定的指令描述了基于一个父镜像创建新镜像的过程。关于 Dockerfile 的具体格式这里就不再赘述了,各位可以自行查阅相关教程。
2、容器
容器是镜像的运行实例,但是它本身与镜像是不同的,容器有着额外的可写层。相比于虚拟机,容器更快、更加轻量级,都是共享所在宿主机的操作系统和内核,而不是运行在一个完整的操作系统上。
可以将 Docker 容器视为独立运行的一个或者一组应用,以及它们所需要的运行环境。就像从虚拟机模板启动虚拟机一样,用户也可以从单个镜像启动一个或者多个容器。实际上,一个容器实例就是宿主机上的一个独立进程。每次执行 docker run 命令,都会创建一个 Docker 容器进程,它具有独立的文件系统、网络和进程树。用 docker ps 和 docker container ls 命令是可以查询正在运行的容器的。
那容器应该怎么创建呢?一般有两种创建方式:
- 用 docker container run 命令
- 用 docker container create 命令
两种创建方式的区别在于,用 create 命令创建的容器是停止的状态,需要用 docker container start 命令来启动容器。
Docker 容器启动参数
容器是整个 Docker 技术的核心,create 和 run 命令支持的选项又都十分复杂,每个选项都有特定的应用场景和用途,是需要使用者不断地学习和实践的,一般选项包括以下几类,这里我就不多做详细的参数介绍,各位可自行查阅相关资料。
- 容器运行模式相关的选项
- 容器环境配置相关的选项
- 容器资源限制和安全保护相关的选项
Docker 容器的 CPU、内容资源的限制
使用 Docker 运行容器时,默认情况下未对容器进行硬件资源限制。然而,当在一台主机上运行数百个容器时,尽管它们相互隔离,但却共享相同的 CPU、内存和磁盘资源。若不限制容器资源使用,可能导致容器之间相互干扰,造成资源不公平分配,甚至使主机和集群资源耗尽,导致服务不可用。
作为容器的管理者,Docker 提供了资源控制功能。类似于使用内核的 namespace 实现容器间的隔离,Docker 通过内核的 cgroups 实现容器的资源限制,包括 CPU、内存和磁盘。这些功能基本涵盖了常见的资源配额和使用量控制。
在 Linux 系统上,Docker 通过内存控制避免内存异常(OOM Exception)。当内核检测到宿主机内存不足时,会引发 OOM Exception,并启动 killing 进程以终止某些进程。为了确保 Docker 守护进程不会被终止,Docker 调整了其 OOM_Odj 优先级,但未调整容器的优先级。系统中的每个进程都有一个 OOM_Score 得分,较高的 OOM_Odj 优先级对应较高的 OOM_Score 得分,系统会优先终止 OOM_Score 最高的进程。在启动容器时,可以通过指定参数 --oom-kill-disable=true 禁止特定重要容器被 OOM Exception 终止。
进入运行中的 Docker 容器
创建并启动容器的时候,一般都会加上 -d 的参数,这样容器启动后就会进入后台,用户无法看到容器中的信息,也无法进行操作,但是可以通过 docker exec 命令进入容器中查看容器运行情况或者执行某种操作行为。
容器端口映射
除了通过网络访问,Docker 还可以提供两个比较便捷的功能来满足服务访问的基本需求:
- 允许映射容器内应用的服务端口到本地宿主机
- 通过互联机制实现多个容器间通过容器名来快捷访问
在启动容器的时候,如果不指定对应参数,在容器外部都是无法通用网络来访问容器内的网络应用和服务的。如果容器中运行的一些网络应用或者服务都需要让外部能够访问,一般在会在启动参数中加上 -p 来指定端口映射,这样就可以实现外部访问容器内指定的端口。关于端口映射可以用 docker ps 或者 docker port 来查看端口映射信息。
容器之间互相访问
容器的互联是一种让多个容器中应用进行快速交互的方式,会在源容器和接收容器之间建立连接关系。接收容器可以通过容器名快速访问到源容器,而不用指定具体的 IP 地址,用 --link 参数可以让容器之间安全地进行交互。
3、镜像仓库
镜像仓库是存放镜像的中心,Docker 通过注册服务器来管理多个仓库,每个仓库包含多个镜像,每个镜像有不同的标签。仓库分为公有和私有,Docker Hub 是官方维护的公有仓库,拥有超过 10 万个镜像。用户可免费使用公有仓库或购买私有仓库。
为加快下载速度,可配置镜像加速器,常选用国内云服务商提供的镜像仓库服务。以阿里云为例,需注册账号,登录后在弹性计算→容器镜像服务→镜像加速器处获取加速器地址,并配置 Docker daemon 文件后重启 Docker 服务。
为了加速镜像下载,一般会配置镜像加速器。上传到 Docker Hub 的镜像可以被任何人访问,虽然可以用私有仓库,但不是免费的,或者某些项目环境无法访问互联网,所以我们有时需要搭建本地仓库来管理自己的私有镜像仓库。本地仓库的安装非常简单,Docker 已经将仓库开源了,我们直接下载安装即可。