一、Docker镜像是什么?

  操作系统分为内核用户空间。在Linux中,内核启动后会挂载 root 文件系统为其提供用户空间支持。

  docker镜像就相当于一个 root文件系统。比如:官方镜像ubuntu:18.04就包含了一套Ubuntu最小系统的root文件系统。

  虽然docker镜像相当于一个root文件系统,但它是一个特殊的文件系统,不仅提供容器运行时所需的程序、库、资源、配置等文件,还包含运行时准备的一些配置参数(如:匿名卷、环境变量、用户等)。

二、分层存储与镜像构建

  Docker设计时充分利用 Union FS 的技术,将其设计为分层存储的架构。镜像只是一个虚拟的概念,并不是一个类似ISO的打包文件,是由多层文件系统联合组成。

1、UnionFS

  联合文件系统(Union File System):2004年由纽约州立大学石溪分校开发,它可以把多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的。UnionFS允许只读和可读写目录并存,就是说可同时删除和增加内容。

  Linux各发行版实现的UnionFS各不相同,因此Docker在Linux发行版中使用的也不同。可以通过docker info 来查看docker使用的是哪一种UnionFS。目前Dokcer支持如下几种storage driver 如下所示:

  

详见:Docker之几种storage-driver比较

2、镜像构建

  镜像构建时会一层层构建,前一层是后一层的基础。
  每一层构建完就不再发生改变,后一层上的任何改变只发生在自己这一层。
  由于这个特性,操作删除前一层文件,并没有真的删除前一层的文件,而是紧紧在当前层标记该文件删除。在容器运行时不会看到该文件,但改文件会一直跟随镜像。
  因此构建镜像时,需要格外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西在该层构建结束前清除掉。

三、使用镜像

1、获取镜像

  从docker镜像仓库获取镜像的命令是 docker pull 。命令格式如下所示:

$ docker pull [选项] [Docker Registry 地址[:端口号]/仓库名[:标签]]
# Dokcer镜像仓库地址:格式一般是<域名/IP>[:端口号],默认地址是 Docker Hub
# 仓库名:两段式名称,<用户名>/<软件名>,对Docker Hub,如果不给出用户名,默认为 library,也就是官方镜像。

  获取ubuntu镜像示例:

[root@kwephicprc03547 yum.repos.d]# docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
9ef5b901d87c: Pull complete # 层id
3daad4f91066: Pull complete
7e9f0564ef6f: Pull complete
fc001299f620: Pull complete
Digest: sha256:7a47ccc3bbe8a451b500d2b53104868b46d60ee8f5b35a24b41a86077c650210 # 镜像完整的sha256摘要
Status: Downloaded newer image for ubuntu:18.04

  注意:

  (1)由于镜像名称为ubuntu:18.04,一次获取官方镜像 library/ubuntu仓库中标签为 18.04 的镜像。
  (2)由于镜像是由多层存储构成,因此下载也是一层层下载。
  (3)下载过程中显示了每一层id的前12位。
  (4)下载完成输出完整sha256摘要以保证下载一致性。
  (5)层ID和sha256下载并不都一致,因为官方一直在维护,处理BUG或版本更新。

2、列出镜像

  想列出已经下载下来的镜像,可以使用 docker images 或者 docker image ls 命令。

[root@kwephicprc03547 yum.repos.d]# docker images
#仓库名 标签 镜像ID 创建时间 所占用的空间
REPOSITORY TAG IMAGE ID CREATED SIZE
euler latest da5bac89d64d days ago .15GB
ubuntu 18.04 21e0cf71370f weeks ago .9MB
hello-world latest de6f0c40d4e5 weeks ago .75kB
centos/aarch64 latest b1b73535f567 months ago 236MB
[root@kwephicprc03547 yum.repos.d]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
euler latest da5bac89d64d days ago .15GB
ubuntu 18.04 21e0cf71370f weeks ago .9MB
hello-world latest de6f0c40d4e5 weeks ago .75kB
centos/aarch64 latest b1b73535f567 months ago 236MB

  注意:镜像ID才是镜像的唯一标识,一个镜像可以对应多个标签

3、镜像体积

  docker images列出镜像所标识的占用空间和在Docker Hub上看到的镜像大小是不同的。

  Docker Hub地址:https://hub.docker.com/_/ubuntu?tab=tags

  Docker Hub中显示的体积是压缩后的体积。

  在镜像下载和上传过程中镜像都是保持在压缩状态的,因此这个镜像大小关注的是网络传输中的流量。

  但是docker images列表中的镜像体积总和也并不是所有镜像的实际消耗:
  1)Docker镜像是多层存储结构,可以继承、复用,因此不同的镜像可能使用的是相同的基础镜像,从而拥有共同的层。
  2)Union FS技术下,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间往往比列表镜像大小总和小很多。
  3)查看镜像、容器、数据卷所占用的空间:

$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images .4MB .9MB (%)
Containers .2MB 0B (%)
Local Volumes 0B 0B
Build Cache 0B 0B

4、镜像删除

  要删除本地镜像其命令格式如下所示:

docker image rm [OPTIONS] IMAGE [IMAGE...]
docker rmi [OPTIONS] IMAGE [IMAGE...]
docker image remove [OPTIONS] IMAGE [IMAGE...] Remove one or more images
Aliases:
rm, rmi, remove
Options:
-f, --force Force removal of the image
--no-prune Do not delete untagged parents 

  删除镜像可以使用镜像短id、镜像长id、镜像名、镜像摘要。删除镜像示例如下所示:

[root@kwephicprc03547 ~]# docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Deleted: sha256:de6f0c40d4e5d0eb8e13fa62ccbbdabad63be2753c9b61f495e7f1f486be1443
Deleted: sha256:26d82c2b34c3dedc481b7db3d84c3d1892a6a82cd97624767c4217beb382e7f8

  删除镜像时,实际上是在要求删除某个标签的镜像。删除镜像的几种情况分析:

  首先需要将满足要求的所有镜像标签取消,即Untagged信息。

  其次当镜像所有的标签都被取消,镜像失去了存在的意义,触发删除行为。从上层向基础层依次进行判断删除。

  如果取消了标签,但是这个镜像仍被其他标签指向,则不会触发删除行为。而且镜像是多层结构,如果有某些镜像依赖于当前镜像的某一层,也不会触发删除行为,直到没有任何层依赖当前层,才会真是删除当前层。

  由于容器是以镜像为基础,再加一层容器存储层,因此镜像启动的容器依然存在也是不可以删除当前镜像的。

四、docker commit理解和使用

  镜像地多层存储的,每一层在前一层的基础上进行修改;容器也是多层存储,以镜像为基础层,在其基础上加一层作为容器运行时的存储层。

  运行容器时(如果不使用卷),任何文件修改都会被记录在容器存储层里。

  docker commit命令,可以将容器的存储层保存下来成为镜像:在原镜像基础上,叠加容器存储层,构成新的镜像。

1、容器修改案例

(1)启动一个nginx容器

  用nginx镜像启动一个容器,命名为webserver,且映射80端口:

[root@kwephicprc03547 ~]# docker run --name webserver -d -p  nginx
Unable to find image 'nginx:latest'
locallylatest: Pulling from library/nginx
42367302fc78: Pull complete
a9cb25c539ce: Pull complete
07dff5c0fced: Pull complete
Digest: sha256:dd2d0ac3fff2f007d99e033b64854be0941e19a2ad51f174d9240dda20d9f534
Status: Downloaded newer image for nginx:latest
84d5102335b184f04e9f9060cafe38ac5216424e641036cc1fab2f84d9140937

  可以在浏览器直接访问该页面:

(2)修改容器nginx页面显示

  以交互终端方式进入webserver容器,执行shell命令修改index.html:

[root@kwephicprc03547 ~]# docker exec -ti webserver bash
root@84d5102335b1:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

  刷新浏览器,显示内容如下所示:

   

  修改容器文件就修改了容器的存储层,利用docker diff 命令查看具体改动:

[root@kwephicprc03547 ~]# docker diff webserver
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
C /root
A /root/.bash_history
C /runA /run/nginx.pid

2、使用docker commit定制镜像

  docker commit语法格式:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

Create a new image from a container's changes

Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)

(1)将webserver容器保存为镜像

[root@kwephicprc03547 ~]# docker commit \
> --author 'hqs' \ # 指定修改的作者
> --message "修改欢迎页面显示" \ # 记录本次修改内容
> webserver \ # 容器名
> nginx:v2 # 仓库名:标签
sha256:c795dacab9b490ff99ee3ea2493eae7675f2c550c5f66064ddaf5a0f7dc14755

(2)查看新定制的镜像

[root@kwephicprc03547 ~]# docker image ls nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 c795dacab9b4 minutes ago 103MB
nginx latest 9235bd14ba8c weeks ago 103MB

再使用docker history查看镜像内历史记录:

  

3、docker commit总结

  docker diff webserver可以发现,容器中除了真正要修改的/user/share/nginx/html/index.html文件外,还有很多文件被改动或添加了。如果是安装软件、编译构建则会有大量的无关内容被添加进去,导致镜像非常臃肿

  docker commit意味着对镜像的操作是黑箱操作,生成的也是黑箱镜像。除了制作镜像人知道执行过什么发生过什么,其他人无从得知。这将导致维护非常困难

  因此定制镜像应该使用 Dockerfile 来完成。

