1 引言

将docker与汽车生产线类比,如果说docker引擎是汽车生产车间,那么容器就是最终的产品——汽车,而本节要介绍的镜像就如同汽车设计图纸,其重要性不言而喻——只有有了设计图(镜像),才能生产汽车(汽车)。

2 镜像管理

2.1 获取镜像

刚安装好的docker里面是没有镜像的,但我们可以从开源的镜像仓库中下载镜像,docker官方提供的docker hub就是最大的一个docker仓库,里面有全球各地用户提供的各式各样的docker镜像供我们下载使用。在下载镜像之前,我们先来熟悉一下docker镜像下载命令和相关知识。
docker [image] pull 仓库名[:标签]
上行命令就是我们常用的docker镜像下载命令,其中,仓库名指定我们要从哪个仓库下载的镜像,标签是指镜像便签,通常指代的是版本信息,例如:ubuntu:16.04和ubuntu:18.04分别指代ubuntu仓库中16.04版本的ubuntu和18.04版本的ubuntu镜像。命令中image和标签参数可加可不加,当省略标签参数时,即指使用默认的latest标签,也就是说,下载指定仓库中的的最新版本。下载ubuntu最新版本:
$ docker pull ubuntu
注意:latest标签会动态跟随最新版本变更,这意味着镜像内容也是动态变化的,所以出于稳定性考虑,在生产环境中,不要在生产环境中使用latest标签。
pull命令默认从官方docker hub仓库中下载镜像,所以,上行命令中并没有指定完整仓库名,如果需要从其他非官方仓库下载镜像,则需要指定完整仓库名,例如,从网易非常的镜像源中下载ubuntu:18.04镜像:
$ docker pull hub.c.163.com/public/ubuntu18.04

2.2 查看及查找镜像

(1)查看本机上所有镜像基本信息:
$ docker images
(2)查看指定镜像详细信息
$ docker [image] inspect 仓库名:标签
例:查看上文中下载的ubuntu:18.04镜像详细信息
$ docker inspect ubuntu:18.04
(3)查看镜像各层创建信息
$ docker history 仓库名:标签
(4)搜索镜像
$ docker search [选项] 关键词
命令中,可以通过选项指定输出内容格式、数量、部分过滤条件等,关键词是指搜索关键字。
例如:查找ubuntu相关镜像
$ docker search ubuntu

2.3 删除镜像

删除镜像可以使用一下两种命令格式:
$ docker rmi 仓库名:标签或镜像id
$ docker image rm 仓库名:标签或镜像id
定位一个镜像可以通过"仓库名:标签"和镜像id两种方式,所以,在删除镜像时,我们也可以通过这两种方式来指定要删除的镜像,也即是上面两行命令中的仓库名:标签或镜像id。
删除镜像时需要注意,每次运行删除镜像命令事实上只是删除指定镜像的一个标签,只有当该镜像仅有一个标签时,使用删除镜像命令才会真正删除镜像。啥?一个镜像还有多个标签,没错,人类除了真名都还有网名、小名、外号呢。在演示删除镜像前,我们先尝试给镜像添加标签。
先查看本地有哪些镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 7698f282e524 7 days ago 69.9MB
hello-world latest fce289e99eb9 4 months ago 1.84kB
给hello-World镜像添加一个标签:
$ docker tag hello-world:latest bye-world:8000
如果成功,没有任何提示,再次查看本地所有镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 7698f282e524 7 days ago 69.9MB
bye-world 8000 fce289e99eb9 4 months ago 1.84kB
hello-world latest fce289e99eb9 4 months ago 1.84kB
看,出现了bye-world镜像,但我们可没有新建或者下载镜像,这就是我们刚才为hello-World创建的新标签,看着他们相同的镜像id你就知道他们是同一个镜像了。接下来尝试删除镜像:
$ docker rmi bye-world:8000
Untagged: bye-world:8000
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 7698f282e524 7 days ago 69.9MB
hello-world latest fce289e99eb9 4 months ago 1.84kB
果然如上文所说,bye-world:8000被删除了,但事实上它所指向的镜像被没有被真正删除,因为这个镜像还有一个标签存在。我们继续参数删除hello-world:latest镜像:
$ docker rmi hello-world:latest
Error response from daemon: conflict: unable to remove repository reference "hello-world:latest" (must force) - container 53c855a9d4a9 is using its referenced image fce289e99eb9
懵逼了,失败了,咋回事?因为尚有依赖于该镜像的容器存在,所以产生冲突。这时候要删除镜像,就必须添加-f参数,强制执行:
$ docker rmi -f hello-world:latest
Untagged: hello-world:latest
Untagged: hello-world@sha256:6f744a2005b12a704d2608d8070a494ad1145636eeb74a570c56b94d94ccdbfc
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 7698f282e524 7 days ago 69.9MB
只剩下一个ubuntu镜像,证明删除成功。

