Docker之CMD与ENTRYPOINT的区别

本文详细介绍了Docker中CMD和ENTRYPOINT的区别与用法。通过实例对比,展示如何在容器启动时指定命令,以及ENTRYPOINT如何允许追加参数。

CMD和ENTRYPOINT

CMD:指定这个容器启动的时候需要执行的命令,但是只有最后一个CMD会生效
ENTRYPOINT:指定这个容器启动的时候需要执行的命令,且可以追加命令

测试CMD
1、编写使用CMD的dockerfile文件
举例:测试制作centos镜像时,输出ls -a的全部目录

FROM centos
CMD ["ls","-a"]

2、构建镜像

[root@liuyang dockerfile]# docker build -f first_dockerfile_cmd  -t centos_liuyang:1.4  .

#输出日志

Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 2a3b27d08525
Removing intermediate container 2a3b27d08525
 ---> 67b2d498c93c
Successfully built 67b2d498c93c
Successfully tagged centos_liuyang:1.4
[root@liuyang dockerfile]# docker images
REPOSITORY              TAG       IMAGE ID       CREATED          SIZE
centos_liuyang          1.4       67b2d498c93c   7 seconds ago    209MB
centos_dockerfile       1.3       2900faf7489f   16 minutes ago   291MB
centos_dockerfile       1.1       ff7532b27bf0   31 minutes ago   291MB
centos_dockerfile       1.2       316bfc73c556   31 minutes ago   291MB
liuyang_centos/centos   1.0       6bb3a414dd02   5 hours ago      209MB
centos                  1.2       c7755e562e14   2 days ago       209MB
mysql                   5.7       a70d36bc331a   7 weeks ago      449MB
tomcat                  latest    040bdb29ab37   2 months ago     649MB
nginx                   latest    f6d0b4767a6c   2 months ago     133MB
centos                  latest    300e315adb2f   3 months ago     209MB

3、查看镜像,并启动容器,查看效果(是否生成了centos 的ls -a,也就是CMD指令)

[root@liuyang dockerfile]# docker run -it 67b2d498c93c
.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr
..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var

已生效!

此时我想在指令ls -a 后面追加l 变成ls -al :

[root@liuyang dockerfile]# docker run -it 67b2d498c93c -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled
[root@liuyang dockerfile]#

发现不行,必须写全代码:

[root@liuyang dockerfile]# docker run -it 67b2d498c93c  ls -al
total 56
drwxr-xr-x   1 root root 4096 Mar 14 14:14 .
drwxr-xr-x   1 root root 4096 Mar 14 14:14 ..
-rwxr-xr-x   1 root root    0 Mar 14 14:14 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3 15:22 bin -> usr/bin
drwxr-xr-x   5 root root  360 Mar 14 14:14 dev
drwxr-xr-x   1 root root 4096 Mar 14 14:14 etc
drwxr-xr-x   2 root root 4096 Nov  3 15:22 home
lrwxrwxrwx   1 root root    7 Nov  3 15:22 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3 15:22 lib64 -> usr/lib64
drwx------   2 root root 4096 Dec  4 17:37 lost+found
drwxr-xr-x   2 root root 4096 Nov  3 15:22 media
drwxr-xr-x   2 root root 4096 Nov  3 15:22 mnt
drwxr-xr-x   2 root root 4096 Nov  3 15:22 opt
dr-xr-xr-x 145 root root    0 Mar 14 14:14 proc
dr-xr-x---   2 root root 4096 Dec  4 17:37 root
drwxr-xr-x  11 root root 4096 Dec  4 17:37 run
lrwxrwxrwx   1 root root    8 Nov  3 15:22 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3 15:22 srv
dr-xr-xr-x  13 root root    0 Mar  1 05:43 sys
drwxrwxrwt   7 root root 4096 Dec  4 17:37 tmp
drwxr-xr-x  12 root root 4096 Dec  4 17:37 usr
drwxr-xr-x  20 root root 4096 Dec  4 17:37 var
[root@liuyang dockerfile]#

现在我们试一试ENTRYPOINT:
1、编写使用ENTRYPOINT的dockerfile文件
举例:测试制作centos镜像时,输出ls -a的全部目录

FROM centos
ENTRYPOINT ["ls","-a"]

2、构建镜像

[root@liuyang dockerfile]# docker build -f first_dockerfile_ENTRYPOINT  -t centos_liuyang:1.6 .

3、查看镜像,并启动容

[root@liuyang dockerfile]# docker run -it 2c0580c11880
.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr
..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var
器,查看效果(是否生成了centos 的ls -a)

4、此时我想在指令ls -a 后面追加l 变成ls -al :

