深入理解Dockerfile —— 筑梦之路
FROM 基础镜像
可以选择现有的镜像,比如centos、debian、apline等,特殊镜像scratch,它是一个空镜像。
如果你以 scratch
为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如swarm
、coreos/etcd
。对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch
会让镜像体积更加小巧。使用 Go 语言开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go
是特别适合容器微服务架构的语言的原因之一。
RUN 指令
shell 格式:
RUN <命令>
,就像直接在命令行中输入的命令一样。刚才写的Dockerfile
中的RUN
指令就是这种格式。exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
,这更像是函数调用中的格式。
Union FS
是有最大层数限制的,比如 AUFS
,曾经是最大不能超过 42 层,现在是不能超过 127 层。
构建上下文
如果注意,会看到 docker build
命令最后有一个 .
,.
表示当前目录,而 Dockerfile
就在当前目录,因此不少初学者以为这个路径是在指定 Dockerfile
所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定上下文路径。那么什么是上下文呢?
首先我们要理解 docker build
的工作原理。Docker
在运行时分为 Docker
引擎(也就是服务端守护进程)和客户端工具。Docker
的引擎提供了一组 REST API,被称为 Docker Remote API
,而如 docker
命令这样的客户端工具,则是通过这组 API
与 Docker
引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker
功能,但实际上,一切都是使用的远程调用形式在服务端(Docker
引擎)完成。也因为这种 C/S
设计,让我们操作远程服务器的 Docker
引擎变得轻而易举。
当我们进行镜像构建的时候,并非所有定制都会通过 RUN
指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY
指令、ADD
指令等。而 docker build
命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker
引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build
命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker
引擎。这样 Docker
引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。
如果在 Dockerfile
中这么写:
COPY ./package.json /app/
这并不是要复制执行 docker build
命令所在的目录下的 package.json
,也不是复制 Dockerfile
所在目录下的 package.json
,而是复制 上下文(context) 目录下的 package.json
。
因此,COPY
这类指令中的源文件的路径都是相对路径。这也是初学者经常会问的为什么 COPY ../package.json /app
或者 COPY /opt/xxxx /app
无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。
现在就可以理解刚才的命令 docker build -t nginx:v3 .
中的这个 .
,实际上是在指定上下文的目录,docker build
命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。
如果观察 docker build
输出,我们其实已经看到了这个发送上下文的过程:
$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
...
理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现 COPY /opt/xxxx /app
不工作后,于是干脆将 Dockerfile
放到了硬盘根目录去构建,结果发现 docker build
执行后,在发送一个几十 GB
的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build
打包整个硬盘,这显然是使用错误。
一般来说,应该会将 Dockerfile
置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore
一样的语法写一个 .dockerignore
,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。
那么为什么会有人误以为 .
是指定 Dockerfile
所在目录呢?这是因为在默认情况下,如果不额外指定 Dockerfile
的话,会将上下文目录下的名为 Dockerfile
的文件作为 Dockerfile。
这只是默认行为,实际上 Dockerfile
的文件名并不要求必须为 Dockerfile
,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php
参数指定某个文件作为 Dockerfile
。
当然,一般大家习惯性的会使用默认的文件名 Dockerfile
,以及会将其置于镜像构建上下文目录中。
重点需要理解构建上下文,对于构建优化比较重要。
其他用法
1. 从url构建
示例:
docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14
这行命令指定了构建所需的
Git repo
,并且指定默认的master
分支,构建目录为/8.14/
,然后 Docker 就会自己去git clone
这个项目、切换到指定分支、并进入到指定目录后开始构建。
2. 用给定的 tar 压缩包构建
docker build http://server/context.tar.gz
ocker
引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。
3. 从标准输入中读取 Dockerfile 进行构建
docker build - < Dockerfilecat Dockerfile | docker build -
如果标准输入传入的是文本文件,则将其视为
Dockerfile
,并开始构建。这种形式由于直接从标准输入中读取Dockerfile
的内容,它没有上下文,因此不可以像其他方法那样可以将本地文件COPY
进镜像之类的事情。
4. 从标准输入中读取上下文压缩包进行构建
docker build - < context.tar.gz如果发现标准输入的文件格式是 gzip、bzip2 以及 xz 的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。
更多详情请阅读:如何优雅的使用 Dockerfile 定制镜像,超详细!
相关文章:

深入理解Dockerfile —— 筑梦之路
FROM 基础镜像 可以选择现有的镜像,比如centos、debian、apline等,特殊镜像scratch,它是一个空镜像。 如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。 不…...

