前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6. Dockerfile详解

6. Dockerfile详解

作者头像
用户7798898
发布2020-09-27 16:51:24
1.2K0
发布2020-09-27 16:51:24
举报

一、Dockerfile 概念

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

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

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

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

1.1. Dockerfile的体系结构

先来看一下我们最常用的centos的Dockerfile

在hub.docker.com中所有centos

代码语言:javascript
复制
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"]

含义:

代码语言:javascript
复制
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. dockerfile的编写规则

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

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

3. #表示注释

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

1.3 docker执行dockerfile的流程

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

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

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

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

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

1.4 dockerfile的保留字指令

  1. FROM:
代码语言:javascript
复制
基础镜像, 当前镜像是基于哪一个镜像
  1. MAINTAINER:
代码语言:javascript
复制
镜像维护者的姓名, 邮箱地址
  1. RUN:
代码语言:javascript
复制
容器构建时需要运行的命令
  1. EXPOSE:
代码语言:javascript
复制
当前容器对外暴露的端口号
  1. WORKDIR:
代码语言:javascript
复制
指定在创建容器后, 终端默认登录进来的工作目录, 一个落脚点
没有指定, 进入到容器的根目录
  1. ENV:
代码语言:javascript
复制
用来在构建镜像的过程中设置环境变量
这个环境你变量可以在后续的任务Run指令中使用, 这就如同在命令前面指定了环境变量前缀一样, 也可以在其他指令中直接使用这些环境变量.

举个例子: 
ENV MY_PATH /usr/home
WORKDIR $MY_PATH

这就是说, 进入到容器以后, 直接进入的工作目录不是根目录, 而是/usr/home
  1. ADD & COPY
代码语言:javascript
复制
ADD 和 COPY一起说
他俩都有将宿主机指定目录下的文件拷贝到到镜像中的含义.
ADD比COPY更强大. 
ADD有拷贝并解压的含义

例如:
  1. VOLUME:
代码语言:javascript
复制
容器数据卷, 用于数据保存和持久化
  1. CMD:
代码语言:javascript
复制
指定一个容器启动时需要运行的命令, 
Dockerfile中可以有多个CMD命令, 但只有最后一个生效, CMD会被docker run之后的参数替代
  1. ENTRYPOINT:
代码语言:javascript
复制
和CMD有相同之处
指定一个容器启动时要运行的命令

ENTRYPOINT的目的和CMD一样, 都是在绑定容器启动程序及参数.
不同之处是, ENTRYPOINT 不会被docker run后面的参数代替, 而是追加
  1. ONBUILD:
代码语言:javascript
复制
子镜像继承自父类镜像以后, 父镜像的onbuild就会被触发, 
这就相当于一个触发器, 满足一定条件的时候触发

二. Dockerfile案例

2.1 Base镜像

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

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

2.2 案例1

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

以centos镜像为例. 我们看

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

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

  2) 为centos安装vim和ifconfig命令

2. 编写dockerfile

代码语言:javascript
复制
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

下面来详细看看其含义

代码语言:javascript
复制
基础镜像
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, 生成镜像

代码语言:javascript
复制
docker build -f Dockerfile2 -t mycentos:1.3 .

4. 运行构建好的镜像

代码语言:javascript
复制
docker run -it mycentos:1.3 /bin/bash

5. 查看dockerfile的构建历史

代码语言:javascript
复制
docker history 镜像ID

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

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

1. CMD命令

代码语言:javascript
复制
CMD: dockerfile中可以有多个CMD指令,但是只有最后一个生效. CMD会被docker run中最后的参数替换

查看tomcat的dockerfile.

代码语言:javascript
复制
.....
最后几行

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中的参数

代码语言:javascript
复制
docker run -it -p 8080:8080 docker.io/tomcat ls -l

运行结果:

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

2. ENTRYPOINT命令

代码语言:javascript
复制
ENTRYPOINT: 执行命名, 和CMD类似, 不同的是, ENTRYPOINT命令不会被docker run中的命令替换, 而是被追加

我们来看一个案例, curl http://ip.cn 是查询当前网络信息

