Docker实践之02-使用镜像及定制

目录

一.获取镜像

Docker运行容器前须要本地存在对应的镜像,若是本地不存在该镜像,Docker会从镜像仓库下载该镜像。
从Docker镜像仓库获取镜像的命令是docker pull,其命令格式为:php

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

如:nginx

$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
297061f60c36: Pull complete 
e9ccef17b516: Pull complete 
dbc33716854d: Pull complete 
8fe36b178d25: Pull complete 
686596545a94: Pull complete 
Digest: sha256:1dfb94f13f5c181756b2ed7f174825029aca902c78d0490590b1aaa203abc052
Status: Downloaded newer image for ubuntu:16.04

上面的命令中没有给出Docker镜像仓库地址,所以将会从Docker Hub获取镜像(若是配置镜像加速器,则从镜像加速器上拉取镜像)。而镜像名称是ubuntu:16.04,所以将会获取官方镜像library/ubuntu仓库中标签为16.04的镜像。
从下载过程当中能够看到咱们以前说起的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并不是单一文件。下载过程当中给出了每一层的ID前12位,而且下载结束后,给出该镜像完整的sha256的摘要,以确保下载一致性。git

二.使用镜像启动容器实例

使用命令:docker run从镜像启动容器实例。github

$ docker run -it --rm ubuntu:16.04 bash

docker run就是运行容器的命令,简要的说明一下上面用到的参数。
-it:这是2个参数,一个是-i:交互式操做,一个-t:终端。
--rm:这个参数说明容器退出以后随之将其删除。默认状况,不使用--rm参数启动的容器在退出以后不会当即删除,除非使用命令明确删除:docker rm
ubuntu:16.04:指定使用ubuntu:16.04这个镜像为基础启动容器
bash:放在镜像名以后的是命令,即:启动容器以后在容器中执行的命令web

使用exit命令退出容器。docker

三.列出镜像

使用docker image ls命令列出当前已经下载到本地的镜像。shell

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               0b1edfbffd27        4 days ago          113MB
hello-world         latest              e38bc07ac18e        2 weeks ago         1.85kB

输出列表中包含了仓库名,标签,镜像ID,建立时间和所占用的空间。
镜像ID则是镜像的惟一标识,一个镜像能够对应多个标签(不一样标签下的同一个镜像的ID值相同)。json

四.删除本地镜像

$ docker image rm <镜像id>

五.定制镜像

镜像的定制实际上就是定制每一层所添加的配置和文件,定制镜像有2种方式:commit,Dockerfile。ubuntu

经过commit命令定制镜像

使用镜像启动容器实例以后,在容器内部作的全部修改,均可以使用commit命令将容器存储层保存为镜像。如:bash

$ docker commit --author "zhangsan@xxx.com" --message "modify default index page content" webserver nginx:v2

--author指定修改的做者,而--message则是记录本次修改的内容,webserver为容器名称,nginx:v2为须要保存为的镜像仓库名和标签。

慎用docker commit命令保存镜像!制做镜像应该使用Dockerfile实现。使用docker commit命令保存镜像存在一些缺陷:
首先,在对容器进行配置时,会涉及多个文件的修改或添加,但其实有些文件是不须要保存为镜像的,若是不进行当心清理,会致使最终保存的镜像文件过于臃肿。
其次,使用命令方式意味着全部对镜像的操做都是黑箱的,不利于重现镜像制做的步骤,以及后期的维护。

经过Dockerfile定制镜像

经过Dockerfile定制镜像就是把每一层修改、安装、构建、操做的命令都写入一个脚本,用这个脚原本构建、定制镜像,那么以前说起的没法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。
Dockerfile是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,所以每一条指令的内容,就是描述该层应当如何构建。

使用了docker build命令进行镜像构建,其格式为:

docker build [选项] <上下文路径/URL/->

例如: $ docker build -t nginx:v3 .

docker build的工做原理