Vue3 魔法:轻松删除响应式对象的属性
🧙♂️ 诸位好,吾乃诸葛妙计,编程界之翘楚,代码之大师。算法如流水,逻辑如棋局。 📜 吾之笔记,内含诸般技术之秘诀。吾欲以此笔记,传授编程之道,助汝解技术难题。 &…...

python命令大全及说明,python命令大全下载
大家好,本文将围绕python命令大全及说明展开说明,python命令大全下载是一个很多人都想弄明白的事情,想搞清楚python简单命令语句需要先了解以下几个事情。 Python有哪些常用但容易忘记的命令? 1 如何忽略报错信息2 Python常见绘图…...

Flink1.17实战教程(第五篇:状态管理)
系列文章目录 Flink1.17实战教程(第一篇:概念、部署、架构) Flink1.17实战教程(第二篇:DataStream API) Flink1.17实战教程(第三篇:时间和窗口) Flink1.17实战教程&…...

ES慢查询分析——性能提升6 倍
问题 生产环境频繁报警。查询跨度91天的数据,请求耗时已经来到了30s。报警的阈值为5s。我们期望值是5s内,大于该阈值的请求,我们认为是慢查询。这些慢查询,最终排查,是因为走到了历史集群上。受到了数据迁移的一定影响…...

[NAND Flash 4.3] 闪存的物理学原理_NAND Flash 的读、写、擦工作原理
依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 2.1.3.1 Flash 的物理学原理与发明历程 经典物理学认为 物体越过势垒,有一阈值能量;粒子能量小于此能量则不能越过,大于此能 量则可以越过。例如骑自行…...

海豚调度 Dolphinscheduler-3.2.0/DolphinScheduler-3.1.9 离线部署 伪集群模式
Dolphinscheduler-3.2.0(离线)伪集群模式 一、依赖(前置准备工作) 1.JDK:版本要求 JDK(1.8),安装并配置 JAVA_HOME 环境变量,并将其下的 bin 目录追加到PATH 环境变量中; 2.数据库:PostgreSQL(8.2.15) 或者MySQL(5.7),两者任选其一即可,如 MySQL 则需要…...

4.33 构建onnx结构模型-Expand
前言 构建onnx方式通常有两种: 1、通过代码转换成onnx结构,比如pytorch —> onnx 2、通过onnx 自定义结点,图,生成onnx结构 本文主要是简单学习和使用两种不同onnx结构, 下面以 Expand 结点进行分析 方式 方法一…...

LeetCode——1599. 经营摩天轮的最大利润
通过万岁!!! 题目:就是一个摩天轮,一共有4个仓位,一个仓位中最多可以做4个人。然后每次上一个人boardingCost钱,但是我们转动1/4圈,需要的成本是runningCost。然后给我们一个数组cu…...

从 MySQL 的事务 到 锁机制 再到 MVCC
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、事务 1.1 含义 1.2 ACID 二、锁机制 2.1 锁分类 2.2 隔离级别 三、MVCC 3.1 介绍 3.2 隔离级别 3.3 原理 四、总结 前…...

PostGreSQL远程连接
1、找到PostGreSQL安装目录,修改“postgresql.conf”配置文件(安装路径\data\postgresql.conf)。 若不知道安装目录,则通过服务,找到PostGreSQL运行的任务,右击“属性”可以进行查看安装的目录。 进入该目…...

CSS 缩减顶部动画
<template><!-- mouseenter"startAnimation" 表示在鼠标进入元素时触发 startAnimation 方法。mouseleave"stopAnimation" 表示在鼠标离开元素时触发 stopAnimation 方法。 --><!-- 容器元素 --><div class"container" mou…...

开源掌机是什么?
缘起 最近在学习小游戏的开发,偶然发现有一种叫“掌机”的游戏机,可以玩远古的各类游戏机、街机游戏!并且价格都还很便宜。这种神器的东西到底是什么?是如何工作的呢?有市场前景吗?带着这些疑问࿰…...

基于Wenet长音频分割降噪识别
Wenet是一个流行的语音处理工具,它专注于长音频的处理,具备分割、降噪和识别功能。它的长音频分割降噪识别功能允许对长时间录制的音频进行分段处理,首先对音频进行分割,将其分解成更小的段落或语音片段。接着进行降噪处理&#x…...

mysql基础-表操作
环境: 管理工具:Navicat 数据库版本:5.7.37 mysql的版本,我们可以通过函数,version()进行查看,本次使用的版本如下: 目录 1.管理工具 1.1创建表 1.2.修改表名 1.3.复制表 1.4.删除表 2…...

