Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。
先来看一下我们最常用的centos的Dockerfile
在hub.docker.com中所有centos
FROM scratch
MAINTAINER The CentOS Project <cloud-ops@centos.org>
ADD c68-docker.tar.xz /
LABEL name="CentOS Base Image" \
vendor="CentOS" \
license="GPLv2" \
build-date="2016-06-02"
# Default command
CMD ["/bin/bash"]
含义:
FROM scratch
这里引用了一个父镜像. 我们通常在使用tomcat或者jdk的时候, 他的父类镜像是centos. 而centos的父类镜像是scratch, scratch是所有镜像的基础镜像
MAINTAINER The CentOS Project <cloud-ops@centos.org>
MAINTAINER是备注的意思, 这是哪个团队,哪个人写的
ADD c68-docker.tar.xz /
这个参数后面讲解
LABEL name="CentOS Base Image" \
vendor="CentOS" \
license="GPLv2" \
build-date="2016-06-02"
LABEL顾名思义,就是描述的含义
# Default command
CMD ["/bin/bash"]
表示运行/bin/bash.
我们通常在运行docker run -it lxl/centos的时候, 有时候加/bin/bash,有时候不加. 那么什么时候加, 什么时候不加呢?
其实加和不加都是可以的....因为这里已经给我们自动加了/bin/bash, 如果不加就是用默认的, 如果加了, 就相当于有两个/bin/bash, 他只会执行一个
1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2. 指令按照顺序, 从上到下, 一条指令就是一层
3. #表示注释
4. 每条指令都会创建一个新的镜像层, 并对镜像进行提交
1. docker从基础镜像运行一个容器
2. 执行一条指令并对容器修改
3. 执行类似docker commit的操作提交一个新的镜像层
4. docker在基于刚提交的镜像运行一个新容器
5. 执行dockerfile中的下一条指令直到所指令都执行完成
基础镜像, 当前镜像是基于哪一个镜像
镜像维护者的姓名, 邮箱地址
容器构建时需要运行的命令
当前容器对外暴露的端口号
指定在创建容器后, 终端默认登录进来的工作目录, 一个落脚点
没有指定, 进入到容器的根目录
用来在构建镜像的过程中设置环境变量
这个环境你变量可以在后续的任务Run指令中使用, 这就如同在命令前面指定了环境变量前缀一样, 也可以在其他指令中直接使用这些环境变量.
举个例子:
ENV MY_PATH /usr/home
WORKDIR $MY_PATH
这就是说, 进入到容器以后, 直接进入的工作目录不是根目录, 而是/usr/home
ADD 和 COPY一起说
他俩都有将宿主机指定目录下的文件拷贝到到镜像中的含义.
ADD比COPY更强大.
ADD有拷贝并解压的含义
例如:
容器数据卷, 用于数据保存和持久化
指定一个容器启动时需要运行的命令,
Dockerfile中可以有多个CMD命令, 但只有最后一个生效, CMD会被docker run之后的参数替代
和CMD有相同之处
指定一个容器启动时要运行的命令
ENTRYPOINT的目的和CMD一样, 都是在绑定容器启动程序及参数.
不同之处是, ENTRYPOINT 不会被docker run后面的参数代替, 而是追加
子镜像继承自父类镜像以后, 父镜像的onbuild就会被触发,
这就相当于一个触发器, 满足一定条件的时候触发
Docker hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的.
最基础的base镜像是scratch, 这是所有镜像的祖先
目标: 练习使用WORKDIR, FROM, EVN, RUN, CMD命令
以centos镜像为例. 我们看
1) 设置进入容器的目录不是根目录
2) 为centos安装vim和ifconfig命令
FROM scratch
MAINTAINER LXL<23413@11.com
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo "success"
CMD /bin/bash
下面来详细看看其含义
基础镜像
FROM scratch
指定镜像维护的作者和邮箱
MAINTAINER LXL<23413@11.com
设置环境变量mypath
ENV MYPATH /usr/local
设置进入容器的默认目录是/usr/local
WORKDIR $MYPATH
安装vim和net-tools工具
RUN yum -y install vim
RUN yum -y install net-tools
设置端口号是80
EXPOSE 80
运行命令,打印success
CMD echo "success"
运行命令, 进入/bin/bash
CMD /bin/bash
docker build -f Dockerfile2 -t mycentos:1.3 .
docker run -it mycentos:1.3 /bin/bash
docker history 镜像ID
这个命令可以查询镜像构建的各个层
CMD: dockerfile中可以有多个CMD指令,但是只有最后一个生效. CMD会被docker run中最后的参数替换
查看tomcat的dockerfile.
.....
最后几行
RUN set -e \
&& nativeLines="$(catalina.sh configtest 2>&1)" \
&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
&& nativeLines="$(echo "$nativeLines" | sort -u)" \
&& if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
最后一行是启动tomcat的命令. 所以, 我们运行tomcat镜像的时候, 会启动tomcat
下面, 我们在命令行中使用其他CMD命令. 按照规则, docker run中最后的参数将替换dockerfile中的参数
docker run -it -p 8080:8080 docker.io/tomcat ls -l
运行结果:
没有启动tomcat,而是进入了查看当前目录的文件.
ENTRYPOINT: 执行命名, 和CMD类似, 不同的是, ENTRYPOINT命令不会被docker run中的命令替换, 而是被追加
我们来看一个案例, curl http://ip.cn 是查询当前网络信息
第一步: 编写一个dockerfile
FROM docker.io/centos
MAINTAINER lxl < 23242@qq.com
RUN yum install -y curl
CMD ["curl", "-s", "https://www.ip.cn"]
第二步: 构建dockerfile
docker build -f Dockerfile3 -t myip .
第三步: 运行容器
docker run -it myip
运行结果
您现在的 IP:**.**.**
所在地理位置:北京市 联通
GeoIP: Beijing, China
第四步: 我们还想查看header. 于是追加一个参数-i即可
如果使用CMD就会以docker run中的命令替换dockerfile, 这时我们应该使用ENTRYPOINT.
FROM docker.io/centos
MAINTAINER lxl < 23242@qq.com
RUN yum install -y curl
ENTRYPOINT ["curl", "-s", "https://www.ip.cn"]
重新build, 然后在docker run启动的时候增加 -i命令
docker run -it myip2 -i
文件名叫Dockerfile. 固定叫法
文件内容如下
From ubuntu
MAINTAINER lxl
CMD echo 'hello docker'
docker build -t demo-docker .
domo-docker: 是生成的新的docker镜像的名字.
. 表示的是文件生成在当前目录
构建的时候, 首先会判断基础镜像是否存在, 如果不存在, 则下载
docker image demo-docker
我们看到生产了一个64.2M的镜像. 版本定义了一个最新版本
docker run demo-docker
运行镜像, 打印输出hello docker
以上我们就自己定义了一个dockerfile,并运行起来了.
FROM docker.io/centos
MAINTAINER LXL<234@QQ.COM
CMD ["/bin/bash"]
增加了触发器
ONBUILD RUN echo "onbuild starting ...... 886"
docker build -f dockerfile4 -t centos03 .
这引用的父类镜像是centos03
FROM centos03
MAINTAINER LXL<234@QQ.COM
CMD ["/bin/bash"]
docker build -f dockerfile5 -t child-centos04 .
练习COPY ADD命令
按照如下操作执行
touch c.txt
apache-tomcat-9.0.8.tar.gz
jdk.tar.gz
其中后两个文件是tomcat和jdk的压缩包, 我们提前下载好,放到文件夹里即可. 如下图所示:
下载tomcat
sudo curl -OL https://mirror.bit.edu.cn/apache/tomcat/tomcat-9/v9.0.35/bin/apache-tomcat-9.0.35.tar.gz
下载jdk
sudo curl -OL https://www.oracle.com/webapps/redirect/signon?nexturl=https://download.oracle.com/otn/java/jdk/8u251-b08/3d5a2bb8f8d4428bbe94aed7ec7ae784/jdk-8u251-linux-x64.tar.gz
FROM docker.io/centos
# 设置dockerfile的作者和邮箱
MAINTAINER lxl < 234@qq.com
# 拷贝文件到指定目录并解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local
ADD jdk-8u251-linux-x64.tar.gz /usr/local
# 定义环境变量
ENV WORKPATH /usr/local
# 设定工作目录
WORKDIR $WORKPATH
# 设置jdk和tomcat的环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.35
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_BASE/bin
# 设定端口号
EXPOSE 8080
# 启动并运行tomcat
CMD $WORKPATH/apache-tomcat-9.0.35/bin/startup.sh && tail -F $WORKPATH/apache-tomcat-9.0.35/logs/catalina.out
docker run -it tomcat9
在本地输入localhost:8080. 看到tomcat启动页