Dockerfile CMD、ENTRYPOINT 区别

ENTRYPOINT与CMD都可以对iamge配置启动命令。但两者之间还是有一些细微的区别。多数情况下需要用户在二者中选择其一使用,但也可以共同使用两者。下面将具体分析二者不同的使用场景。

 

 

ENTRYPOINT or CMD


最终,ENTRYPOINT与CMD都提供了一个方法,让用户指定容器默认启动命令。事实上如果你希望你的image是可执行的(启动docker run时不额外指定启动命令就可以运行),那么你必须在Dockerfile中使用ENTRYPOINT或CMD。

尝试运行一个没有使用ENTRYPOINT或CMD指令的image,启动时会报错:

$ docker run alpine
FATA[0000] Error response from daemon: No command specified

你能在Docker Hub上找到的大多数linux版本基础镜像都使用了/bin/sh/bin/bash这样的shell命令来作为CMD启动命令。这意味着,任何人运行这些image时,都会默认进入到交互式shell界面中(假设运行时指定了-t/-i参数)

这对通用的基础镜像是十分方便的,但是当你希望运行自己的image时(即非通用基础image时),更多时候需要指定一个更具体的可执行文件或命令来作为CMD或ENTRYPOINT参数。

在 Dockerfile 中,CMD 和 ENTRYPOINT 都用于指定容器启动时要执行的命令。它们之间的主要区别是:

- CMD 用于定义容器启动时要执行的命令和参数,它设置的值可以被 Dockerfile 中的后续指令覆盖,包括在运行容器时传递的参数。

- Entrypoint是指定容器启动时要执行的默认命令,它在运行容器时不能被覆盖。而Cmd是指定容器启动时要执行的默认命令参数,它可以被覆盖。通常情况下,Entrypoint用于指定容器启动时要运行的应用程序,而Cmd用于指定应用程序的默认参数。 

1、CMD 指令 


CMD在容器运行的时候提供一些命令及参数,用法如下:

  • CMD ["executable","param1","param2"] (exec form, this is the preferred form)

  • CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

  • CMD command param1 param2 (shell form)

第一种用法:运行一个可执行的文件并提供参数。(可执行程序+参数)

第二种用法:为ENTRYPOINT指定参数。(cmd指定参数)

第三种用法(shell form):是以”/bin/sh -c”的方法执行的命令。(执行shell命令)

如你指定:

CMD [“/bin/echo”, “this is a echo test ”]

build后运行(假设镜像名为ec):

docker run ec

就会输出:

this is a echo test

是不是感觉很像开机启动项,你可以暂时这样理解。

注意点:

docker run命令如果指定了参数会把CMD里的参数覆盖: (这里说明一下,如:docker run -it ubuntu /bin/bash 命令的参数是指/bin/bash而非 -it ,-it只是docker 的参数,而不是容器的参数,以下所说参数均如此。)

同样是上面的ec镜像启动:

docker run ec /bin/bash

就不会输出: this is a echo test 因为CMD命令被”/bin/bash”覆盖了。

- ENTRYPOINT 也用于定义容器启动时要执行的命令,但不像 CMD,它的值不会被 Dockerfile 中的后续指令覆盖,只能在运行容器时添加参数来覆盖它。也就是说,ENTRYPOINT 设置的命令一般是容器镜像所要执行的主要命令,CMD 则是选项和参数。

换句话说,CMD 是为 ENTRYPOINT 提供默认选项,ENTRYPOINT 则是容器镜像中主要执行的命令。在 Dockerfile 中定义 ENTRYPOINT 可以使您的镜像更像一个可执行文件,而在运行容器时传递参数可以以更灵活的方式执行此命令。

2、ENTRYPOINT 指令

ENTRYPOINT指令适合用于:希望容器最终运行时所执行的命令与Dockerfile内配置的命令相同的场景下。也就是说,不希望用户重写image启动命令。 

字面意思是进入点,而它的功能也恰如其意。它可以让你的容器功能表现得像一个可执行程序一样。

容器功能表现得像一个可执行程序一样,这是什么意思呢?直接给个例子好说话,使用下面的ENTRYPOINT构造镜像:

ENTRYPOINT ["/bin/echo"]

那么docker build出来的镜像以后的容器功能就像一个/bin/echo程序,比如我build出来的镜像名称叫imageecho,那么我可以这样用它:

docker  run  -it  imageecho  “this is a test”

这里就会输出”this is a test”这串字符,而这个imageecho镜像对应的容器表现出来的功能就像一个echo程序一样。 你添加的参数“this is a test”会添加到ENTRYPOINT后面,就成了这样 /bin/echo “this is a test” 。现在你应该明白进入点的意思了吧。

例子:

ENTRYPOINT ["/bin/cat"]

构造出来的镜像你可以这样运行(假设名为st):这样相当: /bin/cat /etc/fstab 这个命令的作用。运行之后就输出/etc/fstab里的内容。

ENTRYPOINT

  • ENTRYPOINT 也是在 Dockerfile 中定义的,它用于指定容器启动时始终执行的命令,这个命令不那么容易被 docker run 的命令行参数覆盖,除非以组合的形式追加参数。

  • ENTRYPOINT 也有两种格式,与 CMD 相似:

    • ENTRYPOINT ["executable", "param1"]exec形式,优先级高于 CMD,并且无论是否提供 docker run 后的命令,都会执行此命令,并将 docker run 后的参数追加到 ENTRYPOINT 后。(其实就是一个可执行的程序)

    • ENTRYPOINT command param1shell格式

  • 使用 ENTRYPOINT 可以确保每次容器启动时都执行同一命令,这有助于将容器设计得更加“应用导向”,使得容器的行为更一致。当同时设置了 CMD 和 ENTRYPOINT 时,CMD 的内容会被视为 ENTRYPOINT 的参数。

正确写法:shell格式,可以跟着很多参数,其实就是在linux执行的命令

ENV JAVA_OPTS="-Xmx512m -Xms512m" 

ENTRYPOINT  java $JAVA_OPTS -jar /demo.jar --server.port=8000

ENTRYPOINT ["/bin/sh","-c","java $JAVA_OPTS -jar /demo.jar --server.port=8000"]

/bin/sh是可执行程序,exec形式

错误写法:exec形式,就两部分内容,一个是可执行程序,一个是参数,java不是可执行程序

ENTRYPOINT  ["java",$JAVA_OPTS, "-jar", "/demo.jar","--server.port=8000"]

ENTRYPOINT有两种写法:

写法一:

1

ENTRYPOINT ["executable", "param1", "param2"] (the preferred exec form)

写法二:

1

ENTRYPOINT command param1 param2 (shell form)

你也可以在docker run 命令时使用–entrypoint指定(但是只能用写法一)。

下面是我把ENTRYPOINT设为[“/bin/sh -c”]时候运行的情况:

# docker run -it t2 /bin/bash
root@4c8549e7ce3e:/# ps
PID TTY TIME CMD
1 ? 00:00:00  sh
9 ? 00:00:00  bash
19 ? 00:00:00  ps

可以看到PID为1的进程运行的是sh,而bash只是sh的一个子进程,/bin/bash只是作为 /bin/sh -c后面的参数。

CMD可以为ENTRYPOINT提供参数,ENTRYPOINT本身也可以包含参数,但是你可以把那些可能需要变动的参数写到CMD里而把那些不需要变动的参数写到ENTRYPOINT里面例如:

1

2

3

FROM  ubuntu:14.10

ENTRYPOINT  ["top", "-b"]

CMD  ["-c"]

把可能需要变动的参数写到CMD里面。然后你可以在docker run里指定参数,这样CMD里的参数(这里是-c)就会被覆盖掉而ENTRYPOINT里的不被覆盖。

--------------------------------------------------------------------------------------------------------------------------------

在Docker中,CMDENTRYPOINT都是用于指定容器启动时要执行的命令或脚本。它们之间的区别如下:

CMD用于指定容器启动时要执行的命令。它可以有三种不同的形式:

  • CMD ["executable","param1","param2"](使用JSON数组形式):推荐使用这种形式,它会直接执行指定的可执行文件,并传递参数。

  • CMD command param1 param2(使用命令形式):这种形式会将命令传递给shell进行解释执行。

  • CMD ["param1","param2"](使用JSON数组形式):这种形式会将指定的参数传递给ENTRYPOINT指定的可执行文件。

在Dockerfile中,可以使用多个CMD指令,但只有最后一个CMD指令会生效。如果容器启动时没有指定要执行的命令,将会执行最后一个CMD指令中指定的命令。

ENTRYPOINTENTRYPOINT用于指定容器启动时要执行的可执行文件。它可以有两种不同的形式:

  • ENTRYPOINT ["executable", "param1", "param2"](使用JSON数组形式):推荐使用这种形式,它会直接执行指定的可执行文件,并传递参数。

  • ENTRYPOINT command param1 param2(使用命令形式):这种形式会将命令传递给shell进行解释执行。

在Dockerfile中,只能使用一个ENTRYPOINT指令。如果同时存在CMD指令,CMD中的参数将会作为ENTRYPOINT指定的可执行文件的参数进行传递。

 

总结起来:

  • CMD 是容器启动时如果没有指定命令时的默认行为,它的灵活性较高,易于被 docker run 后的命令覆盖。

  • ENTRYPOINT 更像是容器的核心功能定义,常用于定义容器的主应用程序,并且能接收 docker run 的参数,这样可以确保容器启动时总是执行预期的程序,并且可以处理任何额外的参数。

综上所述,两者可以配合使用,共同决定容器启动时的具体行为,从而更好地控制容器的应用场景和定制程度。

CMD用于指定容器启动时要执行的命令参数,而ENTRYPOINT用于指定容器启动时要执行的可执行文件。可以将ENTRYPOINT看作是容器的入口点,而CMD则是对ENTRYPOINT指定的可执行文件的参数进行补充。

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

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

相关文章

通过实例学C#之ArrayList

介绍 ArrayList对象可以容纳若干个具有相同类型的对象,那有人说,这和数组有什么区别呢。其区别大概可以分为以下几点: 1.数组效率较高,但其容量固定,而且没办法动态改变。 2.ArrayList容量可以动态增长,但…

ros1中python3包调用自定义.py文件

ros中python包相互import不成功问题 问题解决办法 问题 在ros工程中,运行python文件难以直接import自己写的py文件,相互之间无法import,但是在python3虚拟环境python *.py文件就可以正常运行! 注意这里还有个问题,我…

❤️‍FlyFlow工作流周更来咯~~

FlyFlow 借鉴了钉钉与飞书的界面设计理念,致力于打造一款用户友好、快速上手的工作流程工具。相较于传统的基于 BPMN.js 的工作流引擎,我们提供的解决方案显著简化了操作逻辑,使得用户能够在极短的时间内构建定制化的业务流程,即便…

前端近7天,近半个月,近1个月,近1年的日期处理