docker镜像使用和总结的更多相关文章

  1. MySQL、MongoDB、Redis数据库Docker镜像制作

    MySQL.MongoDB.Redis数据库Docker镜像制作 在多台主机上进行数据库部署时,如果使用传统的MySQL的交互式的安装方式将会重复很多遍.如果做成镜像,那么我们只需要make once ...

  2. 理解Docker(2):Docker 镜像

    本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  3. 如何合并两个Docker 镜像

    http://www.open-open.com/lib/view/open1437746544709.html 在你的机器上使用docker pull来从Docker Hub下载镜像. docker ...

  4. Docker镜像的管理和创建

    1. Docker镜像和Docker容器:      Docker镜像实际上是一系列的文件系统,通常的Linux系统一般是两层文件系统,bootfs和rootfs,bootfs就是bootloader ...

  5. docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储

    前段时间一直忙些其他事情,docker源码分析的事情耽搁了,今天接着写,上一章了解了docker client 和 docker daemon(会启动一个http server)是C/S的结构,cli ...

  6. docker使用阿里云Docker镜像库加速

    官方镜像下载实在是慢,于是开通了阿里云开发者帐号, 官方帮助 阿里云Docker镜像库 阿里云容器Hub服务:http://dev.aliyun.com/search.html 来自云端的容器Hub服 ...

  7. 第四章 使用Docker镜像和仓库(二)

    第四章 使用Docker镜像和仓库(二) 回顾: 开始学习之前,我先pull下来ubuntu和fedora镜像 [#9#cloudsoar@cloudsoar-virtual-machine ~]$s ...

  8. 第四章 使用Docker镜像和仓库

    第4章 使用Docker镜像和仓库 回顾: 回顾如何使用 docker run 创建最基本的容器 $sudo docker run -i -t --name another_container_mum ...

  9. 将 ASP.NET Core 1.0 应用作为 docker 镜像发布 (Linux版)

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  10. Docker镜像

    docker镜像123? 额,由于没有实验环境,没有亲手实践,因此理解可能有不对的地方. 反正也是学习笔记,以后再修改吧... docker的镜像跟virtualbox的镜像不一样.在虚拟机中,镜像是 ...

随机推荐

  1. [转]IOS UIView 之属性篇

    [转载自:IOS UIView 之属性篇 From CSDN] UIView 继承于UIResponder             所遵守的协议有 NSCoding .UIAppearance. UI ...

  2. javascript中children,childNodes等节点属性

    1.children与childNodes children: 获取子元素节点,无兼容问题 childnNodes: IE:获取子元素节点 非IE(chrome,Firefox等):获取子节点,包括元 ...

  3. hasattr(object, name)

    查看object有没name属性 有返回True 没有返回 False

  4. 大话AJAX原理

    大话AJAX原理 一.什么是Ajax Ajax(Asynchronous JavaScript and XML的缩写)是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助.简单地说 ...

  5. 04. H5标签有哪些?行内元素有哪些?块级元素有哪些?空(void)元素有哪些?行内元素和块级元素有什么区别?你工作中常用标签有什么?

    4. H5标签有哪些? 2)行内元素有哪些? a - 锚点 em - 强调 img - 图片 font - 字体设定 ( 不推荐 ) i - 斜体 input - 输入框 3)块级元素有哪些? add ...

  6. Java的定时调度

    一般在web开发中定时调度比较有用,因为要维护一个容器不关闭才可以一直定时操作下去. 定时调度:每当一段时间之后,程序就会自动执行,就称为定时调度.如果要使用定时调动,则必须要保证程序要始终运行着,也 ...

  7. python 3 map函数用法

    公式 f是定义的函数,l是你的list,所有功能都在f函数里完成, map(f,l) 有些网址爬虫出来的链接是一部分,省略了前端通用的,这时我们需要补充进去, 这时就用到了map函数,批量补充网址, ...

  8. android 捕获未try的异常

    1.Thread.UncaughtExceptionHandler java里有很多异常如:空指针异常,越界异常,数值转换异常,除0异常,数据库异常等等.如果自己没有try / catch 那么线程就 ...

  9. web测试工具总结

     纯粹的手工测试早已不满足如今的项目需求,各种测试工具的应用早已成为普遍趋势.如何选取合适的工具来完成对应的测试工作?本文将针对Web测试,列举 一些推荐的测试工具,并加以简单介绍. (每个工具的实际 ...

  10. Apache和Tomcat的整合过程(转载)

    一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由 ...