【Docker】Dockerfile从概念介绍到快速上手编写案例实战

news2024/11/28 8:43:15

请添加图片描述


本期目录

  • 1. Dockerfile介绍
    • 1.1 Dockerfile的重要性
    • 1.2 构建三步骤
  • 2. Dockerfile构建过程
    • 2.1 Dockerfile内容基础
    • 2.2 Dockerfile执行流程
    • 2.3 总结
  • 3. Dockerfile常用保留字指令
    • 3.1 Dockerfile常用保留字一览
    • 3.2 保留字讲解
  • 4. 案例演示-自定义CentOS镜像
    • 4.1 前期准备
    • 4.2 编写Dockerfile
    • 4.3 构建镜像
    • 4.4 运行容器
  • 专栏精选文章



1. Dockerfile介绍

Dockerfile 是用来构建 Docker 镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。(可以理解为 Linux 的 Shell 脚本)

Dockerfile 官网文档:https://docs.docker.com/engine/reference/builder/


1.1 Dockerfile的重要性

前面我的这篇博文【docker commit】中讲解过使用 docker commit 来构建一个带 Vim 命令的 Ubuntu 镜像。在镜像不复杂时可以胜任,但是在实际开发中,微服务代码随时变化和改动,如果我们想把开发的微服务及其所有复杂的中间件以及环境等打包成镜像,用 docker commit 来一条一条地构建镜像就力不从心了。因此我们需要 Dockerfile 来一次搞定所有镜像的构建。

image-20221214104602578

例如,Dockerfile 可以告诉 Docker 服务引擎,本镜像需要一次性添加 Vim 、ifconfig 、Tomcat 8.0 、JDK 1.8 … 只要按照 DockerFile 上的清单来添加,就可以做到构建镜像时一次成型。


1.2 构建三步骤

  1. 编写 Dockerfile 文件
  2. docker build 命令构建镜像
  3. docker run 命令按照镜像运行容器实例

2. Dockerfile构建过程


2.1 Dockerfile内容基础

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

2.2 Dockerfile执行流程

  1. Docker 从基础镜像运行一个容器;
  2. 执行一条指令,并对容器作出修改;
  3. 执行类似 docker commit 的操作,提交一个新的镜像层;
  4. Docker 再基于刚提交的镜像运行一个新容器;
  5. 执行 Dockerfile 中的下一条指令,直到所有指令执行完毕。

多个镜像层构成一个总的最终镜像提交版本供你使用。


2.3 总结

image-20221214110727677

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

  • Dockerfile 是软件的原材料;
  • Docker 镜像是软件的交付品;
  • Docker 容器则可以认为是软件的运行态,也即按照镜像运行的容器实例。

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


3. Dockerfile常用保留字指令

这一节是本篇博文的核心内容,学会 Dockerfile 常用保留字,你就能看懂 Dockerfile 甚至亲自撰写 Dockerfile 。

开始之前,大家可以打开 Tomcat 官方的 Dockerfile 看一眼,有一个感性认识:[Tomcat Dockerfile] 。


3.1 Dockerfile常用保留字一览

保留字简介
FROM基础镜像
MAINTAINER镜像维护者的姓名和邮箱地址
RUN容器构建时需要执行的命令
EXPOSE当前容器对外暴露的端口
WORKDIR指定创建容器后,终端默认登录进来的工作目录,一个落脚点
USER指定该镜像以什么样的用户去执行,默认是root用户
ENV用来在构建镜像过程中设置环境变量
ADD将宿主机目录下的文件拷贝进镜像,且会自动处理URL和解压tar压缩包
COPY类似 ADD ,拷贝文件和目录到镜像中
VOLUME容器数据卷,用于数据保存和持久化工作
CMD指定容器启动后要干的事
ENTRYPOINT也是值得容器启动时要运行的命令

3.2 保留字讲解

【FROM】

基础镜像,当前镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,Dockerfile 的第一行必须是 FROM 。说人话就是你继承哪个镜像父类。


【RUN】