前端如何获取近7天,近1年的日期进行查询? methods:{//近7天getRangeDate(ranges) {let nowDays new Date();let getYear nowDays.getFullYear();let getMonth nowDays.getMonth() 1;let getDate nowDays.getDate();let nd new Date();nd nd.valueOf();nd nd - ranges…

记录汇川:五个ST案例

起保停: 简单数学教学: 数据查找: 按钮检测: 数据堆栈:

【k8s】:kubectl 命令设置简写启用自动补全功能

【k8s】:kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能💖The Begin💖点点关注,收藏不迷路💖 Kubernetes(K8s)是一个强大的容器编排平台,而kubectl则是与之交互的命令行工具。尽管Kubernetes提供了强大的功能,但有时…

wiringpi库的应用 -- sg90 定时器 oled

sg 90舵机: 接线: VCC -- 红 GND -- 地 信号线 -- 黄 -- pwm 定时器: 先玩定时器: sg90 需要的pwm波需要定时器输出,so我们得先来玩一下定时器 分析:实现定时器,通过itimerval结构体以及函数setitimer产生的信号,系统…

python装饰器系列教程(1)

若为了与用户交互,有如下代码 def messageOne():print("今天天气是晴转多云")def messageTwo():print("今天的空气质量为优")messageOne() messageTwo()现需在每条提示信息之前加上一条关于客户来自中国的信息,可改写为 def messa…

快手本地生活服务商系统怎么操作?

当下,抖音和快手两大短视频巨头都已开始布局本地生活服务,想要在这一板块争得一席之地。而这也很多普通人看到了机遇,选择成为抖音和快手的本地生活服务商,通过将商家引进平台,并向其提供代运营服务,而成功…

深入探讨虚拟现实中的新型安全威胁:“盗梦攻击”及其防御策略

随着虚拟现实(VR)技术的飞速发展,用户体验达到了前所未有的沉浸水平,但也暴露在一系列新的安全威胁之下。本文着重介绍了近期出现的一种高度隐秘且影响深远的攻击手段——“盗梦攻击”。这一概念由芝加哥大学的研究人员提出&#…

前端打包webpack vite

起步 | webpack 中文文档 | webpack中文文档 | webpack中文网 npm run build 1webpack: mkdir webpack-demo cd webpack-demo npm init -y npm install webpack webpack-cli --save-dev vite : 快速上手 | Vue.js

介绍TCP协议标志位

TCP协议中的控制位(Flags)是TCP头部中的6个标志位,用于控制TCP连接的建立、维护和终止过程,以及在数据传输中的一些特定行为。以下是对每个标志位的详细介绍: SYN (Synchronize): 功能:用于建立…

【Entity Framework】闲话EF中批量配置

【Entity Framework】闲话EF中批量配置 文章目录 【Entity Framework】闲话EF中批量配置一、概述二、OnModelCreating中的批量配置元数据API的缺点 三、预先约定配置忽略类型默认类型映射预先约定配置的限制约定添加新约定替换现有约定约定实现注意事项 四、何时使用每种方法进…

游戏登录界面制作

登录界面制作 1.导入模块和初始化窗口 import subprocessimport tkinter as tkimport picklefrom tkinter import messageboxwindow tk.Tk()window.title(Welcome)window.geometry(450x300) 导入必要的模块,并初始化了主窗口window,设置了窗口的标题和…

【技巧】Leetcode 169. 多数元素【简单】

多数元素 给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 : 输入:nums [2,2,1,1,1,2,2] 输出&a…

day22 java多线程 线程安全问题解决方案

线程安全问题 [面试题]继承Thread和实现Runnable有什么区别? 1.实现接口和继承类 - 实现接口更灵活因为可以多实现。 2.线程安全 同步代码块 : 继承Thread : 锁不可以是this 实现Runnable : 锁可以是this 同步方法 继承Thread : 同步方法要使用静态同步…

修改taro-ui-vue3的tabs组件源码增加数字标签

需求:taro-ui-vue3的tabs组件上增加数字标记 步骤一:node_modules文件夹下找到taro-ui-vue3/lib/tabs/index.js 把173行的这一段替换成下面这段,然后写上样式 default: () > item.number ? [h(View, {class: at-tabs__item_in}, {defau…

Unity导出package

C#代码导出后为一个dll,原有的不同平台的库不变。 以下操作均在build PC 平台下操作。 1.在要导出的文件夹下建assembly definition (Any platform) 2.将项目文件夹下的\Library\ScriptAssemblies中的相应assembly definition的dll复制到要导出的文件夹下 3.在uni…

gstreamer pad cap的协商

这是在大模型中获取的答案,有点意思。 在 GStreamer 中,大多数时候 pad 协商是通过框架自动完成的,并且不需要手动干预。但是,了解如何在代码里面执行 pad 协商是很有帮助的,这在创建自定义元素或更细致地控制数据流时…

关于Pwn的一些文章

关于Pwn的一些文章 仅仅是本人为了方便查阅资料而已 1、保护机制: https://www.zhihu.com/question/464671097/answer/3257122786https://blog.csdn.net/m0_71081503/article/details/127732602 2、DA常用快捷键及其作用 https://blog.csdn.net/weixin_4574396…