Docker 镜像(Image)与仓库(Repository)基础

 2017年02月03日    6089     声明


镜像(Image)是构建容器的基础,镜像是一种分层结构的文件系统。我们可以从仓库(Repository)中下载镜像,而仓库又保存在Registry中,Docker Hub是Docker官方提供的Registry。即可以从Docker Hub顶层仓库中免费获取官方提供的基于镜像,又可以将自已构建的镜像存放于Docker Hub用户仓库中。

  1. 什么Docker镜像
  2. 镜像(Image)的基础操作
  3. 仓库(Repository)介绍

1. 什么Docker镜像

镜像是一个只读的层(layer),由文件系统叠加构成。而镜像又是容器(Container)的构成单元,我们一般会将应用构建成标准的镜像组件,一或多个镜像叠加又构成了容器

Docker 文件系统

bootfs

Docker由文件系统叠加组成,其最底层是一个引导文件系统,即:bootfs,这个很像Linux或Unix的引导文件系统。引导文件系统负责加载容器容器加载完成后会被移到内存中,而引导文件系统会被卸载,以留出更多的内存初始化(initrd)磁盘。

rootfs

引导文件系统之上是root文件系统,即:rootfsrootfs是在容器启动时,其内部可见的文件系统,其中会包含容器所需要的文件、工具、容器文件等。rootfs可以是一或多个操作系统镜像(基础镜像),如:Debian、Ubuntu、CentOS等。

在Linux系统引导过程中,系统内核启动时,会首先加载一个只读的rootfs。系统对其做完整性等检测后,再决定是否将其切换为读/写模式,或者用一种新的rootfs代替当前rootfs。Docker的设计思想与此类似,不同的是Docker不会将文件系统改为读写模式,而是利用联合加载(Union mount)技术,在rootfs之上加载更多的只读文件系统。