首先咱们要理解docker build的工做原理。Docker在运行时分为Docker引擎(也就是服务端守护进程)和客户端工具。Docker的引擎提供了一组REST API,被称为Docker Remote API,而如docker命令这样的客户端工具,则是经过这组API与Docker引擎交互,从而完成各类功能。所以,虽然表面上咱们好像是在本机执行各类Docker功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成的。也由于这种C/S设计,让咱们操做远程服务器的Docker引擎变得垂手可得。
当咱们进行镜像构建的时候,并不是全部定制都会经过RUN指令完成,常常会须要将一些本地文件复制进镜像,好比经过COPY指令,ADD指令等。而docker build命令构建镜像,其实并不是在本地构建,而是在服务端,也就是Docker引擎中构建的。那么在这种C/S架构中,如何才能让服务端得到本地文件呢?这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build命令得知这个路径后,会将路径下的全部内容打包,而后上传给Docker引擎。这样Docker引擎收到这个上下文包后,展开就会得到构建镜像所需的一切文件。若是在Dockerfile中这么写:“COPY ./package.json /app/”,这并非要复制执行docker build命令所在的目录下的package.json ,也不是复制Dockerfile所在目录下的 package.json ,而是复制上下文(context)目录下的package.json。所以,COPY这类指令中的源文件的路径都是相对路径。这也是初学者常常会问的为何“COPY ../package.json /app”或者“COPY /opt/xxxx /app”没法工做的缘由,由于这些路径已经超出了上下文的范围,Docker引擎没法得到这些位置的文件。若是真的须要那些文件,应该将它们复制到上下文目录中去。
如今就能够理解刚才的命令docker build -t nginx:v3 .中的这个.其实是在指定上下文的目录,docker build命令会将该目录下的内容打包交给Docker引擎以帮助构建镜像。
若是观察docker build输出,咱们其实已经看到了这个发送上下文的过程:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
...

理解构建上下文对于镜像构建是很重要的,避免犯一些不该该的错误。好比有些初学者在发现COPY /opt/xxxx /app不工做后,因而干脆将Dockerfile放到了硬盘根目录去构建,结果发现docker build执行后,在发送一个几十GB的东西,极为缓慢并且很容易构建失败。那是由于这种作法是在让docker build打包整个硬盘,这显然是使用错误。
通常来讲,应该将Dockerfile置于一个空目录下,或者项目根目录下。若是该目录下没有所需文件,那么应该把所需文件复制一份过来。若是目录下有些东西确实不但愿构建时传给Docker引擎,那么能够用.gitignore同样的语法写一个.dockerignore ,该文件是用于剔除不须要做为上下文传递给Docker引擎的。那么为何会有人误觉得“.”是指定Dockerfile所在目录呢?这是由于在默认状况下,若是不额外指定Dockerfile的话,会将上下文目录下的名为“Dockerfile”的文件做为构建镜像须要的Dockerfile。这只是默认行为,实际上Dockerfile的文件名并不要求必须为Dockerfile,并且并不要求必须位于上下文目录中,好比能够用“-f ../Dockerfile.php”参数指定某个文件做为Dockerfile 。
固然,通常你们习惯性的会使用默认的文件名Dockerfile,以及会将其置于镜像构建上下文目录中。

docker build的用法

docker build的基本语法为:docker build [选项] <上下文路径/URL/->,从语法中能够很明显地看出该命令支持多种构建方式.

1.从本地文件系统构建

$ docker build -t nginx:v3 .

上述构建操做包含2个参数:
"-t"指定镜像标签名称
"."指定构建上下文路径

2.从Git仓库构建

$ docker build https://github.com/nuccch/docker_test#:8.14

这行命令指定了构建所需的Git仓库,而且指定默认的master分支,构建目录为/8.14/,而后Docker就会本身去 git clone这个项目、切换到指定分支、并进入到指定目录后开始构建。
说明: 从Git仓库中构建Docker镜像是在实际项目中使用得比较多的方式,开发者只须要将代码提交到指定Git仓库的指定分支,测试只须要从该仓库的分支上构建Docker镜像便可.

3.用给定的tar压缩包构建

$ docker build http://server/context.tar.gz

若是所给出的URL不是个Git仓库,而是个tar压缩包,那么Docker引擎会下载这个包,并自动解压缩,以其做为上下文,开始构建。

4.从标准输入中读取Dockerfile进行构建

$ docker build - < Dockerfile

或者

$ cat Dockerfile | docker build -

若是标准输入传入的是文本文件,则将其视为Dockerfile ,并开始构建。
注意: 这种形式因为直接从标准输入中读取Dockerfile的内容,它没有上下文,所以不能够存在像其余方法那样能够将本地文件COPY进镜像之类的事情。

5.从标准输入中读取上下文压缩包进行构建

$ docker build - < context.tar.gz

若是发现标准输入的文件格式是gzip,bzip2以及xz的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。

【参考】 http://blog.daocloud.io/principle-of-docker-image/ 深刻分析 Docker 镜像原理 https://yq.aliyun.com/articles/68477 Docker镜像原理和最佳实践

相关文章
相关标签/搜索