码迷,mamicode.com
首页 > 其他好文 > 详细

Dockerfile 浅析

时间:2021-01-02 11:10:04      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:poi   情况下   and   容器   vendor   tar   odi   enc   oca   

一、Dockerfile 简介

1、Dockerfile 是什么

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

 

2、镜像实例化为容器的三个步骤

2.1、编写 Dockerfile 文件

2.2、根据 Dockerfile 文件,使用 docker build 命令来构建镜像

2.3、docker run 命令启动容器

 

3、Dockerfile 内容和格式

我们这里以 centos 为例,登录 docker hub 官网: https://registry.hub.docker.com/

3.1、搜索 centos

技术图片

3.2、选择官方镜像

技术图片

3.3、Dockerfile 具体内容如下:

技术图片

  • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • 指令按照从上到下,顺序执行
  • # 表示注释
  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

 

二、Dockerfile 、Docker 镜像、Docker 容器的区别

从应用软件的角度来看, Dockerfile、Docker 镜像与 Docker 容器分别代表软件的三个不同阶段
Dockerfile 是软件的原材料
Docker 镜像是软件的交付品
Docker 容器则可以认为是软件的运行态
Dockerfile 面向开发, Docker 镜像成为交付标准, Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石

2.1、Dockerfile:需要定义一个 Dockerfile ,Dockerfile 定义了进程需要的一切东西, Dockerfile 涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace 的权限控制)等等.

2.2、Docker 镜像,在用 Dockerfile 定义一个文件之后, docker build 时会产生一个 Docker 镜像,当运行 Docker 镜像时,会真正开始提供服务.

2.3、Docker容器,容器是直接提供服务的.

 

三、Dockerfile 构建过程解析

Docker 保留字及其代表含义

Dockerfile 保留字 说明
FROM  当前新镜像是基于哪个镜像的
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令
EXPOSE 当前镜像对外暴露的端口
ENV 镜像构建过程中的环境变量
WORKDIR 容器启动后,终端默认登录进来的工作目录(启动容器时的一个落脚点)
ADD 将宿主机目录下的文件拷贝进镜像且 ADD 命令会自动处理 URL 和解压 tar 压缩包
COPY 类似 ADD ,拷贝文件和目录到镜像中.将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定一个容器启动时要运行的命令, Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效, CMD 会被 docker run 之后的参数替换
ENTRYPOINT 指定一个容器启动时要运行的命令, ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数
ONBUILD 当构建一个被继承的 Dockerfile 时运行命令,父镜像在被子继承后父镜像的 ONBUILD 被触发

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.1、案例一(自定义 mycentos 镜像)

我们先看一下官方拉取的镜像,存在如下的问题

技术图片

针对上面的问题,我们是否可以自定义一个 centos , 这个自定义的镜像可以支持 vim 、ifconfig 命令

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"

CMD ["/bin/bash"]

我们可以参考官方镜像的 Dockerfile 来自定义 Dockerfile ,然后通过自定义的 Dockerfile 来构建符合我们要求的镜像

3.1.1、新建一个目录,编写自定义 Dockerfile 文件

// 继承 centos 镜像
FROM centos 
// 环境变量路径
ENV MYPATH /usr/local/mydocker
// 进入容器的时候,默认会进入该入境
WORKDIR $MYPATH
// 支持 vim 命令
RUN yum -y install vim
// 支持 curl 命令
RUN yum -y install curl
// 支持查询 ip
RUN yum -y install net-tools
// 容器启动之后对外暴露的端口
EXPOSE 80
// Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效
CMD echo $MYPATH
CMD echo "mycentos for xiao mao mao is ok"
// 实际生效的命令
CMD [ "curl", "-s", "http://www.baidu.com" ]

3.1.2、使用 docker build 命令构建镜像

// -f 参数是为了指定 Dockerfile 的位置(可以是绝对路径,也可是相对当前操作路径),默认的情况下标准的命名就是 Dockerfile,如果文件的命名是 Dockerfile ,可以省略不写
// /root/mydocker 是构建镜像的构件存放目录, Dockerfile 中通过 ADD 来将该目录下的构件添加进容器(它与 Dockerfile 存在的路径不是一回事)
// 整体的含义就是通过 /root/mydocker/Dockerfile 文件来构建镜像
docker build -f /root/mydocker/Dockerfile -t xiaomaomao/centos:use-cmd /root/mydocker

3.1.3、运行镜像使之成为容器

docker run -it --name mycentos xiaomaomao/centos:use-cmd

技术图片

3.1.4、我们这里是通过命令 docker run -it --name mycentos xiaomaomao/centos:use-cmd 来运行容器的,还记不记得我们自定义的 Dockerfile 里面有编写 CMD 命令,这个命令就是我们运行 Docker 镜像的默认命令,并且多个 CMD 命令只有最后一个生效,实际上是相当于运行如下的命令

docker run -it --name mycentos xiaomaomao/centos:use-cmd curl -s http://www.baidu.com

也就是运行镜像的时候就会直接去访问百度的首页