[root@liuyang dockerfile]# docker run -it 2c0580c11880 -l
total 56
drwxr-xr-x   1 root root 4096 Mar 14 14:16 .
drwxr-xr-x   1 root root 4096 Mar 14 14:16 ..
-rwxr-xr-x   1 root root    0 Mar 14 14:16 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3 15:22 bin -> usr/bin
drwxr-xr-x   5 root root  360 Mar 14 14:16 dev
drwxr-xr-x   1 root root 4096 Mar 14 14:16 etc
drwxr-xr-x   2 root root 4096 Nov  3 15:22 home
lrwxrwxrwx   1 root root    7 Nov  3 15:22 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3 15:22 lib64 -> usr/lib64
drwx------   2 root root 4096 Dec  4 17:37 lost+found
drwxr-xr-x   2 root root 4096 Nov  3 15:22 media
drwxr-xr-x   2 root root 4096 Nov  3 15:22 mnt
drwxr-xr-x   2 root root 4096 Nov  3 15:22 opt
dr-xr-xr-x 144 root root    0 Mar 14 14:16 proc
dr-xr-x---   2 root root 4096 Dec  4 17:37 root
drwxr-xr-x  11 root root 4096 Dec  4 17:37 run
lrwxrwxrwx   1 root root    8 Nov  3 15:22 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3 15:22 srv
dr-xr-xr-x  13 root root    0 Mar  1 05:43 sys
drwxrwxrwt   7 root root 4096 Dec  4 17:37 tmp
drwxr-xr-x  12 root root 4096 Dec  4 17:37 usr
drwxr-xr-x  20 root root 4096 Dec  4 17:37 var
[root@liuyang dockerfile]#

生效!与CMD的区别显而易见,ENTRYPOINT 可以直接在run 后面追加 代码!

<think>好的,我现在需要回答用户关于DockerCMDENTRYPOINT区别的问题。首先,我得回忆一下这两个指令的基本作用。记得CMD用于设置容器启动时的默认命令和参数,而ENTRYPOINT则是用来配置容器启动时执行的主命令。不过用户提供的引用里提到了一些细节,比如CMD可以被覆盖,而ENTRYPOINT的参数在运行时只能添加,不能直接覆盖。需要结合引用中的例子来理清区别。 根据引用[1],ENTRYPOINT设置的命令不会被后续指令覆盖,运行容器时只能添加参数。而CMD作为默认参数,可以被docker run后面的参数覆盖。例如,在引用[4]中,运行容器时指定了/bin/bash,这会覆盖CMD的默认参数。这说明CMD更容易被覆盖,而ENTRYPOINT更固定。 然后要看两者的组合使用。引用[3]提到mysql镜像的例子,ENTRYPOINT执行初始化脚本,CMD作为默认参数。这种情况下,CMD的参数会传递给ENTRYPOINT,用户可以在运行时修改CMD的参数。需要解释这种组合使用的情况,以及单独使用时的不同效果。 还要注意两种格式:exec格式和shell格式的区别。exec格式不会启动shell进程,而shell格式会。这可能会影响信号处理和环境变量的使用。例如,使用shell格式的CMD可能无法正确接收SIGTERM信号。 用户的问题还涉及到应用场景,比如ENTRYPOINT适合做初始化,CMD适合提供默认参数。需要结合引用中的例子,如mysql镜像的ENTRYPOINT运行脚本,CMD设置mysqld作为默认命令。 最后,要总结两者的区别,包括覆盖方式、组合使用时的参数传递、适用场景,以及格式的影响。确保回答结构清晰,分点说明,并引用提供的资料来支持每个观点。</think>### Dockerfile中CMDENTRYPOINT区别及用法 #### 一、核心区别 1. **覆盖性** - **CMD**:定义容器启动时的默认命令和参数,但会被`docker run`后的参数完全覆盖[^1][^4]。例如: ```dockerfile CMD ["echo", "hello"] ``` 运行`docker run image_name echo "world"`时,最终输出`world`而非`hello`[^4]。 - **ENTRYPOINT**:定义容器启动时的主命令,不会被覆盖,仅通过`docker run`添加额外参数[^3]。例如: ```dockerfile ENTRYPOINT ["echo"] ``` 运行`docker run image_name "world"`时,输出`hello world`(若Dockerfile中同时有`CMD ["hello"]`)。 2. **参数传递方式** - 当同时使用`ENTRYPOINT`和`CMD`时,`CMD`的内容会作为参数传递给`ENTRYPOINT`。例如: ```dockerfile ENTRYPOINT ["docker-entrypoint.sh"] CMD ["mysqld"] ``` 实际执行命令为`docker-entrypoint.sh mysqld`。 #### 二、使用场景对比 | 特性 | CMD | ENTRYPOINT | |---------------------|------------------------------|---------------------------------| | 主要用途 | 提供默认参数 | 定义容器主执行逻辑 | | 覆盖方式 | 完全被`docker run`参数覆盖 | 仅追加`docker run`参数 | | 典型场景 | 临时调试(如启动shell) | 初始化脚本(如数据库配置) | | 是否依赖Shell解析 | 支持Shell格式(如`CMD echo`)| 推荐使用Exec格式(避免信号问题)| #### 三、组合用法示例 ```dockerfile ENTRYPOINT ["/bin/nginx"] CMD ["-c", "/etc/nginx/conf.d/default.conf"] ``` - 运行`docker run nginx`时,执行命令:`/bin/nginx -c /etc/nginx/conf.d/default.conf` - 若添加参数:`docker run nginx -g "daemon off;"`,则最终命令为:`/bin/nginx -g "daemon off;"` #### 四、格式注意事项 1. **Exec格式(推荐)** 使用JSON数组格式(如`ENTRYPOINT ["echo"]`),直接执行命令,不启动shell进程,可正确处理信号。 2. **Shell格式** 以字符串形式书写(如`ENTRYPOINT echo`),会通过`/bin/sh -c`执行,可能导致信号无法传递到主进程。 #### 五、调试技巧 若需覆盖ENTRYPOINT,可使用`--entrypoint`参数: ```bash docker run --entrypoint sh mysql -c "echo test" ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘小羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值