Docker 镜像篇
镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。
docker两个跟镜像有关的命令:

hello-world - 最小的镜像
hello-world 是 Docker 官方提供的一个镜像,通常用来验证 Docker 是否安装成功。
我们先通过 docker pull 从 Docker Hub 下载它。

查看

运行hello-world

Base 镜像
base 镜像有两层含义:
不依赖其他镜像,从 scratch 构建。
其他镜像可以之为基础进行扩展。
所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。
从镜像仓库pull一个CentOS镜像下来:

Linux 操作系统由内核空间和用户空间组成。如下图所示:

bootfs
kernel是内核空间,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。
rootfs
rootfs是用户空间的文件系统,包含我们熟悉的 /dev, /proc, /bin 等目录。
对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了;而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。
base 镜像提供的是最小安装的 Linux 发行版。
下面是 CentOS 镜像的 Dockerfile 的内容:
FROM scratch
ADD centos-7-docker.tar.xz / LABEL name="CentOS Base Image" \
vendor="CentOS" \
license="GPLv2" \
build-date="20170406" CMD ["/bin/bash"]
Kernel
通过uname -a 可以看到我们运行的Centos kernel是直接调用宿主机Ubuntu的 kernel.

容器只能使用 Host 的 kernel,并且不能修改。
所有容器都共用 host 的 kernel,在容器中没办法对 kernel 升级。如果容器对 kernel 版本有要求(比如应用只能在某个 kernel 版本下运行),则不建议用容器,这种场景虚拟机可能更合适。
构建镜像
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。比如我们现在构建一个新的镜像,Dockerfile 如下:

① 新镜像不再是从 scratch 开始,而是直接在 Debian base 镜像上构建。
② 安装 emacs 编辑器。
③ 安装 apache2。
④ 容器启动时运行 bash。
构建过程如下图所示:

可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
问什么 Docker 镜像要采用这种分层结构呢?
最大的一个好处就是 - 共享资源。
比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享,我们将在后面更深入地讨论这个特性。
这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?
答案是不会!
修改会被限制在单个容器内。
这就是我们接下来要学习的容器 Copy-on-Write 特性。
可写的容器层
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
只有容器层是可写的,容器层下面的所有镜像层都是只读的
创建镜像
对于 Docker 用户来说,最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等都有现成的 Docker 官方镜像或其他人和组织创建的镜像,我们只需要稍作配置就可以直接使用。
使用现成镜像的好处除了省去自己做镜像的工作量外,更重要的是可以利用前人的经验。特别是使用那些官方镜像,因为 Docker 的工程师知道如何更好的在容器中运行软件。
当然,某些情况下我们也不得不自己构建镜像,比如:
找不到现成的镜像,比如自己开发的应用程序。
需要在镜像中加入特定的功能,比如官方镜像几乎都不提供 ssh。
Docker 提供了两种构建镜像的方法:
docker commit 命令
Dockerfile 构建文件
docker commit
docker commit 命令是创建新镜像最直观的方法,其过程包含三个步骤:
运行容器
修改容器
将容器保存为新的镜像
举个例子:在 Centos base 镜像中安装 vi 并保存为新镜像
1、运行容器:docker run -it centos
2、安装vim:
  
确认 vim 没有安装。
  
3、将容器保存为新的镜像
在另外一台host查看我们刚才安装了vim Container的name或id

通过commit来打包

查看新的镜像

总结:以上演示了如何用 docker commit 创建新镜像。然而,Docker 并不建议用户通过这种方式构建镜像。原因如下:
这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱。比如要在 debian base 镜像中也加入 vi,还得重复前面的所有步骤。
更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。
Dockerfile创建镜像
dockerfile内容:
FROM centos
RUN yum install -y vim

build完成后即可在本地仓库查看到刚才打包的centos-with-vim-dockerfile image

调试 Dockerfile
包括 Dockerfile 在内的任何脚本和程序都会出错。有错并不可怕,但必须有办法排查,所以本节讨论如何 debug Dockerfile。
先回顾一下通过 Dockerfile 构建镜像的过程:
从 base 镜像运行一个容器。
执行一条指令,对容器做修改。
执行类似 docker commit 的操作,生成一个新的镜像层。
Docker 再基于刚刚提交的镜像运行一个新容器。
重复 2-4 步,直到 Dockerfile 中的所有指令执行完毕。
从这个过程可以看出,如果 Dockerfile 由于某种原因执行到某个指令失败了,我们也将能够得到前一个指令成功执行构建出的镜像,这对调试 Dockerfile 非常有帮助。我们可以运行最新的这个镜像定位指令失败的原因。
我们来看一个调试的例子。Dockerfile 内容如下:

执行 docker build:

Dockerfile 在执行第三步 RUN 指令时失败。我们可以利用第二步创建的镜像 22d31cc52b3e 进行调试,方式是通过 docker run -it 启动镜像的一个容器。

手工执行 RUN 指令很容易定位失败的原因是 busybox 镜像中没有 bash。虽然这是个极其简单的例子,但它很好地展示了调试 Dockerfile 的方法。
Docker 镜像篇的更多相关文章
- 关于 Docker 镜像的操作,看完这篇就够啦 !(下)
		
紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...
 - Docker镜像管理基础篇
		
Docker镜像管理基础篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Docker Images Docker镜像还有启动容器所需要的文件系统及其内容,因此,其用于创建并启 ...
 - Docker 镜像之进阶篇
		
笔者在<Docker 基础 : 镜像>一文中介绍了 docker 镜像的基本用法,本文我们来介绍 docker 镜像背后的技术原理. 什么是 docker 镜像 docker 镜像是一个只 ...
 - 【Docker】第二篇 Docker镜像管理
		
一.搜索镜像 1.下载一个docker镜像:我们可以通过登陆docker网站搜索自己需要的镜像,可以选择自己所需要的版本,然后通过详情也可以看到:网址:https://hub.docker.com/2 ...
 - kubernetes实战篇之nexus oss服务器部署及基于nexus的docker镜像仓库搭建
		
系列目录 Nexus oss仓库管理平台搭建 Nexus是一款仓库管理工具,支持Npm,bower,maven,nuget,apt,yum甚至docker,helm等各种仓库,说的通俗以下,就是私服镜 ...
 - kubernetes实战篇之docker镜像的打包与加载
		
系列目录 前面我们讲到了使用nexus搭建docker镜像仓库,操作还是有点复杂的,可能有的童鞋仅仅是想尝试kubernetes功能,并不想在搭建仓库上花费过多时间,但是又想在不同的主机之间传递镜像. ...
 - Docker镜像仓库的搭建--> Harbor篇
		
简介 Harbor是VMware公司开源的一个企业级Docker Registry项目,项目地址:https://github.com/goharbor/harbor Harbor作为一个企业级私有R ...
 - 《Docekr入门学习篇》——Docker镜像制作
		
Docker镜像制作 Docker镜像的构建分为两种,一种是手动构建,一种是dockerfile(自动构建) 手动构建 基于centos镜像进行构建制作Nginx镜像 [root@rbtnode1 ~ ...
 - [第九篇]——Docker 镜像使用之Spring Cloud直播商城 b2b2c电子商务技术总结
		
Docker 镜像使用 当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载. 下面我们来学习: 1.管理 ...
 
随机推荐
- 浅析VS2010反汇编  VS 反汇编方法及常用汇编指令介绍  VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码
			
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
 - webAPI 405
			
web.config 配置 <system.webServer> <modules> <remove name="WebDAVModule" /> ...
 - Android基础笔记(十八)- Fragment
			
博客的感悟终点-開始 什么是Fragment 加入fragment到Activity的两种方式 Fragment的生命周期 Fragment的向下兼容 Fragment之间的通信 博客的感悟,终点-開 ...
 - 李洪强经典面试题39-iOS 程序员 6 级考试(答案和解释)
			
iOS 程序员 6 级考试(答案和解释) 我是前言 1. 下面的代码分别输出什么? @implementation Son : Father- (id)init { self = [super i ...
 - 标准库 - 输入输出处理(input and output facilities)  lua
			
标准库 - 输入输出处理(input and output facilities)责任编辑:cynthia作者:来自ITPUB论坛 2008-02-18 文本Tag: Lua [IT168 技术文档] ...
 - Ajax分页功能的实现
			
电脑换了固态硬盘,准备重装系统,因此打算把项目里一直延用的代码总结出来,防止丢失,以后也方便查阅.Ajax分页已经是非常普遍的技术了,所以也没什么需要特别说明的,直接贴代码: html部分 <! ...
 - scala 编写wordCount
			
加载文件 scala> var f1=sc.textFile("/tmp/dataTest/followers.txt") scala> f1.flatMap(x=&g ...
 - [译]GLUT教程 - 初始化
			
Lighthouse3d.com >> GLUT Tutorial >> Basics >> Initialization 这一节开始从main函数入手.第一步是线 ...
 - Weka关联规则分析
			
购物篮分析: Apriori算法: 参数设置: 1.car 如果设为真,则会挖掘类关联规则而不是全局关联规则. 2. classindex 类属性索引.如果设置为-1,最后的属性被当做类属性. 3. ...
 - NFS网络文件系统服务(配置实战)
			
NFS网络文件系统服务(实战) NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源.让不同的主机系统(NFS的客户端)可以透明地读写位 ...