容器构建时需要执行的命令。即,当运行 docker build 时,就会读取 Dockerfile 中的 RUN 保留字的指令并执行。它有两种格式:Shell 格式和 Exec 格式。我个人更倾向于用 Shell 格式。

  • Shell 格式:

    # <命令行命令>等同于在终端操作的Shell命令
    RUN <命令行命令>
    

    举例:

    RUN yum -y install vim
    

    意思就是,在 FROM 指定的基础镜像创建的容器里,执行 yum -y install vim 这条 Linux Shell 命令,从而在基础镜像的容器中安装 Vim 。

  • Exec 格式:

    RUN ["可执行文件", "参数1", "参数2"]
    

    举例:

    RUN ["./test.php", "dev", "offline"]
    

    等价于

    RUN ./test.php dev offline
    

【WORKDIR】

举例演示 WORKDIR 指的是哪里。例如,我创建一个 Tomcat 容器,以前台交互式启动。

$ docker run -it -p 8080:8080 billygoo/tomcat8-jdk8:latest /bin/bash

image-20221214133633200

我们看到,一进入 Tomcat 容器实例,我们所在的工作目录就是 /usr/local/tomcat 。这就是 Dockerfile 保留字 WORKDIR 指定的。


【ENV】

举例:

ENV MY_PATH /usr/mytest

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

WORKDIR $MY_PATH

【ADD】

将宿主机目录下的文件拷贝进镜像,且会自动处理URL和解压tar压缩包。粗浅地说,ADD 就是 docker cp + 解压命令的合体。我一般更常用 ADD 而不用 COPY

例如,我要在我构建的镜像中安装 JDK 8 ,那么就可以直接把 JDK 1.8 .tar.gz 这个压缩包直接从宿主机上拷贝进镜像中,并自动解压。


【COPY】

相当于 Docker 命令 docker cp 。粗浅地说,COPY 就是不带自动解压功能的 ADD 。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 。


【CMD】

指定容器启动后要干的事。CMD 指令的格式和 RUN 相似,也是 Shell 格式和 Exec 格式两种格式:

  • Shell 格式:

    # <命令行命令>等同于在终端操作的Shell命令
    RUN <命令行命令>
    
  • Exec 格式:

    RUN ["可执行文件", "参数1", "参数2"]
    
  • 参数列表格式:

    CMD ["参数1", "参数2", ...]
    

    在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

注意:

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

举例:Tomcat 官网的 Dockerfile 中最后一行的命令:

image-20221214143531248

我们分别演示带/不带参数的情况来运行 Tomcat 容器的情况。

首先是不带任何参数的情况:

$ docker run -it -p 8080:8080 billygoo/tomcat8-jdk8:latest

image-20221214144130363

在 Windows 电脑上浏览器打开 http://192.168.168.101:8080

image-20221214144253232

是能正常访问 Tomcat 首页的。

接下来,我们演示 docker run 后面带有 /bin/bash 参数来启动 Tomcat 容器,这个参数就会替换 Tomcat 官方 Dockerfile 中最后一行的 CMD 命令,从而无法访问 Tomcat 首页。

$ docker run -it -p 8080:8080 billygoo/tomcat8-jdk8:latest /bin/bash

因为在 docker run 最后加了 /bin/bash 参数,Tomcat 的 Dockerfile 最后一行 CMD 命令就相当于被替换成:

CMD ["/bin/bash", "run"]

image-20221214144827199

此时再次在 Windows 电脑上浏览器打开 http://192.168.168.101:8080 就无法访问 Tomcat 首页,因为 docker run 最后加了 /bin/bash 参数替换了 Tomcat 的 Dockerfile 最后一行 CMD 命令。

image-20221214144908222


【ENTRYPOINT】

类似于 CMD 指令,区别是 ENTRYPOINT 不会被 docker run 后面的命令覆盖,且这些命令行参数会被当做参数传递给 ENTRYPOINT 指令指定的程序。

命令格式:

ENTRYPOINT ["可执行文件", "参数1", "参数2", ...]

ENTRYPOINT 可以与 CMD 一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是给 ENTRYPOINT 传参。

当指定了 ENTRYPOINT 后,CMD 的含义就发生了变化,不再是直接运行其命令而是将 CMD 的内容作为参数传递给 ENTRYPOINT 指令,他两个组合会变成 ENTRYPOINT "<CMD>"

