Docker系列-第六篇DockerFile解析

1.手动编写一个dockerfile文件,当然必须要符合file的规则

2.有了这个文件,直接docker build命令执行,获得一个自定义的镜像

3.run

1.是什么

Dockerfle 是一个文本格式的配置文件, 用户可以使用 Dockerfle 来快速创建自定义的镜像。

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

1.1三步骤

  • 编写Dockerfile文件
  • docker build
  • docker run

2.DockerFile构建过程解析

2.1Dockerfile内容基础知识

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

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

3:#表示注释

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

2.2Docker执行Dockerfile的大致流程

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

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

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

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

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

2.3小总结

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

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态。
    Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。


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

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

3、Docker容器,容器是直接提供服务的。

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

3.1FROM

基础镜像,当前新镜像是基于哪个镜像的

每个Dockerfile的第一挑指令必须是FROM,FROM指令指定一个已存在的镜像,后续指令都继续该镜像进行,这个镜像也称为基础镜像

3.2MAINTAINER

MAINTAINER指令没有具体的格式,建议一般使用姓名和邮箱

3.3RUN

镜像构建时需要运行的命令(即镜像制作过程中需要执行的命令)

每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,就会将此镜像层提交。

如果需要执行多条命令,可使用多行RUN命令,但经验告我,将多条指定通过\命令换行合并成一条,这样将减少锁构建的体积。原因,上面也已经说了,在镜像中每执行一条命令,都会形成新的镜像层,需要尽可能的较少镜像层,从而减少镜像的提示

3.4EXPOSE

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

3.5WORKDIR

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

可以用过-w标志在运行时覆盖工作目录

3.6ENV

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

ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,

比如:WORKDIR $MY_PATH

3.7ADD

将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

在ADD文件时,Docker通过目的地址参数末尾的字符来判断文件源是目录还是文件。如果目标地址以/结尾那么Docker就认为源位置指向的是一个目录。如果目的地址不是以/结尾,那么Docker就认为原文件指向的是文件。

ADD jdk-8u91-linux-x64.tar.gz /opt

是将宿主机当前目录下的 jdk-8u91-linux-x64.tar.gz 拷贝到容器/opt目录下 ,容器的目标路径必须的绝对路径。

一般将Dockerfile与需要添加到容器中的文件放在同一目录下,有助于编写来源路径

3.8COPY

类似ADD,拷贝文件和目录到镜像中。没有自动解压的功能
将从构建上下文目录中 的文件/目录复制到新的一层的镜像内的 位置

3.9VOLUME

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

3.10CMD

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

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

CMD指令用于执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,那么只有最后一个会被执行。

Docker run 命令可以覆盖CMD指令。如果在Dockerfile里指定了CMD指令,而同时在docker run命令行中也指定的要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。

如 CMD java app.jar 容器启动时启动app.jar应用

3.11ENTRYPOINT

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

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

区别:

可以在docker run 命令中覆盖CMD命令。

ENTRYPOINT指令提供的命令则不容易在启动容器时被覆盖。实际上docker run命令中指定的任何参数会被当做参数再次传递给ENTRYPOINT指令中指定的命令。

3.12ONBUILD

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

3.13USER

指定该镜像会以什么用户运行

3.13小结

4.案例

使用Dockerfile构建Java镜像入门1

  • step 1

    新建Dockerfile文件

    touch Dokcerfile
  • step 2

    编写Dockerfile脚本

    FROM centos:latest
    MAINTAINER "NIU GANG"<[email protected]>
    # 在opt目录下新建apps目录
    RUN  mkdir -p /opt/apps
    # 在当前目录下及和Dockerfile在一个目录下,将jdk安装包增加到镜像的opt/apps目录下
    # ADD目录会自动将 .tar.gz包进行解压
    ADD jdk-8u211-linux-x64.tar.gz /opt/apps
    # 在启动容器是执行命令
    CMD /opt/apps/jdk1.8.0_211/bin/java -version
  • step 3 构建镜像
    [[email protected] tools]# docker build -t niugang/java .
    Sending build context to Docker daemon  197.8MB
    Step 1/5 : FROM centos:latest
     ---> 9f38484d220f
    Step 2/5 : MAINTAINER "NIU GANG"<[email protected]>
     ---> Running in e4a4a0c1ffa9
    Removing intermediate container e4a4a0c1ffa9
     ---> a7f400aae1a7
    Step 3/5 : RUN  mkdir -p /opt/apps
     ---> Running in 49f2c1f076c0
    Removing intermediate container 49f2c1f076c0
     ---> 287c44707477
    Step 4/5 : ADD jdk-8u211-linux-x64.tar.gz /opt/apps
     ---> cf2dfbb373c8
    Step 5/5 : CMD /opt/apps/jdk1.8.0_211/bin/java -version
     ---> Running in 83d41700285a
    Removing intermediate container 83d41700285a
     ---> 79bf24642eb4
    Successfully built 79bf24642eb4
    Successfully tagged niugang/java:latest