MySql——1146 - Table‘mysql.proc‘doesn‘t exit是这个
项目场景: 做自己的小项目需要连接mysql数据库 问题描述 点击数据库时报错 1146 - Table’mysql.proc’doesn’t exit 原因分析: 误删原生的mysql数据库 解决方案: 重新安装装部署mysql就好了 注意不要轻易删除原生的东西...

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 代码下载(1)
本文主要参考: BQ3588C_代码下载 1. 安装依赖工具 安装命令如下: sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flexbison gperf build-essential zip curl zlib1g-dev gcc-multilib g-multiliblibc6-dev-i386 l…...

开源预约挂号平台 - 从0到上线
文章目录 开源预约挂号平台 - 从0到上线演示地址源码地址可以学到的技术前端技术后端技术部署上线开发工具其他技术业务功能 项目讲解前端创建项目 - 安装PNPM - 使用VSCODE - 安装插件首页顶部与底部 - 封装组建 - 使用scss左右布局中间内容部分路由 - vue-routerBANNER- 走马…...

Vue3的proxy
vue3.0中,使用proxy替换了原来遍历对象使用Object.defineProperty方法给属性添加set/get vue的核心能力之一是监听用户定义的状态变化并响应式刷新DOM vue2是通过替换状态对象属性的getter和setter来实现的,vue3则通过proxy进行 改为proxy后,可以突破vue当前的…...

Vue Router的介绍与引入
在这里是记录我引入Vue Router的全过程,引入方面也最好先看官方文档 一.介绍 Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括: 嵌套路由映射动态路由选择模块化、基于组件的…...

StratifiedKFold解释和代码实现
StratifiedKFold解释和代码实现 文章目录 一、StratifiedKFold是什么?二、 实验数据设置2.1 实验数据生成代码2.2 代码结果 三、实验代码3.1 实验代码3.2 实验结果3.3 结果解释3.4 数据打乱对这种交叉验证的影响。 四、总结 一、StratifiedKFold是什么? …...

四十八----react实战
一、项目中css模块化管理 1、css-loader 以下可以使用styles.xxx方式使用class是因为使用css-loader配置了module。 import styles from ./index.less export const App(){return <div className={styles.xxx}>hello word</div> }//webpack配置 {test:/\.css$/,u…...

三步实现Java的SM2前端加密后端解密
秦医如毒,无药可解。 话不多说,先上需要用到的js文件下载链接 和 jsp前端代码。 第一步:下载两个必备的js文件—— crypto-js.js、sm2.js 。 它们的下载链接如下↓(该网页不魔法上网的话会很卡,毕竟github&#x…...

1分钟带你了解golang(go语言)
Golang:也被称为Go语言,是一种开源的编程语言。由Google的Robert Griesemer、Rob Pike和Ken Thompson于2007年开始设计,2009年11月正式对外发布。(被誉为21世纪的C语言) 像python一样的优雅,有c一样的性能…...

CSS-4
平面转换 整体认识 div {margin: 100px 0;width: 100px;height: 100px;background-color: pink;/* 过渡效果 */transition: all 1s;}/* 当鼠标悬停到div时,进行平面转换 */div:hover {transform: translate(800px) rotate(360deg) scale(2) skew(180deg);}作用&…...

Python为何适合开发AI项目?
Python在人工智能(AI)项目中的流行和广泛应用归因于多个因素,其中一些主要原因包括: 1、易学易用: Python语法简洁清晰,易于学习和理解。这使得新手能够更容易上手,并且对于处理复杂的AI算法和…...

总结心得:各设计模式使用场景
单例模式:创建单个对象 工厂模式:创建对象交给工厂完成,当需要创建的对象是一系列相互关联或相互依赖的产品族时 原型模式:克隆对象,避免创建初始化开销 建造者模式:创建一个复杂对象,该对象…...

详解Vue3中的事件监听方式
本文主要介绍Vue3中的事件监听方式。 目录 一、v-on指令二、使用符号简写三、事件修饰符四、动态事件名五、常见的监听事件六、自定义事件 在Vue3中,事件监听的方式与Vue2有一些不同。 下面是Vue3中事件监听方式的详细介绍: 一、v-on指令 Vue3中仍然使…...

Unity关于easySave2 easySave3保存数据的操作;包含EasySave3运行报错的解决
关于easySave2 easySave3保存数据的操作;包含EasySave3运行报错的解决 /// 数据存储路径(Easy Save的默认储存位置为:Application.persistentDataPath,为了方便我们可以给它指定储存路径) #region 存储数据/*/// /// 存…...

2022年全球软件质量效能大会(QECon上海站)-核心PPT资料下载
一、峰会简介 近年来,以云计算、移动互联网、物联网、工业互联网、人工智能、大数据及区块链等新一代信息技术构建的智能化应用和产品出现爆发式增长,突破了对于软件形态的传统认知,正以各种展现方式诠释着对新型智能软件的定义。这也使得对…...