「Docker」- 镜像与仓库

更新日期:2019年08月09日

内容简介

本部分介绍什么是镜像,以及镜像的管理,镜像的创建,存储,修改,共享等方面的内容。

#01 什么是镜像

镜像由文件系统叠加而成:

「bootfs」,一个「引导文件系统」,位于最底端,像Linux/Unix的「引导文件系统」。用户不会和该「引导文件系统」有什么交互。当「容器」启动时,「容器」会被移动到内存中,而「引导文件系统」则会被卸载,留出内存供「initrd磁盘镜像」使用。

「rootfs」,第二层文件系统,位于「引导文件系统」之上。「rootfs」可以是多种操作系统,如Debain、Ubuntu等等。「rootfs」永远是只读状态,不同于传统的Linux引导过程,传统的Linux引导过程中,「rootfs」先以只读方式加载,引导结束并完成完整性检查后,才会进入读写模式。

「只读文件系统」,位于「rootfs」之上。通过「联合挂载」技术,在「rootfs」上挂载更多的只读文件系统。「联合挂载」同时加载多个文件系统,但是整体上看只有一个文件系统。「联合挂载」会将各层文件系统叠加到一起,这样最终的文件系统会包含所有底层的文件和目录。

在Docker中,将上面的文件系统称为「镜像」。

一个「镜像」可以放到另一个镜像的顶部。位于下面的「镜像」成为「父镜像」,最底层的镜像称之为「基础镜像」。当从一个「镜像」启动「容器」时,Docker会在「镜像」的最顶层加载一个「读写文件系统」,我们运行的程序都是在这个「读写文件系统」中执行的。

在Docker中,使用到了一种「写时复制」机制。初始化时,「读写层」是空的。当文件系统发生修改时,所有的变化都存在与该「读写层」中。比如修改一个文件,该文件会被从「只读层」复制到「读写层」,在「读写层」进行修改。但是该文件的只读版本依旧存在,但是它被「读写层」中的该文件隐藏,正是因为使用了「联合挂载」技术。 上面的这些层共同构成了「镜像」。

#02 镜像 - 列出

使用docker images命令来查看镜像。

当执行docker run时,如果镜像不存在,则会从仓库中自动拉去。镜像保存在/var/lib/docker/中,每个镜像都保存在Docker所采用的存储驱动目录下面,如aufs或devicemapper。而/var/lib/docker/containers/中保存了所有的容器。

IMAGE -> REPOSITORY -> REGISTRY

REGISTRY,开源,可以运行自己私有的Registry,Docker公司提供了商业版的Docker Hub(Docker Trusted Registry),可以运行在防火墙内部的产品,之前称为Docker Enterprise Hub。

「镜像」保存在「仓库」中,可以类比成Git仓库,包含了镜像,层,镜像的元数据。

使用docker pull命令拉取镜像:docker pull ubuntu:12.04

docker images的输出中,镜像是一个「TAG」为单位列出的,即“有一个「TAG」,就有一条记录”。每个「TAG」对组成特定镜像的一些镜像层进行标记,这样一个「仓库」里就可以由多个「镜像」。使用“冒号加TAG”的形式来指定某个「仓库」里的指定「镜像」。

一个「镜像」可以创建多个「TAG」,「镜像」之间使用「镜像ID」区分的,就是说“可以存在「TAG」不同,但是「镜像ID」相同的多个「镜像」,但实际上他们都是同一个「镜像」”。使用「TAG」是一个好习惯。

在Docker Hub中,有两类仓库:用户仓库;顶层仓库。用户仓库,由用户创建。顶层仓库,由Docker内部人管理。

用户仓库命名分为两部分:用户名和仓库名。如jamtur01/puppet。这些仓库由用户自己创建,未经Docker公司确认,使用时需要承担相应的风险。

顶层仓库则只有仓库名部分,这些镜像由优质的厂商提供,用户可以基于这些镜像构建自己的镜像。

在Docker 1.8后,增加了对镜像签名的功能。用于对镜像内容的安全管理。

#03 镜像 - 拉取

使用docker pull命令拉取镜像。

执行docker run命令时,如果镜像不存在,则会先拉取「TAG」为「latest」镜像。可以先使用docker pull命令拉取镜像,以减少镜像启动的时间。

#04 镜像 - 查找

使用docker search命令可以在Docker Hub上搜索镜像。

#!/bin/sh

docker search puppet

返回的信息有:仓库名、镜像描述、用户评价、是否官方、是否自动构建(是否由Docker Hub的自动构建流程创建)。

然后,可以使用docker pull命令来拉取镜像:docker pull puppet/puppetserver

最后,就可以运行这个容器了:docker run -i -t puppet/puppetserver /bin/bash

#05 镜像 - 构建

构建镜像的两种方式:

  • docker commit(不推荐)
  • docker build and Dockerfile(推荐)

新镜像实际上是基于已有进行构建的。

#01 创建Docker Hub帐号

去Docker Hub注册帐号,使用docker login命令登录,使用docker logout退出登录。

个人认证信息保存在$HOME/.dockercfg中,从Docker 1.7.0开始,保存在$HOME/.docker/config.json中。

#02 使用「docker commit」命令

类似于版本控制系统的提交命令。

创建容器 -> 修改 -> 提交

使用docker commit命令提交修改过的容器。该命令只提交与之前差异的部分。

还可以使用-a选项指定作者,选项-m指定提交信息。

使用docker inspect命令查看镜像信息。

访问「docker commit」查看docker commit命令的所有选项。

#06 镜像 - 推送到Docker Hub

使用docker push命令将镜像推送的远程的Docker Hub,供别人使用。也可以创建私有镜像,但是这是一个付费功能。

推送到远程仓库时,需要指定用户名:docker push your_user/your_image

访问「Docker Hub Quickstart | Docker Documentation」查看文档。

!!!Docker Hub支持自动构建,这需要与GitHub或者BitBuket仓库关联,他会自动读取Dockerfile文件,然后进行构建,查看构建日志及输出。这里不再展开,不过不知道开源的Docker Registry是否也支持这个功能。:-)

相关杂记


# 关于父镜像与父镜像层
-「Is docker inspect -f '{{.Parent}}' a safe way to get the base image ID?
命令docker image inspect b7b28af77ffe --format '{{.Parent}}'输出确实是父镜像,但是这个“父镜像”是“父镜像层”,而不是Dockerfile中FROM引用的镜像层(除非你的Dockerfile中只有一个FROM指令)。

相关连接

Dockerfile reference


ToC

内容简介

#01 什么是镜像

#02 镜像 - 列出

#03 镜像 - 拉取

#04 镜像 - 查找

#05 镜像 - 构建

#01 创建Docker Hub帐号

#02 使用「docker commit」命令

#06 镜像 - 推送到Docker Hub

相关杂记

相关连接