Docker开发实践笔记二

镜像是容器运行基础,容器是镜像运行后的形态,两者紧密相连又有不一样。html

一、镜像的概念java

镜像是一个包含程序运行必要依赖环境和代码的只读文件,它采用分层的文件系统,将每一次改变以读写层的形式增长到原来的只读文件上。nginx

1.1镜像与容器web

若是将容器理解为一套程序运行的虚拟环境,那么镜像就是用来构建这个环境的模板。经过同一镜像,咱们能够构造出不少相互独立但运行环境同样的容器。redis

镜像的最底层必须是一个称为启动文件(bootfs)的镜像,用户不会与这一层直接打交道。bootfs的上层镜像叫做根镜像(rootfs),它在一般状况下是一个操做系统,如Ubuntu、Debina和CentOS等。docker

(素材来源与网络)shell

二、本地镜像的管理ubuntu

2.1查看centos

docker images
docker images ub* //使用通配符

查看结果相似下表
REPOSITORY TAG IMAGE_ID CREATED VIRTUAL SIZE
centos laster 10009deww3 45 hours ago 199MB

REPOSITORY是仓库名称,通常用来存放同一类型的镜像,其名称由建立者指定。安全

命令规则:

一、[namespace\ubuntu]:由命名空间和实际的仓库名组成,中间用”\“隔开,若是要提交到DOcker Hub 非官方的仓库名必需要遵照此规则。

二、[ubuntu]:只有仓库名,它属于顶级命名空间,该空间只能用于官方的镜像。本地也能够这种命名,可是没法分发到DOcker Hub上进行分享。

三、【dl.dockerpool.com:5000\ubuntu:12.04]:指定URL路径的方式。通常是用于本身搭建的Hub或者第三方Hub上,dl.dockerpool.com:5000是第三方Hub的主机名及端口。

TAG用于区分同一仓库中的不一样镜像。若是未指定,默认为laster

IMAGE_ID每一个镜像都有一个字符串类型、长为64位的HashID,同容器ID同样,用来惟一标识一个镜像。通常取前面一部分只要在本机惟一标识一个镜像便可,和Git的CommitID规则相似。

CREATED镜像建立时间。

VIRTUAL SIZE镜像所占用的虚拟大小,该大小包含了全部共享文件的大小。

 

2.2下载

docker run命令运行一个镜像时,首先会在本地查找镜像,若是本地不存在会继续去Docker Hub上面搜索符合条件的镜像并将其下载下来运行。

docker pull ubuntu:13.10
13.10: Pulling from library/ubuntu //本地已经有了
6599cadaf950: Pull complete 
23eda618d451: Pull complete 
f0be3084efe9: Pull complete 
52de432f084b: Pull complete 
a3ed95caeb02: Pull complete 
Digest: sha256:15b79a6654811c8d992ebacdfbd5152fcf3d165e374e264076aa435214a947a3
Status: Downloaded newer image for ubuntu:13.10
docker search wordpress //Docker Hub搜索符合条件的镜像

搜索结果会显示
镜像的名称(NAME)、描述(DESCRIPTION)、
镜像评分(STARS)(越高代表质量越好)、
是否为官方镜像(OFFICIAL)、是否使用了自动构建(AUTOMATED)

有时运行的镜像本地没有,会从Docker Hub上获取,能够经过docker pull 命令预先下载到本地,再使用docker run命令。

docker pull ubuntu

2.3删除

删除的镜像若是被容器所依赖,即使容器已中止了,也仍然须要依赖镜像,这里不能直接删除,若是必定要强制删除可使用-f参数。可是为了安全起见建议先中止容器,删除容器后再删除镜像。

docker rmi 镜像ID或名称 //比删除容器命令多了一个i 
docker rmi -f  镜像ID或名称 //强制删除镜像

 

三、建立本地镜像

建立本地镜像有三种方式:

一、经过镜像导出成tar文件的方式,而后导入镜像建立一个新镜像。(这种方式在 Docker开发实践笔记一 容器的导入和导出已说明)