对于 docker build -t niugang/java . 这个命令

-t 选项指定镜像名称 并读取当前(即.)目录中的Dockerfile文件

  • step 4 验证

    [[email protected] tools]# docker run --rm niugang/java
    java version "1.8.0_211"
    Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

    --rm 是启动并删除容器

    注意:

    最开始在启动docker run --rm niugang/java 会报

    /bin/sh: /opt/apps/jdk-8u211/bin/java: No such file or directory

    是因为当初认为ADD 增加 jdk-8u211-linux-x64.tar.gz 后解压的名称叫 jdk-8u211(感觉犯例了一个常识性的错误),但其实解压完成后的文件夹名称为1.8.0_211

使用Dockerfile构建Java镜像入门2

一般在安装JDK后需要设置JAVA_HOME 与PATH 这样就可以直接在命令中使用Java命令了,而须带路径参数

使用Dockerfile中的ENV指令来设置所需的环境变量

前提:

为了二次生成的镜像于之前的不重名,修改之前生成镜像的tag

docker tag 79bf24642eb4 niugang/java:1.0

修改之前的Dockerfile文件,修改后的文件内容如下

FROM centos:latest
MAINTAINER "NIU GANG"<[email protected]>
RUN  mkdir -p /opt/apps
ADD jdk-8u211-linux-x64.tar.gz /opt/apps
ENV JAVA_HOME /opt/apps/jdk1.8.0_211
ENV PATH $JAVA_HOME/bin:$PATH
CMD java -version

重新构建镜像

[[email protected] tools]# docker build -t niugang/java .
Sending build context to Docker daemon  197.8MB
Step 1/7 : FROM centos:latest
 ---> 9f38484d220f
Step 2/7 : MAINTAINER "NIU GANG"<[email protected]>
 ---> Using cache
 ---> a7f400aae1a7
Step 3/7 : RUN  mkdir -p /opt/apps
 ---> Using cache
 ---> 287c44707477
Step 4/7 : ADD jdk-8u211-linux-x64.tar.gz /opt/apps
 ---> Using cache
 ---> cf2dfbb373c8
Step 5/7 : ENV JAVA_HOME /opt/apps/jdk1.8.0_211
 ---> Running in 6117528026ae
Removing intermediate container 6117528026ae
 ---> 1b9e9c656a8e
Step 6/7 : ENV PATH $JAVA_HOME/bin:$PATH
 ---> Running in 5711715ae4eb
Removing intermediate container 5711715ae4eb
 ---> 82f94b6f5211
Step 7/7 : CMD java -version
 ---> Running in fcb8b117a0c2
Removing intermediate container fcb8b117a0c2
 ---> 9a26c48936a4
Successfully built 9a26c48936a4
Successfully tagged niugang/java:latest

通过上面输出的信息可以观察到,step2 step3 step4 这三个步骤直接从缓存中获取之前构建的镜像,而不是重新构建镜像

Dockerfile和构建和缓存

由于每一步的构建都会将结果提交未镜像,所以Docker的构建过程就显得非常聪明。它会将之前的镜像层看作缓存。

要想忽略缓存功能,可以使用docker build --no-cache标志

如 docker build --no-cache -t niugang/java .

自定义mycentos镜像

  • 新建Dockerfile

    touch Dockerfile
  • 编写Dockerfile
    FROM centos
    MAINTAINER ng<[email protected]>
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "success--------------ok"
    CMD /bin/bash
  • 构建

    docker build -t 新镜像名:TAG .

    参数:

    -f :指定要使用的Dockerfile路径;

    --no-cache :创建镜像的过程不使用缓存;

    -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;

  • 运行

? docker run -it 新镜像名:TAG

  • 列出镜像变更历史

? docker history 镜像ID

CMD/ENTRYPOINT案例镜像

共同特点:都是指定一个容器启动时要运行的命令

CMD

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

列如:

以下是运行tomcat镜像的命令

docker run -it -p 8888:8080 tomcat

