DockerFile文件解析
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
编写和执行过程:
- 按照规范编写dockerfile文件
- docker build命令执行
- docker run运行
小结
Docker执行Dockerfile的大致流程
(1)docker从基础镜像运行一个容器
(2)执行一条指令并对容器作出修改
(3)执行类似docker commit的操作提交一个新的镜像层
(4)docker再基于刚提交的镜像运行一个新容器
(5)执行dockerfile中的下一条指令直到所有指令都执行完成
小总结
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件的运行态。
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
保留字指令
FROM
基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要运行的命令
EXPOSE
当前容器对外暴露出的端口
WORKDIR
指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV
用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,
比如:WORKDIR $MY_PATH
ADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY
类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
COPY src dest
COPY ["src", "dest"]
VOLUME
容器数据卷,用于数据保存和持久化工作
CMD
指定一个容器启动时要运行的命令
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
ENTRYPOINT
指定一个容器启动时要运行的命令
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数,但是不会覆盖参数,会追加到后面的指令
ONBUILD
当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
案例(制作mycentos)
Base镜像(scratch)
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
精简版的centos是没有vim和ifconfig等命令工具的
mycentos
创建一个带有网路工具和vim的镜像
dockerfile文件
FROM centos
MAINTAINER liutao<liutao4_3@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
build
docker build -f ./dockerfil1 -t mycentos:v1.0 .
查看images
进入容器之后,可以使用ifconfig
CMD/ENTRYPOIN的区别
CMD,docker run 。。。 指令,会把指令覆盖掉
ENTRYPOIN,docker run。。。指令,会在指令后面追加
ONBUILD
子类容器继承父类容器,在父类容器下ONBUILD加入命令,子类容器build过程中将会执行父类容器下的ONBUILD下命令。
一个centos的dockerfile中加入ONBUILD RUN echo ‘father images‘
build子镜像centos时候就会执行相应命令
案例
COPY和ADD
Build 上下文的概念
在使用 docker build 命令通过 Dockerfile 创建镜像时,会产生一个 build 上下文(context)。所谓的 build 上下文就是 docker build 命令的 PATH 或 URL 指定的路径中的文件的集合。在镜像 build 过程中可以引用上下文中的任何文件,比如我们要介绍的 COPY 和 ADD 命令,就可以引用上下文中的文件。
默认情况下 docker build -t testx . 命令中的 . 表示 build 上下文为当前目录。当然我们可以指定一个目录作为上下文,比如下面的命令:
docker build -t testx /home/nick/hc
我们指定 /home/nick/hc 目录为 build 上下文,默认情况下 docker 会使用在上下文的根目录下找到的 Dockerfile 文件。
COPY 和 ADD 命令不能拷贝上下文之外的本地文
一、ADD指令
ADD指令的功能是将主机构建环境(上下文)目录中的文件和目录、以及一个URL标记的文件 拷贝到镜像中。
其格式是: ADD 源路径 目标路径
如:
复制代码
#test
FROM ubuntu
MAINTAINER hello
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1 data1
ADD data2 data2
ADD zip.tar /myzip
复制代码
有如下注意事项:
1、如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。
如果目标路径不存在,则会自动创建目标路径。
2、如果源路径是个文件,且目标路径是不是以 / 结尾,则docker会把目标路径当作一个文件。
如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;
如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。
如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
3、如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。
如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。
4、如果源文件是个归档文件(压缩文件),则docker会自动帮解压。
5 、对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身
二、COPY指令
COPY指令和ADD指令功能和使用方式类似。只是COPY指令不会做自动解压工作。
docker container内运行的进程,在宿主机上,通过ps也是能够查到的,但是在不熟悉命令的时候,无法快速找到他们的关系。
这里科普一个基础命令 docker top
三、制作zookeeper镜像的dockerfile
1.前期准备:
2. Dockerfile
FROM centos
MAINTAINER liutao<liutao4_3@163.com>
#把zookeeper添加到容器中并解压
ADD zookeeper-3.4.6.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
RUN yum -y install net-tools
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#把宿主机当前上下文的zoo.cfg拷贝到容器/usr/local/zookeeper/conf路径下,并且在${zookeeper}下创建myid文件
COPY zoo.cfg /usr/local/zookeeper-3.4.6/conf/
RUN mv /usr/local/zookeeper-3.4.6/ zookeeper
RUN mkdir /usr/local/zookeeper/tmp
RUN touch /usr/local/zookeeper/tmp/myid
RUN echo 1 >> /usr/local/zookeeper/myid
COPY jdk8 /usr/local/jdk8/
#配置java与zookeeper环境变量
ENV JAVA_HOME /usr/local/jdk8
ENV ZOOKEEPER_HOME /usr/local/zookeeper
ENV PATH $PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin
#容器运行时监听的端口
EXPOSE 2181 2888 3888
CMD /bin/bash
3.build镜像
docker build -t myzoo .
4. 进入容器修改zoo.cfg文件,启动服务
ipconfig
修改配置文件
zkServer.sh start
其它一些小技巧
1. 找到容器的id
docker ps
2. 找到容器在宿主机上映射后的进程信息
docker top 容器id
就会得到类似下面的信息,其中PID是容器内进程在宿主机上的pid,ppid是容器内进程在宿主机上的父进程pid
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
到此结束,后续将用docker run -p来将容器对外界进行映射,构建分布式集群