二、使用commit命令保存对基础镜像的修改建立出新的镜像

运行镜像容器后,对容器进行修改,而后使用commit提交建立。

docker run -i -t ubuntu
修改容器,好比安装软件、修改配置等。

docker commit -m="Message" --author="LIU" 运行的容器ID myDOcker/redis:v1

若是须要对上面的镜像再修改,进入容器内更新后再使用上面的命令提交一个新版本镜像便可。

docker commit -m="Message" --author="LIU" 运行的容器ID myDOcker/redis:v2

三、使用Dockerfile文件建立镜像(推荐方式)

Dockerfile用来建立一个自定义的image,包含了用户指定的软件依赖等。

下面是一个DOckerfile文件实例,本例只是介绍语法无任何实际意义。

#version: 1.00

#指定待扩展的父级镜像。除注释外文件开头必须是一个FROM指令
FROM ubuntu:latest 

#做者信息
MAINtAINER jiuwu "jiuwu@qq.com" 

#设置root用户为后续命令的执行者
USET root 

#执行操做
RUN apt-age update
RUN apt-get install -y nginx

#使用&&拼接命令
RUN touch test.txt && echo "abc" >> abc.txt

#对外暴露端口
EXPOSE 80 8080 1038

#添加文件 第一个是源文件,第二个是要添到的容器中的目标路径
ADD abc.txt /opt/

#添加文件件
ADD /webapp /opt/webapp

#添加网络文件
ADD https://www.baidu.com/logo.jpg /opt/

#设置环境变量
ENV WEBAPP_PORT=9000

#设置工做目录
WORKDIR /opt/

#设置启动命令,只能出现一次,后面的会覆盖前面的
ENTRYPOINT ["ls"]

#设置启动参数,只能出现一次,后面的会覆盖前面的
CMD ["-a","-l"]

#设置卷
VOLUME ["/data","/var/www"]

#设置子镜像的触发操做(当有镜像以此镜像为父镜像时,会执行下面的操做)
ONBUILD ADD ./app/src
ONBUILD RUN echo "on build excuted " >> onbuild.txt

下面是对上述指令的详细说明:

指令不区分大小写。可是,命名约定为所有大写。
全部Dockerfile都必须以FROM命令开始。 FROM命令会指定镜像基于哪一个基础镜像建立,接下来的命令也会基于这个基础镜像(译者注:CentOS和Ubuntu有些命令但是不同的)。FROM命令能够屡次使用,表示会建立多个镜像。具体语法以下:

FROM <image name>

1. MAINTAINER:设置该镜像的做者。语法以下:

MAINTAINER <author name>

2. RUN:在shell或者exec的环境下执行的命令。RUN指令会在新建立的镜像上添加新的层面,接下来提交的结果用在Dockerfile的下一条指令中。语法以下:

RUN 《command》
RUN apt-get update //这种形式使用/bin/sh环境中执行的命令
RUN ["apt-get","update"] //直接使用系统调用exec来执行

多个命令能够用&&链接执行
RUN apt-get update && apt-get install nginx

这里须要注意一下,由于一次RUN会增长一个新层,全部最佳实践是减小RUN次数,尽可能将多个操做合并到RUN中一次执行。

3. ADD:复制文件指令。它有两个参数<source>和<destination>。destination是容器内的路径。source能够是URL或者是启动配置上下文中的一个文件。语法以下:

ADD 《src》 《destination》

若是源文件是主机上的zip或tar形式的压缩文件,Docker会先解压缩,而后将文件添加到镜像指定的位置,若是是URL指定的网络压缩文件则不解压。

4. CMD:提供了容器启动时默认执行的命令。 Dockerfile只容许使用一次CMD指令。 使用多个CMD会抵消以前全部的指令,只有最后一个指令生效。 CMD有三种形式:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

5. EXPOSE:指定容器在运行时监听的端口。语法以下:

EXPOSE <port>; //多个端口使用空格隔开

EXPOSE 80 8080 9000