3 创建镜像

创建镜像的方法有三种:基于已有镜像的容器创建镜像、基于dockerfile创建、基于本地模板导入,这里我们只介绍前两种。

3.1 基于已有镜像容器创建镜像

基于已有镜像容器创建镜像需通过docker commit命令,命令格式如下:
$ docker commit [选项] 容器名或容器id [<仓库名>[:<标签名>]]
在使用docker commit命令创建镜像之前,我们先得有一个容器。
$ docker run -it ubuntu:18.04 /bin/bash
root@001b647aad4e:/#
docker run命令时使用镜像创建一个容器的命令,具体个参数什么含义,我们后面继续学习。可以看到,运行这一命令后,启动了一个id为001b647aad4e的容器,记住这一id,后面要用到。
我们继续在这一容器里git环境:
root@001b647aad4e:/# git --version
bash: git: command not found
可以看到,刚创建的容器里面刚开始是没有git的,我们安装一个:
root@001b647aad4e:/# apt-get update
root@001b647aad4e:/# apt install git
root@001b647aad4e:/# git --version
git version 2.17.1
可以看到,git安装成功。
退出容器,然后使用刚才的容器创建一个镜像。
root@001b647aad4e:/# exit
exit
$ docker commit -m "Add git in ubuntu18.04" -a "God" 001b647aad4e ubuntu_git:1.0
sha256:30e6c7c480dc44743f0f030f4904089fb8568ad2333f8de3a22c4f6a71fdb451
成功创建镜像,并返回了镜像id信息。
查看一下本地镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu_git 1.0 30e6c7c480dc About a minute ago 189MB
ubuntu 18.04 7698f282e524 8 days ago 69.9MB
可以看到,镜像创建成功。以ubuntu_git为基础,创建一个容器,新容器也会有git环境,换句话说,docker commit相当于是对001b647aad4e进行了一次备份。
docker commit命令创建镜像虽然简单直观,但是在时间生产中并不建议用,因为使用docker commit命令创建的镜像无法追踪镜像的创建过程,造成镜像创建过程难以重复、维护困难,且容易出现镜像臃肿的镜像。所以,在实际应用中,更推荐使用下一小节要说到的使用dockerfile文件创建镜像的方法。

3.2 使用dockerfile创建镜像

dockerfile是一个文本文件,通过每一条指令构建镜像一层,或者说dockerfile每一条指令定义了镜像每一层如何构建,所以,使用dockerfile创建镜像的过程完全是透明的、可重复的,很好的你不了docker commit命令创建镜像的不足。
还以上一小节中定制一个包含git环境的镜像为例,不过这次我们使用dockerfile来创建。
首先创建一个目录作为创建镜像的上下文路径,并进入该目录:
$ mkdir ubuntu_dockerfile_git
$ cd ubuntu_dockerfile_git/
然后创建创建dockerfile文件:
$ touch dockerfile
开始编辑dockerfile,在dockerfile内写入一下内容:
FROM ubuntu:18.04