举例:假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 固定参数
CMD ["/etc/nginx/nginx.conf"] # 变参
是否传参按照Dockerfile编写执行传参运行
Docker命令docker run nginx:testdocker run nginx:test -c /etc/nginx/new.conf
生成的实际命令nginx -c /etc/nginx/nginx.confnginx -c /etc/nginx/new.conf

4. 案例演示-自定义CentOS镜像

在上面讲解中,如果仍然感到迷惑看不懂,这是非常正常的。下面我将通过一个 Dockerfile 的案例实际演示,来帮助大家更好地理解 Dockerfile 中常用保留字的使用。


4.1 前期准备

本次案例中,我们自定义一个带 JDK8 、Vim 、ifconfig 的 CentOS 7 镜像 mycentosjava8

从远程仓库中拉取 CentOS 7 的镜像。这个原始的 CentOS 镜像里是没有 JDK8 、Vim 、ifconfig 的。注意不要拉取 CentOS 的最新镜像。

$ docker pull centos:7

image-20221214155222057

到 Oracle 官网下载 JDK 8 。注意要下载 Linux 版的 .tar.gz 格式的压缩包。

image-20221214150900784

把这个压缩包上传至 Linux 宿主机。

image-20221214151232680


4.2 编写Dockerfile

在 Linux 宿主机上创建一个文件夹存放 Dockerfile 。

$ mkdir -p /xsh/myfiles
$ cd /xsh/myfiles

进入这个目录并创建 Dockerfile 。

$ vim Dockerfile

Dockerfile 内容如下:

# 基础镜像,刚刚拉取的centos7镜像
FROM centos:7
# 指定作者和邮箱
MAINTAINER xsh<xiesihang@stu.ouc.edu.cn>

# 指定环境变量
ENV MYPATH /usr/local
# 指定登录镜像容器后的工作目录,引用上面定义的环境变量MYPATH
WORKDIR $MYPATH

# 安装Vim编辑器
RUN yum -y install vim
# 安装ifconfig查看网络IP
RUN yum -y install net-tools
# 安装JDK8及其lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
# ADD是相对路径,把jdk-8u351-linux-x64.tar.gz添加到容器中,安装包的相对路径取决于相对于你的Dockerfile的位置,为了方便与Dockerfile放在同一目录
ADD jdk-8u351-linux-x64.tar.gz /usr/local/java/
# 配置Java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_351
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

# 对外暴露80端口
EXPOSE 80

# 打印环境变量MYPATH
CMD echo $MYPATH
# 走到这一条命令就打印出构建成功
CMD echo "success-------------ok"
# CentOS需要伪终端交互
CMD /bin/bash

:wq! 保存退出。我们就完成了 Dockerfile 的编写。


4.3 构建镜像

构建镜像的命令格式如下。

$ docker build -t 新镜像名字:TAG .

【注意】

  • 上面 TAG 后面要加一个空格和一个点。
  • 要在 Dockerfile 所在目录下执行该命令。

举例:

本次案例的构建命令这样写:

$ docker build -t centosjava8:1.0 .

image-20221214160210158

构建过程大概需要 10 分钟左右,如果看到上图,就说明构建成功了。如果失败了,则有可能是 yum 需要更新索引,这部分操作自行搜索即可。

查看自定义构建的镜像 centosjava8

$ docker images

image-20221214160609762

可以看见,由于加入了 JDK8 、Vim 、ifconfig ,自定义构建的新 CentOS 镜像从原始的 204 MB 膨胀到 1.24 GB 。


4.4 运行容器

接下来我们创建这个新镜像的容器,来验证是否安装了 JDK8 、Vim 、ifconfig 。

$ docker run -it centosjava8:1.0 /bin/bash

image-20221214161010468

登录进容器后,发现当前所在的工作目录就是 Dockerfile 中 WORKDIR 指定的目录 ENV MYPATH /usr/local

测试 Vim 编辑器是否可用。

$ vim a.txt

image-20221214161218020

测试 ifconfig 命令是否可用。

$ ifconfig

image-20221214161352727

测试 JDK8 是否可用。

$ java -version

image-20221214161458839

三个全部都可以成功使用。那么到这里,自定义的 CentOS 镜像就创建成功了。



