Loading

四、DockerFile解析

Dockerfile简介

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

构建三步骤:

  • 编写Dockerfile文件:必须符合file规范

  • docker build:docker build -f /mydocker/Dockerfile -t mrlinxi/centos . 通过docker build获得一个自定义的镜像

  • docker run

文件长什么样?下面就是我们使用的centos的Dockerfile

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
# default cmd
CMD ["/bin/bash"]

6.2 DockerFile构建过程解析

Dockerfile内容基础知识:

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

  • 指令按照从上到下,顺序执行

  • #表示注释

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

Docker执行Dockerfile的大致流程:

  • (1)docker从基础镜像运行一个容器

  • (2)执行一条指令并对容器作出修改

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

  • (4)docker再基于刚提交的镜像运行一个新容器

  • (5)执行dockerfile中的下一条指令直到所有指令都执行完成

总结:

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料

  • Docker镜像是软件的交付品

  • Docker容器则可以认为是软件的运行态。

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

img

  1. Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
  2. Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
  3. Docker容器,容器是直接提供服务的。

6.3 DockerFile体系结构(保留字指令)

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"]

ADDCOPY的区别在于ADD在复制后会自动解压缩和处理URL,而COPY仅仅进行复制。

VOLUME:容器数据卷,用于数据保存和持久化工作;

CMD:指定一个容器启动时要运行的命令;Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换(后面案例会具体说明);

img

ENTRYPOINT:指定一个容器启动时要运行的命令;ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数;

CMDENTRYPOINT的区别是CMD存在多个时只有最后一个生效以及CMD会被docker run之后的参数替换;而ENTRYPOINT是追加命令。

ONBUILD:当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

6.4 案例

1. Base镜像(scratch)

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

2. 自定义镜像mycentos

Hub默认CentOS镜像什么情况:

img

自定义mycentos目的使我们自己的镜像具备如下:

登陆后的默认路径、vim编辑器、查看网络配置ifconfig支持

安装Centos镜像之后会默认进入根目录,但是不支持vim也不支持ifconfig,因此利用DockerFile创建的时候安装好相关插件以及修改默认根目录

① 编写自定义镜像的Dockerfile

我们在宿主机的/mydocker文件夹下,新建一个Dockerfile:vim Dockerfile2,写入下面的内容

from centos  --继承自本地镜像
MAINTAINER ylc<xxx@qq.com>  --作者和邮箱

ENV mypath /tmp  --环境变量
WORKDIR $mypath   --默认登陆的进来目录

RUN yum -y install vim  --安装vim
RUN yum -y install net-tools 

EXPOSE 80  --指定端口

CMD echo $MYPATH  --打印内容
CMD echo “success-----ok”
CMD /bin/bash

② 构建自定义镜像——docker build

docker build -f /root/mydocker/Dockerfile2 -t mycentos:1.3 .

build语句最后面一个**.**表示当前目录

image-20211225122602582

③ 运行自定义镜像——docker run

docker run -it mycentos:1.3

image-20211225122733796

可以看到默认进入的目录是/tmp

④ 列出镜像的变更历史

docker history 镜像名

image-20211225123109903

每一步都产生了一个镜像,镜像都是层层叠加的,内部像千层饼一样

3. CMD/ENTRYPOINT 镜像案例

CMD/ENTRYPOINT都是指定一个容器启动时要运行的命令

① CMD镜像案例

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

这里以tomcat为例,tomcat的dockerfile最后一句是img

正常我们启动tomcat的命令是:docker run -it -p 主机端口:8080 tomcat

现在我们执行这样一句命令:docker run -it -p 8888:8080 tomcat ls -l

这样就相当于在tomcat的dockerfile后面又加了一句CMD ls -l,因此会覆盖掉之前的语句。

img

此时tomcat并没有运行,只是查看了默认路径下的文件。

img

② ENTRYPOINT镜像案例

docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合。

制作CMD版可以查询IP信息的容器:

FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]

crul命令解释:curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。curl是将下载文件输出到stdout。

使用命令:curl http://www.baidu.com,执行后,www.baidu.com的html就会显示在屏幕上了。这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的header。要全部显示,请加参数 -i

构建镜像:docker build -f /mydocker/Dockerfile3 -t myip .

创建并启动容器:docker run myip

img

现在返回的是网页的html文件。

如果我们希望显示 HTTP 头信息,就需要加上 -i 参数:

img

加上-i后报错了。我们可以看到可执行文件找不到的报错,executable file not found。

之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s https://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:

docker run myip curl -s https://ip.cn -i

img

为了解决上述问题,制作ENTROYPOINT版查询IP信息的容器

FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
docker build -f /mydocker/Dockerfile4 -t myip2
docker run myip2 -i

img

现在只用追加一个-i即可打印请求头跟html文件。

③ ONBUILD案例

直接在Dockerfile4上修改,追加一句ONBUILD RUN echo "father onbuild-----------10086"

然后使用Dockerfile4构建镜像:docker build -f /mydocker/Dockerfile4 -t myip_father .

复制Dockerfile3命名为Dockerfile5,修改Dockerfile5,直接继承自Dockerfile4:

FROM myip_father
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]

使用Dockerfile5构建镜像:docker build -f /mydocker/Dockerfile5 -t myip_son .

img

posted @ 2021-12-29 20:55  炒焖煎糖板栗  阅读(110)  评论(0编辑  收藏  举报