zl程序教程

您现在的位置是:首页 >  其它

当前栏目

6. Dockerfile详解

详解 Dockerfile
2023-09-27 14:25:57 时间
一、Dockerfile 概念

Docker 镜像是一个特殊的文件系统 除了提供容器运行时所需的程序、库、资源、配置等文件外 还包含了一些为运行时准备的一些配置参数 如匿名卷、环境变量、用户等 。镜像不包含任何动态数据 其内容在构建之后也不会被改变。


镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本 用这个脚本来构建、定制镜像 那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。


Dockerfile 是一个文本文件 其内包含了一条条的指令(Instruction) 每一条指令构建一层 因此每一条指令的内容 就是描述该层应当如何构建。有了 Dockerfile 当我们需要定制自己额外的需求时 只需在 Dockerfile 上添加或者修改指令 重新生成 image 即可 省去了敲命令的麻烦。


 Dockfile最多不超过128层, 也就是一个docker最多128行


1.1. Dockerfile的体系结构


先来看一下我们最常用的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是备注的意思, 这是哪个团队,哪个人写的
表示运行/bin/bash. 我们通常在运行docker run -it lxl/centos的时候, 有时候加/bin/bash,有时候不加. 那么什么时候加, 什么时候不加呢? 其实加和不加都是可以的....因为这里已经给我们自动加了/bin/bash, 如果不加就是用默认的, 如果加了, 就相当于有两个/bin/bash, 他只会执行一个


1.2. dockerfile的编写规则


1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数


2. 指令按照顺序, 从上到下, 一条指令就是一层


3. #表示注释


4. 每条指令都会创建一个新的镜像层, 并对镜像进行提交

 

1.3 docker执行dockerfile的流程


1. docker从基础镜像运行一个容器


2. 执行一条指令并对容器修改


3. 执行类似docker commit的操作提交一个新的镜像层


4. docker在基于刚提交的镜像运行一个新容器


5. 执行dockerfile中的下一条指令直到所指令都执行完成

 

1.4 dockerfile的保留字指令


FROM:


基础镜像, 当前镜像是基于哪一个镜像


2.MAINTAINER:


镜像维护者的姓名, 邮箱地址


3.RUN:


容器构建时需要运行的命令


4.EXPOSE:


当前容器对外暴露的端口号


5.WORKDIR:


指定在创建容器后, 终端默认登录进来的工作目录, 一个落脚点

没有指定, 进入到容器的根目录

 


6.ENV:


用来在构建镜像的过程中设置环境变量

这个环境你变量可以在后续的任务Run指令中使用, 这就如同在命令前面指定了环境变量前缀一样, 也可以在其他指令中直接使用这些环境变量.

举个例子: 

ENV MY_PATH /usr/home

WORKDIR $MY_PATH

这就是说, 进入到容器以后, 直接进入的工作目录不是根目录, 而是/usr/home


7.ADD COPY


ADD 和 COPY一起说

他俩都有将宿主机指定目录下的文件拷贝到到镜像中的含义.

ADD比COPY更强大. 

ADD有拷贝并解压的含义例如:ADD c68-docker.tar.xz /这个含义就是, 拷贝到根目录, 并进行解压


8.VOLUME:


容器数据卷, 用于数据保存和持久化


9.CMD:


指定一个容器启动时需要运行的命令, 

Dockerfile中可以有多个CMD命令, 但只有最后一个生效, CMD会被docker run之后的参数替代


10.ENTRYPOINT:


和CMD有相同之处

指定一个容器启动时要运行的命令

ENTRYPOINT的目的和CMD一样, 都是在绑定容器启动程序及参数.

不同之处是, ENTRYPOINT 不会被docker run后面的参数代替, 而是追加


11.ONBUILD:


子镜像继承自父类镜像以后, 父镜像的onbuild就会被触发, 

这就相当于一个触发器, 满足一定条件的时候触发


微信图片_20220513144231.png


 二. Dockerfile案例2.1 Base镜像


 Docker hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的.

 最基础的base镜像是scratch, 这是所有镜像的祖先

 

2.2 案例1


目标: 练习使用WORKDIR, FROM, EVN, RUN, CMD命令

 