专栏精选文章

  1. 《Docker是什么?Docker从介绍到Linux安装图文详细教程》
  2. 《30条Docker常用命令图文举例总结》
  3. 《Docker如何构建自己的镜像?从镜像构建到推送远程镜像仓库图文教程》
  4. 《Docker多个容器和宿主机之间如何进行数据同步和数据共享?容器数据卷从介绍到常用操作图文教程》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑白图片怎样上色?教你如何给黑白照片上色

平时我们在网上浏览照片时&#xff0c;就会经常看到一些黑白色的照片。自从前段时间的复古风出现之后&#xff0c;很多小伙伴都会给自己拍摄的一些照片加上黑白滤镜&#xff0c;让原本彩色的照片变成了黑白色的&#xff0c;那大家知道黑白照片怎么变成彩色照片吗&#xff1f;今…

xxljob 自动清理日志的业务逻辑,以及涉及到的文件

目录 1 需求2 实现3 JobLogFileCleanThread1 需求 xxljob定时任务,会产生很多的日志文件,那么他是如何自动清除的呢? 2 实现 我们自己的项目集成了xxljob之后,会在yml里面有一个配置 ### 执行器日志文件保存天数 [选填] : 过期日志自动清理, # 限制值大于等于3时生效; …

物联网通信技术第7章 自组织网络(非常全,持续更新)

目录 知识点要求 7.1自组织网络概述 7.1.1 自组织网络的定义&#xff08;掌握&#xff09; 7.1.2 自组织网络的特点 &#xff08;理解&#xff09; 7.1.3 自组织网络的应用 7.2 自组织网络的体系结构&#xff08;了解&#xff09; 7.2.1 节点结构 7.2.2 自组织网络的网…

微信小程序开发—入门到跑路(二)

1、学习目标 知识点名称知识点内容难度系数要求程度模板语法数据绑定、事件绑定、条件渲染、列表渲染2星掌握WXSS样式WXSS3星掌握配置操作全局配置、TabBar配置、页面配置、3星掌握网络请求和案例网络数据请求、本地生活案例3星掌握文章目录1、学习目标2、模板语法2.1、数据绑…

AVS-代码路径说明

训练 1 config.py里面有backbone的路径,这里最好写在外面&#xff0c;写成绝对路径 不然每个算法都要放如下三个与训练模型&#xff0c;会很占地方vggishxxx.pth resnetxxx.pth pvt_v2_xxx.py AVS/AVSBenchmark1/avs_ms3/config.py 本来pretrained_backbones/xxx.pth文件在AVSB…

【C++】STL——list的常用接口

list的常用接口 文章目录list的常用接口一、list的介绍二、list的使用1.list的构造2.迭代器的使用2.1.begin和end2.2.rbegin和rend2.3.范围for2.4.迭代器的分类3.list的元素访问函数3.1.front和back4.list的容量操作函数4.1.empty4.2.size和max_size5.list修改的相关函数5.1.pu…

内卷起来,2023年外贸B2B企业怎么通过独立站吸引客户的注意

从国外疫情解封后&#xff0c;中国在2022年的最后一个月也解封了&#xff0c;我们努力了三年&#xff0c;现在不再查核酸、健康码&#xff0c;多家航空公司重新开通了国际航班。对许多外贸公司来说&#xff0c;是“外贸春天”的到来。那么即将到来的2023年&#xff0c;外贸B2B企…

十三、JavaScript——类型转化

一、类型转化 1 定义 类型转化&#xff1a;指将一种数据类型转化为其他的数据类型 - 指将其他类型转化为&#xff08;字符串、数值、布尔值&#xff09; 转化为字符串、调用toString()方法将其他类型转化为字符串 调用String&#xff08;&#xff09;函数将其他类型转化为字…

彻底理解并解决服务器出现大量TIME_WAIT

首先我们说下状态 TIME_WAIT 出现的原因 TCP的新建连接&#xff0c;断开连接的流程和各个状态&#xff0c;如下图所示 由上图可知&#xff1a;TIME_WAIT 是主动断开连接的一方会出现的&#xff0c;客户端&#xff0c;服务器都有可能出现 当客户端主动断开连接时&#xff0c;发…

C语言回调函数,提升C技巧必备