3.1.5、下面我们又有了新的需求,希望访问百度首页的时候能够返回报文头(需要在 curl 命令后面加上参数 -i),如果想要完成需求,完整的命令应该如下

docker run -it --name mycentos xiaomaomao/centos:use-cmd curl -s -i http://www.baidu.com

执行上述的命名确实是能够完成需求,因为 curl -s -i http://www.baidu.com 命令会覆盖我们在 Dockerfile 里面默认的 curl -s http://www.baidu.com 命令

但是呢,我现在不想去覆盖 Dockerfile 里面的命令,只想通过添加参数 -i 的方式去实现需求,也就是执行下面这条命令实现需求

docker run -it --name mycentos xiaomaomao/centos:use-cmd -i

执行完命令之后,结果出现了报错,因为 docker run 命令的标准形式是这样的

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

-i 不是具体的 CMD 命令,所以会出现报错

技术图片

那么有没有其它办法呢,答案是有的,这个时候就需要是用 ENTRYPOINT 保留字来代替 CMD 保留字

重写修改 Dockerfile 如下,把 CMD 换成 ENTRYPOINT

FROM centos
ENV MYPATH /usr/local/mydocker
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install curl
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "mycentos for xiao mao mao is ok"
// 将 CMD 改为 ENTRYPOINT
ENTRYPOINT [ "curl", "-s", "http://www.baidu.com" ]

重新构建奖项,然后运行镜像,此时加上参数 -i 就返回了头部信息

技术图片

总结 CMD 和 ENTRYPOINT 的区别

CMD: 运行容器的时候,最后加的参数 -i 会覆盖 Dockerfile 里面 CMD 保留字定义的命令,使整个命令变成如下(这种命令是错误的,因为 -i 不是 CMD 命令)

docker run -it --name mycentos xiaomaomao/centos:use-cmd -i

ENTRYPOINT: 运行容器的时候,最后加的参数 -i 会被当做参数追加到 Dockerfile 里面 ENTRYPOINT 保留字定义的命令里面,也就是当使用如下命令时

docker run -it --name mycentos xiaomaomao/centos:use-entrypoint -i

就相当于

docker run -it --name mycentos xiaomaomao/centos:use-entrypoint curl -s -i http://www.baidu.com

  

3.2、案例二、自定义 tomcat 镜像

3.2.1、编写 Dockerfile 文件

技术图片

tomcat-dockerfile 文件内容如下

# 继承基础镜像
FROM centos
# 维护者姓名和邮箱地址
MAINTAINER xiaomaomao<xiaomaomao@163.com>
# 环境变量
ENV MYPATH /usr/local
# 把 java 与 tomcat 添加到容器中指定目录下
ADD jdk-8u261-linux-x64.tar.gz $MYPATH/
ADD apache-tomcat-8.5.60.tar.gz $MYPATH/
# 安装 vim 编辑器
RUN yum -y install vim
# 设置工作访问时候的 WORKDIR 路径,进入容器时的默认工作目录
WORKDIR $MYPATH/apache-tomcat-8.5.60/
# 配置 java 与 tomcat 环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_261
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME $MYPATH/apache-tomcat-8.5.60
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 把宿主机当前上下文的 xiaomaomao.txt 拷贝到容器 /usr/local/webapps 路径下
COPY xiaomaomao.txt $CATALINA_HOME/webapps/
# 添加容器数据卷
VOLUME $CATALINA_HOME/webapps/
# 容器运行时监听的端口
EXPOSE  8080
# 启动时运行tomcat 并打印日志
CMD $CATALINA_HOME/bin/startup.sh && tail -F $CATALINA_HOME/logs/catalina.out

3.2.2、使用 docker build 构建镜像

技术图片

构建成功信息如下

技术图片

3.2.3、查看镜像

技术图片

3.2.4、启动镜像

技术图片

3.2.5、查看镜像是否启动成功,启动成功后进入容器

技术图片

3.2.6、查看 tomcat 容器的挂载的容器数据卷

技术图片

宿主机目录

技术图片

容器目录

技术图片

对比可以发现,容器的挂载目录是我们在 Dockerfile 中定义的,宿主机挂载的目录是 Docker 帮我们随机生成的,两个目录里面的内容是相同的,并且经过测试,数据可以同步

3.2.7、宿主机的挂载目录新建一个 test 目录,在 test 目录下新建一个 a.jsp 文件,写入如下内容

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    hello i am xiao mao mao, when will you back?
  </body>
</html>

3.2.8、此时,由于通过容器数据卷同步信息,在容器的 webapps 下会有 test 目录

技术图片

3.2.9、访问 a.jsp

技术图片

3.2.10、同理,比如我们以后部署 war 包,也可以只通过操作宿主机,就可以将 war 包部署到容器内的 tomcat 中

 

Dockerfile 浅析

标签:poi   情况下   and   容器   vendor   tar   odi   enc   oca   

原文地址:https://www.cnblogs.com/xiaomaomao/p/14202525.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!