Docker - 深入理解Dockerfile中的 RUN, CMD 和 ENTRYPOINT
RUN
docker file 中的 RUN 命令相对来教容易理解
- RUN 指令用于在构建镜像时执行命令,这些命令会在 Docker 镜像的构建过程中执行。常用于安装软件包、设置环境变量、创建目录等。
- RUN 指令会在镜像构建中创建新的镜像层,每个 RUN 指令都会创建一个新的镜像层。
- RUN 指令执行的命令会在构建阶段生效,而不会在容器运行时执行。
关键是
RUN 可以有多条
RUN 只会在构建阶段执行, 在容器启动时不会执行
提供1个例子:
我们准备1个docker file
test_cmd1
FROM busyboxRUN echo "hello run"
RUN echo "hello run2"CMD ["echo", "hi"]
当build 时, RUN两条命令都被执行了, 但是CMD 的没有执行
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$docker build -f test_cmd1 -t test_cmd1:latest .create mode 100644 dockerfile/test_cmd1
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.Install the buildx component to build images with BuildKit:https://docs.docker.com/go/buildx/Sending build context to Docker daemon 8.192kB
Step 1/4 : FROM busybox---> 65ad0d468eb1
Step 2/4 : RUN echo "hello run"---> Running in 276d14886a99
hello run
Removing intermediate container 276d14886a99---> 1323139f939a
Step 3/4 : RUN echo "hello run2"---> Running in 483674db3603
hello run2
Removing intermediate container 483674db3603---> dbdc9963c5dc
Step 4/4 : CMD ["echo", "hi"]---> Running in 3db1c9c199d9
Removing intermediate container 3db1c9c199d9---> 9ff4d1d0ea33
Successfully built 9ff4d1d0ea33
Successfully tagged test_cmd1:latest
但是启动容器时, 只有CMD 那句被执行
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd1:latest
hi
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$
RUN 命令顺便带过了, 不是本文的重点
CMD
- CMD 指令用于指定容器启动时要运行的默认命令。它可以被 Dockerfile 中的 ENTRYPOINT 指令覆盖。
- 如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 指令会生效。
- CMD 指令的内容会在容器启动时执行,可以通过 docker run 命令传递参数来覆盖默认命令。
我们先讲下CMD的写法
原则上, CMD 后面的内容应该是1个数组
CMD [“executeable”, “arg1”, “arg2”…]
其中第1个参数必须是1个在容器内可以执行的命令(定义在$PATH 中的 可执行文件)
但是CMD 有多个写法
我们用各种例子来体现
例子1
# ok
# command "echo hhih"
CMD ["echo", "hhih"]
这种写法是可以的
正常输出:
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd3:latest
hhih
可以用docker ps -a --no-trunc 命令来查看容器被启动时真正执行的命令
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker ps -a --no-trunc | head -n 2
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f4be762c74eaaa281010eab2b40a1cd39a638ff688e63d371d0166cfdd23a21 test_cmd3:latest "echo hhih" 18 minutes ago Exited (0) 18 minutes ago upbeat_kirch
可见执行的命令就是 “echo hhih"
CMD [“echo”, “hhih”] 这种写法就是符合了第1个参数是可以执行命令, 第2个参数是args 的原则.
例子2
# error unable to start container process: exec: "echo hhih", and pts hundled in host server
# command "echo hhih"
CMD ["echo hhih"]
这种写法会启动时会出错
因为CMD 第1个参数是 “echo hhih" 并不是1个可执行文件命令
例子3
# ok
# command "/bin/sh -c 'echo hhih'"
CMD echo hhih
这种写法是可以的, 实际上 后面的字符串按照空格被自动分割成多个item, 第1个item是echo , 第2个是hhih
但是这种写法与例子1还是有点区别, 就是当容器被启动时, 执行的命令是
/bin/sh -c ‘echo hhih’
例子4
# first CMD will be ignored
CMD echo hhih
CMD echo hhihb
这种写法break了CMD 只能有单个的原则, 但是构建镜像时不会出错, 只是容器启动时只会执行最后一条CMD 命令, 而忽略之前的
例子5
# error /bin/sh: echo hhih: not found
# command "/bin/sh -c '\"echo hhih\"'"
CMD "echo hhih"
这种写法也是错误示范, 这里的echo hhih 被双引号扩着, 则会被CMD 认为是1个 元素item, 违反了第一个item 必须是可执行文件命令的原则
例子6
# ok
# command "/bin/sh -c '\"echo\" \"hhih\"'"
CMD "echo" "hhih"
这种写法是ok的类似 例子3
小结
CMD 的写法大概是两种
一种是 用中扩号括住, 显式数组写法
CMD [“executeable”, “args1”, “args2”…]
这种写法容器启动时 正常执行 executeable args1 args2 …
另1种写法是 不用中扩号
直接 CMD executeable args1 args2 …
这种写法容器启动时, 会被按照 sh -c " executeable args1 args2 …"
注意, 其实这两种写法还有变种, 例如显式利用sh -c
CMD [“sh”, “-c”, “echo hhic”]
CMD [“sh”, “-c”, “echo hhic, $0”, "hhic2]
CMD sh
-c
-|
echo hhic
等等, 但是都是基于上面提到的两大类扩展的, 这种写法也适合于 Dockerfile, cloudbuild yaml, k8s yaml中命令参数的编写
CMD 定义的命令可以在容器启动时被覆盖
这个特性很重要
例子:
定义1个 docker file
FROM busybox
CMD echo hhih
构建镜像
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ git pull && docker build -f test_cmd3 -t test_cmd3:latest .
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 8 (delta 6), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (8/8), 659 bytes | 131.00 KiB/s, done.
From e.coding.net:nvd11/bq/sql_backup483f2de..438d518 master -> origin/master
Updating 483f2de..438d518
Fast-forwarddockerfile/test_cmd3 | 6 ++++--1 file changed, 4 insertions(+), 2 deletions(-)
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.Install the buildx component to build images with BuildKit:https://docs.docker.com/go/buildx/Sending build context to Docker daemon 8.704kB
Step 1/2 : FROM busybox---> 65ad0d468eb1
Step 2/2 : CMD echo hhih---> Using cache---> 4c73e1a69ab2
Successfully built 4c73e1a69ab2
Successfully tagged test_cmd3:latest
正常执行时会输出
hhih
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd3:latest
hhih
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$
但是我们可以在docker run 命令后面加上命令覆盖掉CMD 定义的命令
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd3:latest echo hello
hello
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$
这个特性相当重要, 可以让我们的容器部署更加灵活
ENTRYPOINT
- ENTRYPOINT 指令用于配置容器启动时要运行的命令,它定义了容器的主要执行命令。
- 如果 Dockerfile 中有多个 ENTRYPOINT 指令,只有最后一个 ENTRYPOINT 指令会生效。
- ENTRYPOINT 指令的内容不会被覆盖,但可以通过 docker run 命令的 --entrypoint 选项来覆盖。
ENTRYPOINT 的用法是CMD 基本一样, 大部分场景下能互相替换
例如:
test_cmd4
FROM busybox# error /bin/sh: echo hello: not found
# command /bin/sh -c '\"echo hello\"'
# ENTRYPOINT "echo hello"# error /bin/sh: echo 'hello': not found
# command "/bin/sh -c '\"echo 'hello'\"'"
# ENTRYPOINT "echo 'hello'"# error runc create failed: unable to start container process: exec: "echo hello"
# command "echo hello"
# ENTRYPOINT ["echo hello"]# ok
# command "echo hello"
# ENTRYPOINT ["echo", "hello"]# ok
# command "/bin/sh -c 'echo hello'"
# could not be append or override
# ENTRYPOINT echo hello# ok
# command "/bin/sh -c 'echo hello;'"
# could not be append or override
ENTRYPOINT echo hello;
那么既然CMD 能用, 为何需要ENTRYPOINT
是因为 ENTRYPOINT 定义的命令在容器启动时一定会执行, 无法被覆盖
在某些场景下, 为了安全等原因, 不想容器启动命令被覆盖, 则应该考虑用ENTRYPOINT 来构建镜像
但是, ENTRYPOINT 仍然可以配合CMD 命令来令到命令的某些部分 or 参数可以被覆盖
例如下面3中写法都是ok的
# ok
# command "/bin/sh -c 'echo hello; $0'"
# $0 could be override
ENTRYPOINT echo hello; $0# ok
# command "sh -c 'echo hello; $0'"
# $0 could be override
# equal to "ENTRYPOINT echo hello; $0"
ENTRYPOINT [ "sh", "-c", "echo hello; $0"]# ok
# command "/bin/sh -c 'sh -c \"echo 'hello'; $0\"'"
# $0 could be override
ENTRYPOINT sh -c "echo 'hello'; $0"
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd4:latest
hello
gateman@DESKTOP-UIU9RFJ:~/projects/sql_backup/dockerfile$ docker run test_cmd4:latest "echo hi"
hello
hi
注意这里两点
- docker run 提供的参数必须用“括住”, 除非你在ENTRYPOINT 定义了两个参数 $0 和 $1
- 即使部分被覆盖, 但是 ENTRYPOINT 定义的部分仍然会执行
相关文章:
Docker - 深入理解Dockerfile中的 RUN, CMD 和 ENTRYPOINT
RUN docker file 中的 RUN 命令相对来教容易理解 RUN 指令用于在构建镜像时执行命令,这些命令会在 Docker 镜像的构建过程中执行。常用于安装软件包、设置环境变量、创建目录等。RUN 指令会在镜像构建中创建新的镜像层,每个 RUN 指令都会创建一个新的镜…...
Python 函数式编程 内置高阶函数及周边【进阶篇 3】推荐
前面我们已经总结并实践了用python获取到了数据。也介绍了python中http网络请求的几种方式,正在学习python开发语言或者对python3知识点生疏需要回顾的请点这里 ,本章主要总结了函数式编程及特点 和 python中内置的高阶函数及周边知识,方便自…...
【Rust光年纪】探秘Rust GUI库:从安装配置到API概览
Rust语言GUI库全方位比较:选择适合你的工具 前言 在现代软件开发中,图形用户界面(GUI)库扮演着至关重要的角色。随着Rust语言的不断发展,越来越多的优秀的GUI库也相继问世,为Rust开发者提供了更多选择。本…...
Element plus部分组件样式覆盖记录
文章目录 一、el-button 样式二、Popconfirm 气泡确认框三、Popover 气泡卡片四、Checkbox 多选框五、Pagination 分页六、Form 表单七、Table 表格 一、el-button 样式 html: <el-button class"com_btn_style">button</el-button>样式覆盖…...
重塑业务生态,Vatee万腾平台:引领行业变革的新引擎
在数字经济浪潮汹涌的今天,传统行业的边界正被不断模糊与重塑,新兴技术如云计算、大数据、人工智能等正以前所未有的速度改变着商业世界的面貌。在这一背景下,Vatee万腾平台应运而生,以其独特的创新模式和强大的技术实力ÿ…...
标准术语和定义中的【架构】应该如何描述
一、参考国家标准和国际标准中对“架构”的描述 (1)GB/T 8566-2022 国家标准 架构的术语描述:(系统)在其环境中的一些基本概念或性质,体现在其元素关系,以及设计与演进原则中。 (2)ISO/IEC/IEEE 42010 国际标准 架构的…...
华为鸿蒙Core Vision Kit 骨骼检测技术
鸿蒙Core Vision Kit 是华为鸿蒙系统中的一个图像处理框架,旨在提供各种计算机视觉功能,包括物体检测、人脸识别、文本识别等。骨骼检测是其中的一项功能,主要用于检测和识别人类身体的骨骼结构。 骨骼检测的关键点 骨骼点检测:通…...
Table API SQL系统(内置)函数System (Built-in) Function详解
目录 函数类型 引用函数 函数精确引用 函数模糊引用 函数解析顺序 精确的函数引用 模糊的函数引用 系统函数 标量函数(Scalar Functions) 比较函数(Comparison Functions) 逻辑函数(Logical Functions) 算术函数(Arithmetic Functions) 字符串函数(Strin…...
一键运行RocketMQ5.3和Dashboard
一键运行RocketMQ5.3和Dashboard 目录 一键运行RocketMQ5.3和Dashboard通过Docker Compose 来一键启动运行的容器包括docker-compose.yml文件运行命令启动本地效果查看 参考信息 通过Docker Compose 来一键启动 运行的容器包括 NameServerBrokerProxyDashBoard docker-compo…...
HAL STM32 SG90舵机驱动控制
HAL STM32 SG90舵机驱动控制 🔖测试对象:STM32F103SG90舵机 🌼功能实现:通过串口指令,控制SG90舵机转动到指定角度。 ✨在实际硬件舵机驱动过程中,使用SG90普通舵机空载运转情况下,电流在180mA…...
【Kubernetes】k8s集群图形化管理工具之rancher
目录 一.Rancher概述 1.Rancher简介 2.Rancher与k8s的关系及区别 3.Rancher具有的优势 二.Rancher的安装部署 1.实验准备 2.安装 rancher 3.rancher的浏览器使用 一.Rancher概述 1.Rancher简介 Rancher 是一个开源的企业级多集群 Kubernetes 管理平台,实…...
AI编程系列一1小时完成链家房价爬虫程序
背景 AI编程实在太火,写了很多年的Java,现在Python 和Go 简单好用,今天结合智谱清言快速完成一个程序爬虫程序,没有任何Python 编程经验,只需要会提问,熟悉简单HTML结构即可。未来一定是有业务能力者的福…...
【JavaEE初阶】文件内容的读写—数据流
目录 📕 引言 🌴 数据流的概念 🚩 数据流分类 🌳 字节流的读写 🚩 InputStream(从文件中读取字节内容) 🚩 OutputStream(向文件中写内容) 🎄 字符流的…...
Spring Boot项目中使用Sharding-JDBC实现读写分离
Sharding-JDBC是一个分布式数据库中间件,它不仅支持数据分片,还可以轻松实现数据库的读写分离。下面是如何在Spring Boot项目中集成Sharding-JDBC并实现读写分离的详细步骤: 目录 1. 引入依赖 2. 配置数据源 3. 配置Sharding-JDBC相关参数…...
【网络安全】SSO登录过程实现账户接管
未经许可,不得转载。 文章目录 正文正文 登录页面展示了“使用 SSO 登录”功能: 经分析,单点登录(SSO)系统的身份验证过程如下: 1、启动SSO流程:当用户点击按钮时,浏览器会发送一个GET请求到指定的URL: /idp/auth/mid-oidc?req=[UNIQUE_ID]&redirect_uri=[REDI…...
Admin.NET源码学习(3:LazyCaptcha使用浅析)
Admin.NET项目前端登录页面的验证码图片默认使用动态图,且图形内容为阿拉伯数字运算(如下图所示),用户输入正确的计算结果才能正常登录。项目采用LazyCaptcha模块生成验证码及动态图。 在Admin.NET.Core项目中添加了Lazy.Cap…...
在原生未启用kdump的BCLinux 8系列服务器上启用kdump及报错处理
本文记录了在原生未启用kdump的BCLinux 8系列操作系统的服务器上手动启用kdump服务及报错处理的过程。 一、问题描述 BCLinux 8系列操作系统,系统初始化安装时未启用kdump服务,手动启动时报以下“No memory reserved for crash kernel”或“ConditionK…...
Android架构组件中的MVVM
Android架构组件中的MVVM(Model-View-ViewModel)模式是一种广泛应用的设计模式,它通过将应用程序分为三个主要部分(Model、View、ViewModel)来分离用户界面和业务逻辑,从而提高代码的可维护性、可扩展性和可…...
走向绿色:能源新选择,未来更美好
当前,全球范围内可再生能源正经历着从辅助能源向核心能源的深刻转型,绿色能源日益渗透至居住、出行、日常应用等多个领域,深刻影响着我们的生活方式,使我们能够更加充分地体验清洁能源所带来的优质生活。 一、绿色能源与“住” …...
鸿蒙装饰器的介绍
State装饰器, State装饰的变量,称为状态变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时,必须指定其类型和本地初始化。 Provide装饰器和Consume装饰器&#…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