从docker.hub上查看tomcat镜像的Dockerfile文件会发现最后有 CMD ["catalina.sh", "run"]

现在以如下方式启动:

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH \(CATALINA_HOME/bin:\)PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME

在tomcat的Dockerfile中设置的WORKDIR为/usr/local/tomcat

docker run -it -p 8888:8080 tomcat ls -l

[[email protected] mycmdip]# docker run -it -p 8888:8080 tomcat ls -l
total 124
-rw-r--r--. 1 root root  19534 Jul  4 20:56 BUILDING.txt
-rw-r--r--. 1 root root   5407 Jul  4 20:56 CONTRIBUTING.md
-rw-r--r--. 1 root root  57011 Jul  4 20:56 LICENSE
-rw-r--r--. 1 root root   1726 Jul  4 20:56 NOTICE
-rw-r--r--. 1 root root   3255 Jul  4 20:56 README.md
-rw-r--r--. 1 root root   7139 Jul  4 20:56 RELEASE-NOTES
-rw-r--r--. 1 root root  16262 Jul  4 20:56 RUNNING.txt
drwxr-xr-x. 2 root root   4096 Jul 18 02:55 bin
drwxr-sr-x. 2 root root    238 Jul  4 20:56 conf
drwxr-sr-x. 2 root staff    78 Jul 18 02:55 include
drwxr-xr-x. 2 root root   4096 Jul 18 02:54 lib
drwxrwxrwx. 2 root root      6 Jul  4 20:53 logs
drwxr-sr-x. 3 root staff   151 Jul 18 02:55 native-jni-lib
drwxr-xr-x. 2 root root     30 Jul 18 02:54 temp
drwxr-xr-x. 7 root root     81 Jul  4 20:53 webapps
drwxrwxrwx. 2 root root      6 Jul  4 20:53 work

以上说明:

ls -l 命令覆盖了Dockerfile中的catalina.sh run

NETRYPOINT

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

通过案列镜像对比

操作 1

执行CMD版查询IP信息的镜像

具体Dockerfile文件内容为:

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

构建镜像

运行镜像 会返回你当前的ip信息

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

为什么会出错:

我们可以看到可执行文件找不到的报错,executable file not found。

之前也提到过跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。

因此这里的 -i CMD而不是添加在原来的后面。而根本不是命令,所以自然找不到

操作2

制作ENTROYPOINT版查询IP信息的容器

具体Dockerfile文件内容为:

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

这样制作出的镜像在运行过程就不会报错了 ,就会显示出http头信息了

自定义tomcat9镜像

step1 在根目录下新建mytomcat9文件夹

mkdir mytomcat9

step2 上传jdk tomcat安装包

step3 新建Dockerfile文件

touch Dockerfile

step4 编写Dockerfile 内容如下

FROM         centos
MAINTAINER    niugang<[email protected]>
#把宿主机当前上下文的test.txt拷贝到容器/usr/local/路径下并重命名为test1.txt
COPY test.txt /usr/local/test1.txt
#把java与tomcat添加到容器中
ADD jdk-8u211-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.27.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_211
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.27
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.27
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE  8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.27/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.27/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.27/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.27/bin/logs/catalina.out

step5 构建镜像

docker build -t niugang/tomcat9 .

step6 运行容器

docker run -d -p 9080:8080 --name myt9  -v /mytomcat9/mywebapp/:/usr/local/apache-tomcat-9.0.27/webapps   -v /mytomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.27/logs niugang/tomcat9 --privileged=true

上述运行容器创建两个数据卷

第一个是将容器中的tomcat日志映射到宿主机上
第二个是 将tomcat中的webapps目录映射到宿主机上方便日后发布应用
也可以将容器中tomcat的配置conf文件夹映射到宿主机

step7 验证应用发布

在映射的/mytomcat9/mywebapp/ 新建test目录,test目录下新建index.html,写入helle world。

[[email protected] test]# pwd
/mytomcat9/mywebapp/test
[[email protected] test]# ll
总用量 4
-rw-r--r--. 1 root root 12 10月 23 21:30 index.html

5.小总结


微信公众号


JAVA程序猿成长之路
分享资源,记录程序猿成长点滴。专注于Java,Spring,SpringBoot,SpringCloud,分布式,微服务。

原文地址:https://www.cnblogs.com/niugang0920/p/12187068.html

时间: 2024-07-28 14:25:00

Docker系列-第六篇DockerFile解析的相关文章

Docker系列-第八篇Docker常用安装