运行容器时经过参数-P(大写)便可将EXPOSE里所指定的端口映射到主机上另外的随机端口,其它容器或主机就能够经过映射后的端口与此容器通讯。同时,咱们也能够经过-p(小写)参数将DOckerfile中EXPOSE中没有列出的端口设置成公开的。

6. ENTRYPOINT:配置给容器一个可执行的命令,这意味着在每次使用镜像建立容器时一个特定的应用程序能够被设置为默认程序。同时也意味着该镜像每次被调用时仅能运行指定的应用。相似于CMDDocker只容许一个ENTRYPOINT,多个ENTRYPOINT会抵消以前全部的指令,只执行最后的ENTRYPOINT指令。语法以下:

ENTRYPOINT ["executable", "param1","param2"]
ENTRYPOINT command param1 param2

7. WORKDIR:指定RUNCMDENTRYPOINT命令的工做目录。语法以下:

WORKDIR /path/to/workdir

8. ENV:设置环境变量。它们使用键值对,增长运行程序的灵活性。语法以下:

ENV <key> <value>

在运行容器的时候能够经过-e参数来设置或修改环境变量:

docker run -e WEBAPP_PORT=8000 -e WEBAPP_HOST=www.test.com ....

9. USER:镜像正在运行时设置一个UID。语法以下:

USER <uid> //好比:USER root

10. VOLUME:受权访问从容器内到主机上的目录。语法以下:

VOLUME ["/data"]

此挂载通常是在运行容器的时候指定,由于要关联到宿主机上,这样分享Dockerfile就不方便了。多个容器能够经过同一个挂载点共享数据,即使其中一个容器已经中止,挂载点也仍然能够访问,只有当挂载点的容器引用所有消失时,挂载点才会自动删除。

11. ONBUILD: 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行。

ONBUILD中的命令会在当前镜像的子镜像构建时执行。能够把ONBUILD命令当成父镜像的Dockerfile传递给子镜像的Dockerfile的指令。

在子镜像的构建过程当中,Docker 会在执行Dockerfile中的任何指令以前,先执行父镜像经过ONBUILD传递的指令。

当从给定镜像构建新镜像时,ONBUILD指令颇有用。例如,你可能会在一个语言栈镜像中使用ONBUILD,语言栈镜像用于在Dockerfile中构建用户使用相应语言编写的任意软件,正如 Ruby 的ONBUILD变体

使用ONBUILD构建的镜像应用一个单独的标签,例如:ruby:1.9-onbuild或ruby:2.0-onbuild。

在ONBUILD中使用ADD或COPY时要格外当心。若是新的构建上下文中缺乏对应的资源,“onbuild”镜像会灾难性地失败。添加一个单独的标签,容许Dockerfile的做者作出选择,将有助于缓解这种状况。

 

最后再重点说明一下CMD和ENTRYPOINT命令:

两个命令都是用来指定容器启动时默认运行的命令。

假如,咱们指定的ENTRYPOINT是这样的:

ENTRYPOINT ["ls","-l"]

并构建出名为 jiuwu/newImage的镜像,那么 docker run jiuwu/newImage的运行结果与docker run ubuntu ls -l是同样,而docker run jiuwu/newImage -a 的运行结果与docker run ubuntu ls -l -a 同样。

否则发现,ENTRYPOINT与CMD的区别在于运行容器时添加在镜像名以后的参数,对ENTRYPOINT 是拼接,而对CMD则是覆盖。咱们能够在运行容器的时候使用--entrypoint来覆盖Dockerfile中的指定:

docker run --entrypoint echo jiuwu/newImage "hello docker"

输出为:hello docker

一般状况下风们会将ENTRYPOINT 和CMD搭配起来使用。ENTRYPOINT 用于指定须要运行的命令,CMD用于指定运行命令所须要的参数(这是个知识点,记住)。示例以下:

ENTRYPOINT  ["ls"]
CMD ["-a","-l"]

 

Dockerfile 最佳实践

相关文章
相关标签/搜索