Docker入门系列三——镜像

上一篇介绍了如何在Windows、macOS、Ubuntu上安装docker,安装完成后,我们将开始正式学习docker。Docker的三大核心概念分为是:镜像、容器和仓库,在本篇,我们将介绍第一个核心概念----镜像。 1. 简介 Docker镜像(Image),一个镜像是一个只读的用于创建docker容器(container)的指令模板,包括了程序运行所需的全部依赖包(包括程序、库、资源、配置等)。通常,镜像基于另一个镜像,并进行自定义。镜像是只读的、可运行的,运行后的镜像即为容器(Container)。 1.1. 镜像的几个概念 通过docker images查询本地的镜像列表时,可以看到镜像有REPOSITORY、ID、TAG等字段,镜像包含几个概念,首先需要弄清楚它们间的关系: Registry 镜像注册表,用来存储镜像数据的地方,官方的Docker hub就是一个公共的Registry,另外,还可以通过官方的registry镜像搭建私有的镜像注册表。通常所说的镜像仓库是泛指Registry,但并不完全准确,一个Registry可以包含多个Repository。 例如,拉取镜像:docker pull registry.hub.docker.com/ubuntu:18.04,这里的registry.hub.docker.com就是官方提供的镜像注册表,可以省略不写。 Repository 镜像库,包含多个镜像,存储于Registry中。在仓库搜索镜像时,按名称搜索在registry中查找repository。例如,我们所说的nginx镜像,一般就是指的nginx的Repository,它包含多个nginx镜像,它们通过tag来区分。 Tag 镜像的标签,一般用来作为版本区分,默认不写Tag为latest,一个Image有多个Tag。 Image 具体的镜像,有唯一的GUID和多个Tag。 简单而言,一个Registry包含多个Repository,每个Repository包含多个Image,每个Image有多个Tag,但是ID是唯一的。 1.2. 镜像层 镜像由不同的层(layer)组成。一般而言,Dockerfile每一个指令都会创建一个层,每层只是与之前图层的一组差异,它们都有自己的GUID,并且堆叠在彼此之上。当创建新容器时,将会在基础层的顶部添加新的可写层,称为“容器层”,对正在运行的容器所做的所有更改(例如,写入新文件、修改现有文件和删除文件)都将写入此可写容器层。 Figure 1. 镜像层示意 以镜像ubuntu15.04为例,运行一个容器,下图展示了其基本结构: Figure 2. 基于ubuntu15.04镜像的容器结构 上图展示了一个容器层(container layer)和镜像的多个镜像层(image layer)。其实,容器和镜像最主要的区别就在于容器层,容器层可读写,新写入或者修改的数据都存储在容器层上。基于同一镜像的不同容器都有自己的不同容器层,但是对于底层的各个镜像层,各个容器是共享的。当容器被删除后,只需删除该容器的容器层即可。可以看到,Docker通过层的设计极大地复用了资源,这也是docker轻量和快速的主要原因。 Figure 3. 基于ubuntu15.04镜像创建的多个容器结构 2. 镜像基本操作 接下来,我们看看镜像的一些基本操作。 2.1. 拉取镜像 拉取镜像意思是从镜像的Registry中将镜像下载到本地,类似于Git的pull拉取代码,命令如下: docker image pull [OPTIONS] NAME[:TAG|@DIGEST] 选项包括: -a, --all-tags: 拉取镜像的所有标签 --disable-content-trust: 是否跳过镜像验证,默认为true 例如:docker pull registry.hub.docker.com/ubuntu:18.04 2.2. 镜像查询 1、查询列表 查询本地的所有镜像: docker image ls 等同于docker images,例如: root@ubuntu:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE local/mynginx latest 4d24e58d851d 26 hours ago 108MB python 1.0 22a7b6b93718 5 days ago 131MB nginx latest f68d6e55e065 2 weeks ago 109MB python 2.7-slim ca96bab3e2aa 5 weeks ago 120MB hello-world latest fce289e99eb9 6 months ago 1.84kB ubuntu 14.10 a8a2ba3ce1a3 4 years ago 194MB ...

2019-07-23 · 6 min · 1111 words · Hank

WEBP格式的图片导致ImageIO.read方法return null

1. 问题背景 最近开发一个图片服务,主要是维护项目图片,支持JPG、BMP、PNG、JPEG等常规格式。开发的时候没问题,但是上到生产的时候,客户在维护图片的时候,发现有的JPG格式的图片能上传,有的不能。 拿到正常上传和不能上传的图片,对比发现,不能上传的图片,在windows上根本无法打开,图片如下(用chrome打开可以看见,右键另存图片,或者 点击这里下载): 但是奇怪的是,该图片可以在chrome浏览器显示,也可以在安卓APP上显示,但是其他浏览器和iOS无法正常显示。 2. 问题分析 首先debug代码,发现图片都会使用ImageIO来读取,以便获取图片宽高从而进行等比例压缩,代码如下: BufferedImage bi = ImageIO.read(inputStream); Map rtnMap = new HashMap(); if (bi == null) { rtnMap.put("status", "1"); //上传不成功 rtnMap.put("msg", "该图片本身不是图片格式"); return rtnMap; } 非正常图片,上边的bi会返回null,而不会抛出任何异常信息。 首先怀疑图片是损坏的,因为windows上根本无法打开,显示如下: 但是该图片可以在chrome上正常显示,这表明图片不会是损坏了,应该是跟平台有关,那么会不会是图片格式根本不是JPG,仅仅后缀显示为JPG呢? 然后我用记事本打开正常的和非正常的图片文件进行比对,想获取一些有用的信息,结果发现: 非正常JPG图片 正常JPG图片 如上所示,正常JPG里边,显示格式为JFIF,而非正常图片显示为WEBPVP8,明显不同。看来,不能正常上传的图片是平台不支持的图片格式,到底WEBPVP8是什么格式? 3. WEBP格式 通过谷歌搜索,查询半天发现,这种格式名为WEBP,由谷歌开发,官方地址(记得翻墙): https://developers.google.com/speed/webp/?hl=zh-CN,也是图片格式的一种, 百度百科原文如下: WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。 但WebP是一种有损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更多的计算资源。桌面版Chrome可打开WebP格式。 恍然大悟,原来是一种新型图片格式,很明显windows和iOS还不支持,但是谷歌旗下产品可以支持,这就解释了为什么chrome、安卓能够打开。 在JAVA中,还不支持这种格式,可以用如下代码检查当前支持的图片格式: String[] ss = ImageIO.getReaderFormatNames(); System.out.println(Arrays.asList(ss)); 返回结果:[JPG, jpg, bmp, BMP, gif, GIF, WBMP, png, PNG, jpeg, wbmp, JPEG] 在查找问题时,我还尝试使用twelvemonkeys扩展包来扩展所支持的图片类型: <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-jpeg</artifact> <version>3.3.2</version> </dependency> <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-tiff</artifact> <version>3.3.2</version> </dependency> <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-pnm</artifact> <version>3.3.2</version> </dependency> ...

2017-11-03 · 2 min · 375 words · Hank