小知识:
传统虚拟机:
模拟出一套硬件及操作系统,有自己的内核,体积大
docker:
有自己的文件系统,不模拟硬件系统,运行于宿主机内核之上,没有自己的内核,不同的docker容器之间互相不影响,体积小易进行持续集成及虚拟化操作
系统要求:
需centos6.5以上
概念介绍:
镜像(image)
镜像是一种轻量级可执行的独立软件包,用来打包软件运行环境和给予运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件
简而言之,打包好的运行环境或组件就成为镜像文件,docker通过镜像文件生成容器,一个镜像文件可以生成多个同时运行的容器实例互不影响
Docker容器(Container)
Docker利用容器独立运行一个或一组应用,容器是用镜像创建的运行实例,容器可以启动停止,开始,删除,容器直接相互隔离,可以看作一个微缩的Linux环境
仓库(Registry)
用来集中存放镜像文件的地方
docker images
- Docker镜像含有启动容器所需的文件系统和内容,因此用其创建并启动容器
- 采用分层构建机制,最底层为bootfs,其他为rootfs
- bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源;
- rootfs:位于bootfs之上,表现为docker容器的根文件系统; l传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为“只读”模式,完整性自检完成后将其重新挂载为读写模式;ldocker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载”技术额外挂载一个“可写”层
- 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image)v最上层为“可读写”层,其下的均为“只读”层
- advanced multi-layered unification filesystem:高级多层统一文件系统v用于为Linux文件系统实现“联合挂载”
- aufs是之前的UnionFS的重新实现,2006年由Junjiro Okajima开发;
- Docker最初使用aufs作为容器文件系统层,它目前仍作为存储后端之一来支持;
- aufs的竞争产品是overlayfs,后者自从3.18版本开始被合并到Linux内核;
- docker的分层镜像,除了aufs,docker还支持btrfs, devicemapper和vfs等
- 在Ubuntu系统下,docker默认Ubuntu的aufs;而在CentOS7上,用的是devicemapper;
- Docker Registry中的镜像通常由开发人员制作,而后推送至“公共”或“私有”Registry上保存,供其他人员使用,例如“部署”到生产环境;
镜像操作
镜像的生成途径
- Dockerfile
- 基于容器制作
- Docker Hub automated builds
基于容器制作镜像
使用示例
- 启动容器执行需要的修改操作
docker run --rm -it --name bbox1 busybox
- 查看修改
docker logs bbox1
- 提交镜像ɰ
docker commit bbox1 mageedu/busybox/httpd:latest
- 提交镜像,修改默认运行的命令
docker commit --change=‘CMD [“httpd”, "-h /data/httpd/htdocs“, “-f”]’
-c “EXPOSE 80” bbox1 mageedu/busybox/httpd:v0.
镜像导入和导出
在容器添加使用数据卷
- 挂载数据卷到docker容器中,实现主机和docker容器数据共享
- 为docker run命令使用-v选项即可使用Volume
docker run -it -v /宿主机绝对目录:/容器内目录 镜像名
例如:
[root@yunac ~]# docker run -it -v /opt/serverfile:/clentfile dunyun-tomcat
注意
如果出现容器卷不可读写情况在命令上加上权限
–privileged=true
例如:
[root@yunac ~]# docker run -it -v /opt/serverfile:/clentfile --privileged=true dunyun-tomcat
Dockerfile
- copy
拷贝文件到镜像中
COPY src desc
- src:要复制的源文件或目录,支持使用通配符l
- desc:目标路径,即正在创建的image的文件系统路径;建议为使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;
文件复制准则 - src必须是build上下文中的路径,不能是其父目录中的文件
- 如果src是目录,则其内部文件或子目录会被递归复制,但src目录自身不会被复制
- 如果指定了多个src,或在src中使用了通配符,则dest必须是一个目录,且必须以/结如果
- desc事先不存在,它将会被自动创建,这包括其父目录路径
ADD
将宿主机目录下的文件拷贝到镜像中,且ADD会自动处理URL和解压tar压缩包,类似于COPY指令
ADD指令
ADD src desc
操作准则
同COPY指令
- 如果
<src>
为URL且<dest>
不以/结尾,则<src>
指定的文件将被下载并直接被创建为<dest>
;如果<dest>
以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
- 如果
<src>
是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开; - 如果
<src>
有多个,或其间接或直接使用了通配符,则<dest>
必须是一个以/结尾的目录路径;如果<dest>
不以/结尾,则其被视作一个普通文件,<src>
的内容将被直接写入到<dest>
;
WORKDIR
用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
WORKDIR dirpath
在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径l另外,WORKDIR也可调用由ENV指定定义的变量
例如
WORKDIR /var/loglWORKDIR $STATEPATH
VOLUME
用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
- VOLUME mountpoint
- 如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
EXPOSE
用于为容器打开指定要监听的端口以实现与外部通信
EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]
<protocol>
用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
EXPOSE指令可一次指定多个端口,例如:EXPOSE 11211/udp 11211/tcp
ENV
用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用
- 调用格式为
$variable_name
或${variable_name}
ENV <key> <value>
- 第一种格式中,
<key>
之后的所有内容均会被视作其<value
>的组成部分,因此,一次只能设置一个变量; - 第二种格式可用一次设置多个变量,每个变量为一个
"<key>=<value>"
的键值对,如果<value>
中包含空格,可以以反斜线(\)
进行转义,也可通过对<value>
加引号进行标识;另外,反斜线也可用于续行; - 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
RUN
用于指定docker build过程中运行的程序,其可以是任何命令
RUN <command>
- 第一种格式中,
<command>
通常是一个shell命令,且以“/bin/sh -c”
来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>
命令停止容器时,此进程接收不到SIGTERM信号; - 第二种语法格式中的参数是一个JSON格式的数组,其中
<executable>
为要运行的命令,后面的<paramN>
为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”
来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。 RUN ["/bin/bash", "-c", "<executable>", "<param1>"]
CMD
指定一个容器启动时要运行的命令
- 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
- RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时
- CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
CMD <command>
或CMD [“<executable>”, “<param1>”, “<param2>”]
或CMD ["<param1>","<param2>"]
- 前两种语法格式的意义同RUNɝ第三种则用于为ENTRYPOINT指令提供默认参数
ENTRYPOINT
类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
- 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
- 不过,docker run命令的–entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
ENTRYPOINT <command>
ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
- docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
- Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
USER
用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID
- 默认情况下,container的运行身份为root用户
SyntaxɰUSER <UID>|<UserName>
- 需要注意的是,
<UID>
可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败
ONBUILD
用于在Dockerfile中定义一个触发器
- Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件
- 在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器
SyntaxɰONBUILD <INSTRUCTION>
- 尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
- 使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuildɝ在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败
编写Dockerfile
例一:
1.在宿主机根目录下新建一个Dockerfile文件
[root@yunac mydocker]# vim Dockerfile
2.编写如下Dockerfile指定
# volume test
FROM dunyun-tomcat
VOLUME ["/mydocker1","mydocker2"]
CMD echo "文件挂载中"
CMD /bin/bash
等价于:docker run -it -v /mydocker1:/mydocker1 dunyun-tomcat
3.通过Dockerfile文件构建一下镜像
- -t xxyy/dunyun-tomcat:给构建的镜像重新命名
- -f 指定Dockerfile文件路径,如果在当前目录下直接打出文件名即可
[root@yunac mydocker]# docker build -f Dockerfile -t xxyy/dunyun-tomcat .
- -f :指定Dockerfile文件
- -t :指定新创建的镜像名
4.构建完成后images ps一下看看新生成的镜像
5.用新构建的镜像生成运行容器
[root@yunac mydocker]# docker run -it xxyy/dunyun-tomcat
6.运行后直接就会生成mydocker1,mydocker2数据卷
例二:
- 1.pull一个centos7镜像
[root@localhost mydocker]# docker pull centos:7
- 2.编写Dockerfile文件,yum安装vim和基础组件
vim Dockerfile
FROM docker.io/centos
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 8080
CMD echo $(MYPATH)
CMD echo "运行成功"
CMD /bin/bash
- 3.通过Dockerfile文件构建一个新的镜像
[root@localhost mydocker]# docker build -f Dockerfile -t centos .
构建完成!
注意:
- dockerfile每条指令都会创建一个新的镜像层,并对镜像进行提交
- 每条保留字指令都必须为大写字母,并且后面至少要跟随一个参数
- 指令从上到下升序执行
docker执行dockerfile的流程:
- docker从基础镜像运行一个容器
- 执行类似docker commit 的操作提交一个新的镜像层
- 再基于刚提交的镜像层运行一个容器
- 执行dockerfile中的下一条指令知道所有指令执行完成