RUN apt-get update \
&& apt-get install -y git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
先来解释一下上面写入dockerfile文件的内容:
FROM ubuntu:18.04的意思是以ubuntu:18.04镜像为基础来构建新的镜像,每一个新的镜像,都必须有一个基础镜像,FROM命就是用于指定基础镜像,而且需要注意的是,FROM命令必须位于整个过程的第一行。
第二行的RUN命令是用来执行命令行操作。那为何上面的RUN命令执行的4条命令行操作都用一个RUN命令来执行呢?事实上,每个命令行操作都使用一个RUN命令来执行也不会出错,但,上面提到过,dockerfile中,每一条指令都会创建一层,如果每一条命令行操作的用一个RUN命令执行,这种写法就创建了4层,创建出来的镜像就显得臃肿,也增加了部署时间,另外从功能上来说,这4条命令行操作都是为了安装一个git,没必要拆分。docker镜像总层数不得操作127层。
现在可以用创建好的dockerfile文件创建镜像了,使用的是docker build命令,命令格式如下:
docker build [选项] <上下文路径/URL>
假定我们将要创建镜像的镜像名为ubuntu_dockerfile_git,使用docker build如下:
$ docker build -t ubuntu_dockerfile_git:1.0 .
在一大段的输出之后可以看到:
Successfully built 6e703a3b11e2
Successfully tagged ubuntu_dockerfile_git:1.0
说明镜像创建成功。再次查看本地镜像:
$ docker images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu_dockerfile_git 1.0 6e703a3b11e2 About a minute ago 163MB
ubuntu_git 1.0 30e6c7c480dc 20 hours ago 189MB
ubuntu 18.04 7698f282e524 9 days ago 69.9MB
果然有刚创建的ubuntu_dockerfile_git,我们用它来创建一个容器:
$ docker run -it ubuntu_dockerfile_git:1.0 /bin/bash
root@18c03ae954ab:/# git --version
git version 2.17.1
可以看到,刚启动的容器里果然有git。
dockerfile是用的最多的一种镜像创建方法,涉及到的内容也较多,在上面的应用中,我们只介绍了FROM、RUN指令,除此之外还有COPY、CMD、ADD等众多指令没有涉及到,大家可以参考纯洁的微笑前辈的这篇博客,写得很详细且通俗易懂。

4 总结

本篇博文介绍了对docker镜像的管理,包括镜像查看、删除、创建等操作。但作为docker的核心内容,镜像管理可绝不仅仅包含这点点只是,例如镜像存出、载入、上传等内容就没有涉及到。本文只作为入门阶段抛砖引玉吧。
 
 
 
 