一、函数指针 在讲回调函数之前&#xff0c;我们需要了解函数指针。 我们都知道&#xff0c;C语言的灵魂是指针&#xff0c;我们经常使用整型指针&#xff0c;字符串指针&#xff0c;结构体指针等 int *p1; char *p2; STRUCT *p3; //STRUCT为我们定义的结构体 但是好像我们…

今天又get到一个小技能,collect_set函数

collect_set函数今天又get到一个小技能&#xff0c;掌握了hive一个关于列转行专用函数 collect_set函数。在这里做个学习笔记。collect_set是Hive内置的一个聚合函数, 结果返回一个消除了重复元素的对象集合, 其返回值类型是 array 。和collect_set相似的还有另一个函数collect…

Android12指纹调用流程介绍(一)

Android12指纹框架流程介绍(一) 前言&#xff1a;根据网上的相关资料&#xff0c;Android 12开始支持屏下指纹方案&#xff0c;根据自己手中的测试机&#xff0c; ​ 下载了android 12的源码&#xff0c;准备学习下新的指纹框架 注&#xff1a;目前笔者使用的版本是android_…

Qt扫盲-QSlider理论总结

QSlider理论总结1. 简述2. 常用功能3. 外观4. 最常用信号5. 键盘功能1. 简述 QSlider是用于控制边界值的经典小部件。它允许用户沿水平或垂直凹槽移动QSlider 的滑块&#xff0c;并将 滑块 的位置转换为合法范围内的整数值。但是 QSlider 仅提供整数范围。如果QSlider处理非常…

RSTP快速生成树简介、RSTP与STP的区别、RSTP BPDU字段信息、RSTP角色与端口状态介绍、RSTP工作过程之P/A机制详细分解)

2.11.0 以太网 RSTP快速生成树&#xff08;简介、RSTP与STP、RSTP BPDU、RSTP端口状态、RSTP工作过程之P/A机制&#xff09; RSTP快速生成树简介RSTP、STP的区别RSTP BPDU格式RSTP与STP的兼容性RSTP如何兼容STP&#xff1f;RSTP端口状态RSTP的5种端口角色RSTP的3种端口状态RSTP…

Windows OS中关闭445 Port

445端口是什么&#xff1f; 445端口是一个毁誉参半的端口&#xff0c;它和139端口一起是IPC$入侵的主要通道。有了它我们可以在局域网中轻松访问各种共享文件夹或共享打印机&#xff0c;但也正是因为有了它&#xff0c;黑客们才有了可乘之机&#xff0c;他们能通过该端口偷偷共…

Aba | 全自动biomarker分析神包!~(原作者用这个包发了三篇Nature啦~)

1写在前面 今天介绍一个Github上的神包吧, 主要是用于Biomarker的临床分析, 原作者用这个包已经发了3篇Nature了, 一起看看吧:&#x1f447; 在一些针对Biomarker的临床研究中, 我们常常需对Biomarker进行模型拟合, 预测效果评估等等.&#x1f970; 这个包可以完美解决这些问题…

[附源码]Python计算机毕业设计SSM基于web的火车订票管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Ansible概述及命令行模块

目录 一、Ansible概述 1 Ansible是什么 2 Ansible的四个组件&#xff1a; 3 Ansible的特性 二、Ansible 环境安装部署 三、ansible常用的命令行模块 1 command模块 2 shell模块 3 cron模块 4 user模块 5 group模块 6 copy模块 7 file模块 8 hostname模块 9 ping模块 10 …

Web端H5播放FLV、HLS、MP4 (二)

使用video.js播放HLS、FLV、MP4。 MP4、FLV、HLS、RTMP等协协和播放器之间的支持情况&#xff0c;参看这里。 一、主要JS插件&#xff1a; jquery(v3.6.0) video.js (v7.21.0&#xff0c;其它版本没试) https://cdn.bootcdn.net/ajax/libs/video.js/7.21.0/video.min.js f…

基于FPGA的RGB转HSV图像算法设计

一、什么是HSV色彩空间&#xff1f; RGB色彩空间是基于三基色而言&#xff0c;即红色、绿色、蓝色。而HSV色彩空间则是基于色调、饱和度和亮度而言的。 色调&#xff08;H&#xff09;是指光的颜色&#xff0c;例如&#xff0c;彩虹中的赤&#xff0c;橙&#xff0c;黄&#…