以centos镜像为例. 我们看

 微信图片_20220513144258.png

 

1. 目标: 下面我们要处理的就是以上两个问题:


 1) 设置进入容器的目录不是根目录


 2) 为centos安装vim和ifconfig命令


2. 编写dockerfile


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


3. 构建dockerfile, 生成镜像


docker build -f Dockerfile2 -t mycentos:1.3 .


4. 运行构建好的镜像


docker run -it mycentos:1.3 /bin/bash


5. 查看dockerfile的构建历史


docker history 镜像ID


这个命令可以查询镜像构建的各个层


 微信图片_20220513144442.png


 

2.3 案例2--CMD命令 和 EntryPoint的区别


1. CMD命令


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 then \

 echo 2 $nativeLines \

 exit 1; \

EXPOSE 8080

CMD [ catalina.sh , run ]


最后一行是启动tomcat的命令. 所以, 我们运行tomcat镜像的时候, 会启动tomcat


微信图片_20220513144525.png


下面, 我们在命令行中使用其他CMD命令. 按照规则, docker run中最后的参数将替换dockerfile中的参数


docker run -it -p 8080:8080 docker.io/tomcat ls -l


运行结果:


微信图片_20220513144551.png


 没有启动tomcat,而是进入了查看当前目录的文件.

 

2. ENTRYPOINT命令


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 . 


微信图片_20220513144641.png


第三步: 运行容器


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


1. 新建文件, 创建一个DockerFile


文件名叫Dockerfile. 固定叫法


文件内容如下


From ubuntu

MAINTAINER lxl

CMD echo hello docker 


2. 构建Dockerfile


docker build -t demo-docker .


domo-docker: 是生成的新的docker镜像的名字. 


. 表示的是文件生成在当前目录


构建的时候, 首先会判断基础镜像是否存在, 如果不存在, 则下载


微信图片_20220513144848.png


3. 查看构建好的镜像


docker image demo-docker


微信图片_20220513144915.png


我们看到生产了一个64.2M的镜像. 版本定义了一个最新版本


4. 运行镜像


docker run demo-docker

微信图片_20220513144942.png运行镜像, 打印输出hello docker

 

以上我们就自己定义了一个dockerfile,并运行起来了.

 

2.4 案例3--ONBUILD命令 


第一步: 构建一个父类镜像


FROM docker.io/centos

MAINTAINER LXL 234 QQ.COM

CMD [ /bin/bash ]

增加了触发器

ONBUILD RUN echo onbuild starting ...... 886 


第二步: 编译父类镜像


 docker build -f dockerfile4 -t centos03 .

微信图片_20220513145023.png


第三步: 构建一个子类镜像


这引用的父类镜像是centos03

FROM centos03

MAINTAINER LXL 234 QQ.COM

CMD [ /bin/bash ]


第四步: 编译子类镜像


docker build -f dockerfile5 -t child-centos04 .

微信图片_20220513145110.png


 2.5 案例4


练习COPY ADD命令


 按照如下操作执行


1. 创建一个/docker/tomcat9文件夹, 里面放三个文件

touch c.txt

apache-tomcat-9.0.8.tar.gz

jdk.tar.gz

其中后两个文件是tomcat和jdk的压缩包, 我们提前下载好,放到文件夹里即可. 如下图所示:微信图片_20220513145130.png

下载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


2. 在/docker/tomcat9文件夹下创建一个dockerfile文件


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


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


3. 构建dockerfile


微信图片_20220513145214.png


4. docker run 运行镜像


docker run -it tomcat9


5. 验证tomcat启动结果


在本地输入localhost:8080. 看到tomcat启动页 

DockerFile理解和使用 Dockerfile构建镜像是以基础镜像为基础的,Dockerfile是一个文本文件,内容是用户编写的一些docker指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。 Dockerfile的基本指令有十三个,分别是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD
Dockerfile Docker系列文章: 此篇是Docker系列的第五篇,大家一定要按照我做的Demo都手敲一遍,印象会更加深刻的,加油! • 为什么要学习Docker • Docker基本概念 • Docker镜像基本原理 • Docker容器数据卷