docker系列(二):镜像的更多相关文章

  1. Docker系列-(2) 镜像制作与发布

    上篇文章引入了Docker的基本原理和操作,本节文章主要介绍如何制作Docker镜像和发布. 镜像文件结构 Docker镜像的本质是一系列文件的集合,这些文件依次叠加,形成了最后的镜像文件,类似于下图 ...

  2. Docker 系列二(操作镜像).

    一.镜像管理 1.拉取镜像 docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] -- Docker 镜像仓库地址 :一般是 域名或者IP[:端口号 ...

  3. Docker系列二: docker常用命令总结

    https://docs.docker.com/reference/  官方命令总结地址 容器生命周期管理 1.docker run 创建一个新的容器并运行一个命令 docker run [optio ...

  4. Docker系列(二)组件介绍

    镜像 镜像是一个只读的模版,可以用来创建Docker容器. 容器 Docker利用容器来运行应用,容器是从镜像创建的运行实例.它可以被启动.开始.停止.删除.每个容器都是互相隔离的,保证安全的平台.可 ...

  5. Docker系列二:Docker的基本结构

    Docker的基本结构 Docker 的三大基础组件 Docker有三个重要的概念:仓库 , 镜像 和 容器 ,它们是Docker的三大基出组件 Docker的组织结构 Docker处于操作系统和虚拟 ...

  6. docker 系列 - 基础镜像环境和Docker常用命令整理

    =======================docker 基础镜像环境 alpine=======================可以使用 docker search 命令搜索指定的 image, ...

  7. docker系列之镜像服务器

    docker 的镜像服务器 docker-registry 是 docker 项目的组成部分. 前面在谈 docker 的命令时, 它的 pull/push 命令就是和镜像服务器打交道. 并且, do ...

  8. Docker系列之镜像瘦身(五)

    前言 本节我们来讲讲在我们在构建镜像过程中不出问题,同时使得最后所构建的镜像文件大小尽可能最小,温馨提示:文中大图均可点击放大查看详细信息. 缓存(cache) Docker的优势之一在于提供了缓存, ...

  9. Docker系列(二):Docker基础命令

    docker的部署安装(Linux kernel至少3.8以上): yum install docker docker1.8安装:(下面 是两个命令) # cat >/etc/yum.repos ...

  10. windows下部署.netcore+docker系列二 (unbuntu 18.4 下 安装 docker)亲测!!!

    1.卸载sudo apt-get remove docker docker-engine docker.io containerd runc2.更新sudo apt-get update3.安装依赖包 ...

随机推荐

  1. C++中两个类相互包含引用问题

    在构造自己的类时,有可能会碰到两个类之间的相互引用问题,例如:定义了类A类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A { int i; B b; } class B { in ...

  2. poj2228Naptime——环形DP

    题目:http://poj.org/problem?id=2228 dp[i][j][0/1]表示前i小时中第j小时睡(1)或不睡(0)的最优值: 注意第一个小时,若睡则对最终取结果有要求,即第n个小 ...

  3. C# 线程的暂停和恢复的 实现

    我们可以通过ManualResetEvent类来实现. 声明, 初始化时不执行 private static ManualResetEvent _eventWorkList = new ManualR ...

  4. vijos:P1285佳佳的魔法药水

    背景 发完了k张照片,佳佳却得到了一个坏消息:他的MM得病了!佳佳和大家一样焦急万分!治好MM的病只有一种办法,那就是传说中的0号药水……怎么样才能得到0号药水呢?你要知道佳佳的家境也不是很好,成本得 ...

  5. AR/VR-VR-Info-Micron-Insight:一镜观一屋:VR 将建筑设计变为现实

    ylbtech-AR/VR-VR-Info-Micron-Insight:一镜观一屋:VR 将建筑设计变为现实 1.返回顶部 1. 一镜观一屋:VR 将建筑设计变为现实 想象一下,在一栋为你设计的还没 ...

  6. 1、R-reshape2-cast

    1.cast:     长型数据转宽型数据 (1).acast,dcast的区别在于输出结果.acast 输出结果为vector/matrix/array,dcast 输出结果为data.frame. ...

  7. charles关于手机APP抓包

    这里相比其他抓包软件来说要简单的多了,具体步骤如下: 1 使手机和电脑在一个局域网内,不一定非要是一个ip段,只要是同一个漏油器下就可以了,比如电脑连接的有线网ip为192.168.16.12,然后手 ...

  8. Go语言入门——数组、切片和映射

    按照以往开一些专题的风格,第一篇一般都是“从HelloWorld开始” 但是对于Go,思来想去,感觉真的从“HelloWorld”说起,压根撑不住一篇的篇幅,因为Go的HelloWorld太简单了. ...

  9. PHP之递归函数

    https://www.cnsecer.com/4146.html http://www.jb51.net/article/71424.htm //一列数字的规则如下:1,1,2,3,5,8,13,2 ...

  10. Unity 5着色器系统代码介绍(上)

    http://forum.china.unity3d.com/thread-25724-1-10.html Unity 5着色器系统代码介绍(上) Unity在着色器开发方面提供了很大的灵活性.有些工 ...