第一步: 编写一个dockerfile

代码语言:javascript
复制
FROM docker.io/centos

MAINTAINER lxl < 23242@qq.com

RUN yum install -y curl

CMD ["curl", "-s", "https://www.ip.cn"]

第二步: 构建dockerfile

代码语言:javascript
复制
docker build -f Dockerfile3 -t myip . 

第三步: 运行容器

代码语言:javascript
复制
docker run -it myip

运行结果

代码语言:javascript
复制
您现在的 IP:**.**.**
所在地理位置:北京市 联通
GeoIP: Beijing, China

第四步: 我们还想查看header. 于是追加一个参数-i即可

如果使用CMD就会以docker run中的命令替换dockerfile, 这时我们应该使用ENTRYPOINT.

代码语言:javascript
复制
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命令

代码语言:javascript
复制
docker run -it myip2 -i

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

文件名叫Dockerfile. 固定叫法

文件内容如下

代码语言:javascript
复制
From ubuntu
MAINTAINER lxl
CMD echo 'hello docker'

2. 构建Dockerfile

代码语言:javascript
复制
docker build -t demo-docker .

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

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

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

3. 查看构建好的镜像

代码语言:javascript
复制
docker image demo-docker

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

4. 运行镜像

代码语言:javascript
复制
docker run demo-docker

运行镜像, 打印输出hello docker

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

2.4 案例3--ONBUILD命令

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

代码语言:javascript
复制
FROM docker.io/centos
MAINTAINER LXL<234@QQ.COM

CMD ["/bin/bash"]

增加了触发器
ONBUILD RUN echo "onbuild starting ...... 886"

第二步: 编译父类镜像

代码语言:javascript
复制
 docker build -f dockerfile4 -t centos03 .

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

代码语言:javascript
复制
这引用的父类镜像是centos03
FROM centos03
MAINTAINER LXL<234@QQ.COM

CMD ["/bin/bash"]

第四步: 编译子类镜像

代码语言:javascript
复制
docker build -f dockerfile5 -t child-centos04 .

2.5 案例4

练习COPY ADD命令

按照如下操作执行

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

touch c.txt

apache-tomcat-9.0.8.tar.gz

jdk.tar.gz

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

代码语言:javascript
复制
下载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文件

代码语言:javascript
复制
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

3. 构建dockerfile

4. docker run 运行镜像

代码语言:javascript
复制
docker run -it tomcat9

5. 验证tomcat启动结果

代码语言:javascript
复制
在本地输入localhost:8080. 看到tomcat启动页 

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Dockerfile 概念
    • Dockfile最多不超过128层, 也就是一个docker最多128行
      • 1.1. Dockerfile的体系结构
        • 1.2. dockerfile的编写规则
          • 1.3 docker执行dockerfile的流程
            • 1.4 dockerfile的保留字指令
            • 二. Dockerfile案例
              • 2.1 Base镜像
                • 2.2 案例1
                  • 1. 目标: 下面我们要处理的就是以上两个问题:
                  • 2. 编写dockerfile
                  • 3. 构建dockerfile, 生成镜像
                  • 4. 运行构建好的镜像
                  • 5. 查看dockerfile的构建历史
                • 2.3 案例2--CMD命令 和 EntryPoint的区别
                  • 1. CMD命令
                  • 2. ENTRYPOINT命令
                  • 1. 新建文件, 创建一个DockerFile
                  • 2. 构建Dockerfile
                  • 3. 查看构建好的镜像
                  • 4. 运行镜像
                • 2.4 案例3--ONBUILD命令
                  • 第一步: 构建一个父类镜像
                  • 第二步: 编译父类镜像
                  • 第三步: 构建一个子类镜像
                  • 第四步: 编译子类镜像
                • 2.5 案例4
                  • 1. 创建一个/docker/tomcat9文件夹, 里面放三个文件
                  • 2. 在/docker/tomcat9文件夹下创建一个dockerfile文件
                  • 3. 构建dockerfile
                  • 4. docker run 运行镜像
                  • 5. 验证tomcat启动结果
              相关产品与服务
              容器镜像服务
              容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档