一.总体步骤 1.搜索镜像 2.拉取镜像 3.查看镜像 4.启动镜像 5.停止容器 6.移除容器 二.安装Tomcat 2.1 docker push方式安装tomcat https://hub.docker.com/_/tomcat docker hub上每个镜像怎么使用,都有对应的说明,这个说明对于每个镜像的安装和使用都很有帮助 2.1.1.docker hub上面查找tomcat镜像 2.1.2.从docker hub上拉取tomcat镜像到本地 2.1.3.docker images查看

【Docker系列教程之四】Dockerfile入门

在上一篇的文章中,我们把 Docker 容器的工作流程剖析的十分清楚了,我们大体可以知道 Docker 组件协作运行容器可以分为以下几个过程: Docker 客户端执行 docker run 命令 Dockerdaemon 发现本地没有我们需要的镜像 daemon 从 DockerHub 下载镜像 下载完成后,镜像被保存到本地 Dockerdaemon 启动容器 了解了这些过程以后,我们再来理解这些命令就不会觉得很突兀了,下面我来给大家讲讲 Docker 常用的一些命令操作吧. Docker常用

Docker系列-第五篇Docker容器数据卷

1.是什么 在生产环境中使用 Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作 . 容器中的管理数据主要有两种方式 : 数据卷 ( Data Volumes ) : 容器内数据直接映射到本地主机环境: 数据卷容器( Data Volume Containers ) : 使用特定容器维护数据卷. 一句话:有点类似我们Redis里面的rdb和aof文件 将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的

【Windows编程】系列第六篇:创建Toolbar与Statusbar

上一篇我们学习了解了如何使用Windows GDI画图,该应用程序都是光光的静态窗口,我们使用Windows应用程序,但凡稍微复杂一点的程序都会有工具栏和状态栏,工具栏主要用于一些快捷功能按钮.比如典型的windows应用程序的上面是菜单栏,从菜单栏我们可以选择应用程序提供的各种功能,但是有的功能比较常用,且不能放在第一级菜单,需要进入二级.三级甚至更多的菜单才能选择.显然这样使用起来比较麻烦,于是这时候工具栏的作用就体现出来了,一般工具栏位于菜单栏的下面,但是位于客户窗口的上面.下面就是win

Docker系列-第七篇Docker构建SpringBoot应用

1.基于Dockerfile构建SpringBoot镜像 1.1准备工作 将SpringBoot项目通过maven打成jar包 mvn clean package #使用maven打包项目 1.2使用Dockerfile构建镜像 step1 在存放jar所在目录下创建Dockerfile文件 touch Dockerfile step2 编辑Dockerfile增加以下内容 FROM java:8 MAINTAINER niugang<[email protected]> RUN mkdir

黑马程序员系列第六篇 面向对象基础

ASP.Net+Android+IOS开发  .Net培训.期待与您交流! (前言:本篇文章主要依据毕向东老师的课程视频整理而成,如要详细学习,请观看毕老师视频  百度网盘链接地址:http://pan.baidu.com/s/1mgngVl2) 目录:1.面向对象三大特性    2.类和对象    3.内部类   1.面向对象三大特性    封装.继承.多态 封装 概念:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. 好处:将变化隔离:便于使用:提高重用性:安全性. 封装原则:将不需要

深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法

× 目录 [1]动态样式 [2]CSS类[3]setAttribute()[4]CSSRule对象添加[5]空样式覆盖[6]CSSRule对象删除 前面的话 我们可以通过计算样式来读取伪元素的样式信息,但是却无法使用javascript来直接操作伪元素,本文以一个需求解决为例,详细介绍脚本化伪元素的6种方法 需求说明 [1]为id=box的div元素添加content="前缀"的:before伪元素 [2]为已经添加:before伪元素的div元素删除伪元素  [注意]由于IE7-浏览

Docker系列:入门篇-安装docker

Docker 提供了两个版本:社区版 (CE) 和企业版 (EE). Docker 社区版 (CE) 是开发人员和小型团队开始使用 Docker 并尝试使用基于容器的应用的理想之选,所以这里我们来说一下Docker社区版的安装 操作系统要求 64位 CentOS 这里只说明centos上的安装方法 卸载旧版本 Docker 的早期版本称为 docker 或 docker-engine.如果安装了这些版本,请卸载它们及关联的依赖资源. $ sudo yum remove docker docker

Docker系列-第四篇Docker镜像

1.镜像是什么 镜像是一种轻量级.可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码.运行时.库.环境变量和配置文件. 1.1UnionFS(联合文件系统) UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层.轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single