联合加载(Union mount

联合加载(Union mount)是指一次加载多个文件系统,但外面看来只有一个文件系统。联合加载会将各层文件系统叠加到一起,这样最终看到的是一个包含所有文件和目录的、合并后的文件系统。

镜像(Image

在Docker中将这种文件称为镜像(Image),或者说上Docker容器的文件系统是由多个镜像来构成的。一个镜像,可以放在另一个镜像之上。位于底层的镜像称之为父镜像,而位于最底层的镜像称之为基础镜像(Base Image)。

当从一个镜像启动容器时,Docker会从该镜像的最顶层加载一个读/写文件系统,而我们的应用就会运行于这个读/写层中。


2. 镜像(Image)的基础操作

2.1 显示所有镜像

通过镜像创建容器后,镜像从镜像仓库(Registry)下载到本地。可以通过docker images命令查看本地主机上的镜像:

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              f49eec89601e        8 days ago          129 MB

如上所示,我们在介绍Docker 容器时,使用ubuntu镜像创建容器。该镜存放于Docker Hub一个名为ubuntu的仓库中,而其下载到本地后,会被保存在/var/lib/docker目录下。

2.2 拉取(下载)镜像

使用docker run命令从镜像启动容器时,如果镜像在本地不存在,那么首先会从Docker Hub中下载该镜像。

如,我们按如下方式运行一个交互式容器后:

$ sudo docker run -i -t --name itbilu_ubuntu ubuntu /bin/bash

创建后,会在宿主机上保存了一个ubuntu镜像,其版本号为latest,即,最后一个版本的镜像。

为了加快容器启动时间,在运行容器前,可以通过docker pull命令将镜像先下载到本地。

如,拉取一个centos6版本的CentOS基础镜像:

$ sudo docker pull centos:centos6
centos6: Pulling from library/centos
32c4f4fef1c6: Pull complete 
Digest: sha256:1092df198d3da4faccc0660941b763ce5adf133b0ec71701b760d6f173c1f47b
Status: Downloaded newer image for centos:centos6

在这个示例中,使用仓库名:版本号形式下载了一个centos镜像。如果不指定版本号,默认将下载最后一个版本,即:latest

下载完成后,就可以通docker images命令工看到这个镜像。也可以docker images命令后指定镜像名查看:

$ sudo docker images centos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              centos6             8315978ceaaa        3 months ago        195 MB


查找镜像有两种方式:Docker Hub在线查找镜像、docker search命令查找。

在线查找镜像

可以通过Docker Hub官网在线查找镜像:

https://hub.docker.com

如,通过centos关键字可以搜索到名称中含有该关键字的相关镜像:

在线查找Docker镜像

docker search命令查找

还可以使用docker search命令查找镜像。命令格式如下:

docker search [OPTIONS] TERM

如,通过centos关键字查找镜像:

$ sudo docker search centos
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                                 The official build of CentOS.                   3063      [OK]       
jdeathe/centos-ssh                     CentOS-6 6.8 x86_64 / CentOS-7 7.3.1611 x8...   57                   [OK]
jdeathe/centos-ssh-apache-php          CentOS-6 6.8 x86_64 - Apache / PHP-FPM / P...   25                   [OK]
nimmis/java-centos                     This is docker images of CentOS 7 with dif...   23                   [OK]
consol/centos-xfce-vnc                 Centos container with "headless" VNC sessi...   18                   [OK]
million12/centos-supervisor            Base CentOS-7 with supervisord launcher, h...   12                   [OK]

通过命令查找时,返回信息包括:

  • 仓库名(NAME)
  • 镜像描述(DESCRIPTION)
  • 用户评价(STARS)
  • 是否官方式镜像(OFFICIAL)
  • 是否自动构建(AUTOMATED)- 即由Docker Hub自动构建(Automated Build)流程创建

查找到指定镜像后,就可以git pull命令下载镜像。

如,下载名为jdeathe/centos-ssh的镜像:

$ sudo docker pull jdeathe/centos-ssh

镜像下载后,就可以通过下载的镜像创建或启动容器,也可以基于这些镜像构建自己的镜像。


2.4 镜像删除

当镜像不再需要时,可以将镜像从删除。删除镜像使用docker rmi命令。

如,删除jdeathe/centos-ssh的镜像:

$ sudo docker rmi jdeathe/centos-ssh
Untagged: jdeathe/centos-ssh:latest
Untagged: jdeathe/centos-ssh@sha256:7dbd9e7e37bac65bc6aff99472ea2919b38ede8da3a09c58bf56d4a3523d5abf
Deleted: sha256:c3c34686b22ea2290d2c0316dde74ed4d2639b2f2ab27a7b72734dbc397ee2db
Deleted: sha256:ef89b3ead0b29fdc9e02a040830df8e18186f65e92134e0ec8bbd6f3d2e0f77e
Deleted: sha256:fe9df9eef47591a7afeba1a0747bf2b9b75dc31d9521df0dffd1cfa2677e82a7
…

删除和镜像时,我们会看到很多的Deleted行。这是因为,Docker镜像是一种以层(Layer)为单位的分层文件系统,每一行Deleted都表示一个镜像层被删除。

注意:docker rmi只能删除本地镜像,并不能删除镜像仓库。镜像仓库需要登录Docker Hub后,在后台删除对应的Repository

删除镜像时,可以同时删除多个镜像:

$ sudo docker rmi image1 image2

删除镜像时,也可以指定版本号:

$ sudo docker rmi centos:centos6


3. 仓库(Repository)介绍

3.1 镜像从哪里来

docker pull命令会把镜像从Registry的镜像仓库中将镜像拉到本地,使用docker rundocker run命令创建、运行容器时,如果本地不存在创建容器的镜,首先也会从镜像仓库下载镜像。

镜像是从镜像仓库下载下来的。镜像保存在镜像仓库,而镜像仓库保存在RegistryRegistry是由Docker运营的一个公共镜像服务,即:Docker Hub(类似于GitHub)。

Docker Registry是开源的,个人或组织也可以运行自己的Registry。市场上除了Docker官方的Registry外,还有很多第三方Registry服务。这些Registry服务大多基于Docker RegistryDocker Trusted RegistryDocker公司提供的商业版的Docker Hub)构建。

3.2 镜像仓库

镜像在保存Docker Hub仓库(Repository)中的,镜像仓库类似于Git中仓库的概念。一个仓库中可以保存很多镜像,或者说很多版本的镜像。也和Git一样,Docker Hub也通过标签(tag)来标签镜像的不同版本。如:ubuntu镜像的仓库中就包含了12.0414.0416.10trustylatest等不同的镜像版本。

在使用docker pull等命令下载镜像时,如果不指定镜像版本,默认将下载latest版本。如果需要下载指定版本的镜像,可以通过仓库名:标签名的形式下载。

如,下载14.04版本的ubuntu镜像:

$ sudo docker pull ubuntu:14.04
14.04: Pulling from library/ubuntu
c60055a51d74: Pull complete 
755da0cdb7d2: Pull complete 
969d017f67e6: Pull complete 
37c9a9113595: Pull complete 
a3d9f8479786: Pull complete 
Digest: sha256:8f5f12335124c1b78e4cf2f8860d395f75ba279bae70a3c18dd470e910e38ec5
Status: Downloaded newer image for ubuntu:14.04

下载完成后,可以通过docker images查看当前已下载的镜像:

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              f49eec89601e        12 days ago         129 MB
ubuntu              14.04               b969ab9f929b        12 days ago         188 MB

可以看到,本机除latest版的镜像外,又多出了一个14.04版本的镜像。

需要注意的是,我们可以看到相比完整的Ubuntu系统来说,镜像要小的。这是因为,镜像并不是一个完整的系统,而是一个裁剪版的系统,只包含了支持系统运行的有限组件。

除了在docker pull命令中可以指定镜像标签(版本)外,使用镜像的docker rundocker run命令同样可以指定。

如,使用16.04版本的ubuntu镜像运行一个容器:

$ sudo docker run -t -i --name ubuntu_16.04 ubuntu:16.04 /bin/bash
Unable to find image 'ubuntu:16.04' locally
16.04: Pulling from library/ubuntu
Digest: sha256:71cd81252a3563a03ad8daee81047b62ab5d892ebbfbf71cf53415f29c130950
Status: Downloaded newer image for ubuntu:16.04
root@a75027d832e4:/# 

docker images查看,同样会下载指定版本的镜像到本地:

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f49eec89601e        12 days ago         129 MB
ubuntu              latest              f49eec89601e        12 days ago         129 MB
ubuntu              14.04               b969ab9f929b        12 days ago         188 MB


3.3 镜像标签(tag)

为区分一个仓库中的不同镜像(不同镜像版本),Docker Hub引入标签(tagGit中标签的作用基本,都是为了文件进行标识。

我们在前面介绍,镜像由文件系统叠加构成。而镜像又是由多层构成,每一层包含了文件配置两部分,我们一般会把层(Layer)做为一个独立的单元。而标签就是对这些镜像层的标记。

通过镜像层标签,我们可以轻松实现镜像和容器的模块化管理。通过一定的提交、构建机制,还可以很轻松的在现在镜像的基础上构建新镜像。

为了方便镜像的查找,同一个镜像可以存在不同的标签。如,上面的ubuntu:latestubuntu:16.04具有相同的镜像ID,镜像ID才是镜像的唯一标识。


3.4 仓库类型

Docker Hub有类型的仓库:用户仓库(User Repository)和顶层仓库(Top-level Repository)。其中,用户仓库是由用户创建的仓库;而顶层仓库由Doker官方创建和维护。

登录Docker Hub后,可以通过Create-Create Repository链接创建用户创建:

创建Docker用户仓库

用户仓库由用户名和仓库名两部分组成,如,itbilu/myrepository

  • 用户名:itbilu
  • 仓库名:myrepository

用可以基于顶层仓库构建自己的仓库。下载用户仓库中的镜像与项层仓库下载规则相同:

$ sudo docker pull itbilu/myrepository:latest


顶层仓库只有仓库名一级,如:ubuntu。顶层仓库一般由Docker公司,及Docker公司指定的基础镜像厂商管理。