在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
当前回答
•Dockerfile应至少指定一条CMD或ENTRYPOINT指令
•仅使用Dockerfile中的最后一个CMD和ENTRYPOINT
•将容器用作可执行文件时,应定义ENTRYPOINT
•您应该使用CMD指令来定义默认参数定义为ENTRYPOINT的命令或用于在容器
•使用替代参数运行容器时,CMD将被覆盖
•ENTRYPOINT设置每次容器是使用图像创建的
•如果您将ENTRYPOINT与CMD结合,则可以从CMD中删除可执行文件并且只留下将传递给ENTRYPOINT的参数
•ENTRYPOINT的最佳用途是设置图像的主命令,允许映像要像运行该命令一样运行(然后使用CMD作为默认值标志)
其他回答
代码中EntryPoint函数的注释
//入口/usr/sbin/nginx。//将入口点(默认为sh-c)设置为/usr/sbin/nginx。//将接受CMD作为/usr/sbin/nginx的参数。
文件中的另一个参考
您可以使用ENTRYPOINT的exec形式设置相当稳定的默认命令和参数,然后使用CMD设置更可能更改的其他默认值。
例子:
FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]
Build:sudo docker Build-t ent_cmd。
CMD arguments are easy to override.
NO argument (sudo docker -it ent_cmd) : ping localhost
argument (sudo docker run -it ent_cmd google.com) : ping google.com
.
To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd
附笔:在存在EntryPoint的情况下,CMD将保存要馈送到EntryPoint的参数。如果没有EntryPoint,CMD将是将要运行的命令。
通过从头开始重建OS映像(只需从头开始编写,并在dockerfile中使用COPY复制最小的文件系统),我了解到,
如果没有在dockerfile中指定ENTRYPOINT和CMD,docker将使用
/bin/sh -c
作为默认ENTRYPOINT,如果在docker文件中定义CMD或在运行容器时传递命令行参数(这将覆盖已定义的CMD),则将采用CMD。
假设您传递一个参数(或在dockerfile中定义CMD)ls,那么它将被馈送到ENTRYPOINT。即,
/bin/sh -c ls
/bin/sh-c将运行传递给它的任何参数。您将获得“ls”命令的输出,然后容器将退出。
ubuntu映像没有显式定义ENTRYPOINT,因此docker将使用/bin/sh-c,但包含CMD定义,即bash运行容器的以下命令,
docker container run -it ubuntu
Docker实际上使用ENTRYPOINT作为/bin/sh-c,然后使用bash为其提供数据最终运行的是
/bin/sh -c bash
它启动交互式bash终端(仅当如上所述指定了-i标志并可选地指定了-t以获得类似本地终端的体验时)
当您通过命令行提供参数时,bash将被替换为您传递的任何内容,输出将根据该内容,即
/bin/sh -c passed_argument
您可以定义自定义ENTRYPOINT,它将覆盖默认ENTRYPOINT,但随后需要相应地使用CMD。
对于dockerfile中的RUN命令,它不考虑定义的ENTRYPOINT和CMD,而是运行指定的命令,因为它们被提供给中间容器中的交互式bash终端
我想以轻松的方式区分CMD、RUN和ENTRYPOINT之间的差异。
让我们以节点的npm init为例。
命令:
假设下面是我们在dockerfile中添加的初始命令
CMD [ "npm", "init" ]
现在,如果我运行docker,运行-t node npm install
它将覆盖dockerfile中的npm init命令。
CMD [ "npm", "init" ] This will become CMD [ "npm", "install" ]
它将执行npm install命令,而不是npm init,因为它会使用npm install。
现在,我们来谈谈
入口点:
假设在docker文件中添加了相同的命令,但使用ENTRYPOINT
ENTRYPOINT [ "npm", "init" ]
现在,如果我运行docker,运行-t节点安装
它将在dockerfile中附加npm init命令和npm install。
ENTRYPOINT [ "npm", "init" ] This will become ENTRYPOINT [ "npm", "init", "install" ]
它将同时执行npm init和npm install命令。
总结如下:
RUN:这将在生成图像时执行。用于安装任何依赖项,如node_modules。例如RUN npm安装
CMD:要覆盖完整命令时使用
ENTRYPOINT:要附加一些附加命令时使用。
是的,这是个好问题。我还不完全理解,但是:
我知道ENTRYPOINT是正在执行的二进制文件。可以通过--entrypoint=“”覆盖entrypoint。
docker run -t -i --entrypoint="/bin/bash" ubuntu
CMD是容器的默认参数。如果没有入口点,默认参数是执行的命令。使用entrypoint,cmd将作为参数传递给entryppoint。您可以使用入口点模拟命令。
# no entrypoint
docker run ubuntu /bin/cat /etc/passwd
# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
所以,主要优点是使用entrypoint可以将参数(cmd)传递给容器。要做到这一点,您需要同时使用:
# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]
and
docker build -t=cat .
那么您可以使用:
docker run cat /etc/passwd
# ^^^^^^^^^^^
# CMD
# ^^^
# image (tag)- using the default ENTRYPOINT
我将把我的答案作为一个例子,1这样可以帮助你更好地理解其中的区别。
假设我们希望创建一个图像,该图像在启动时始终运行sleep命令。我们将创建自己的映像并指定一个新命令:
FROM ubuntu
CMD sleep 10
构建图像:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
如果我们想改变秒数怎么办?我们必须更改Dockerfile,因为该值是硬编码的,或者通过提供不同的值来重写该命令:
docker run custom_sleep sleep 20
虽然这是可行的,但这不是一个好的解决方案,因为我们有一个冗余的“睡眠”命令。为什么冗余?因为容器的唯一目的是睡眠,所以必须显式指定睡眠命令有点尴尬。
现在,让我们尝试使用ENTRYPOINT指令:
FROM ubuntu
ENTRYPOINT sleep
此指令指定容器启动时将运行的程序。
现在我们可以运行:
docker run custom_sleep 20
默认值如何?嗯,你猜对了:
FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
ENTRYPOINT是将要运行的程序,传递给容器的值将附加到该程序。
可以通过指定--ENTRYPOINT标志,后跟要使用的新入口点来覆盖ENTRYPOINT。
不是我的,我曾经看过一个提供了这个例子的教程