Docker_Dockerfile中保留字指令CMD和ENTRYPOINT区别

本文详细解析了Docker中CMD与ENTRYPOINT指令的区别,通过实例演示了两者的使用场景与行为差异,CMD易被docker run参数覆盖,而ENTRYPOINT则会追加参数。

CMD

指定一个容器启动时要运行的命令
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被 docker run之后的参数替换

ENTRYPOINT

指定一个容器启动时要运行的命令
ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数

验证

验证中使用的命令为curl

首先编写Dockerfile文件,内容如下:

FROM centos:7
RUN yum -y install curl
CMD ["curl","-s","https://ip.cn"]

build构建新的镜像

[root@localhost myDocker]# docker build -f /myDocker/DockerfileTree -t myip .
Sending build context to Docker daemon  4.096kB
Step 1/3 : FROM centos:7
 ---> 5e35e350aded
Step 2/3 : RUN yum -y install curl
 ---> Running in cb4a10126aa2
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: mirror.bit.edu.cn
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
Package curl-7.29.0-54.el7.x86_64 already installed and latest version
Nothing to do
Removing intermediate container cb4a10126aa2
 ---> 88d37e3c7f89
Step 3/3 : CMD ["curl","-s","https://ip.cn"]
 ---> Running in 80b594b5d5ae
Removing intermediate container 80b594b5d5ae
 ---> 38e3d380c971
Successfully built 38e3d380c971
Successfully tagged myip:latest

运行容器

[root@localhost myDocker]# docker run myip
{"ip": "118.113.40.151", "country": "四川省成都市", "city": "电信"}

现在需要在原有的 curl -s https://ip.cn 后面追加一个-i得到报文头

[root@localhost myDocker]# docker run myip -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.

可以看到,CMD后面的命令,会被docker run后面的命令覆盖掉,也就是我刚才写的 -i

测试ENTRYPOINT指令,方法一样,只不过构建文件的最后CMD替换为ENTRYPOINT

FROM centos:7
RUN yum -y install curl
ENTRYPOINT ["curl","-s","https://ip.cn"]

build新镜像

[root@localhost myDocker]# docker build -f /myDocker/DockerfileFour -t myip2 .
Sending build context to Docker daemon   5.12kB
Step 1/3 : FROM centos:7
 ---> 5e35e350aded
Step 2/3 : RUN yum -y install curl
 ---> Using cache
 ---> 88d37e3c7f89
Step 3/3 : ENTRYPOINT ["curl","-s","https://ip.cn"]
 ---> Running in 41efe0250802
Removing intermediate container 41efe0250802
 ---> 0c174d9b9d07
Successfully built 0c174d9b9d07
Successfully tagged myip2:latest

运行myip2

[root@localhost myDocker]# docker run myip2
{"ip": "118.113.40.151", "country": "四川省成都市", "city": "电信"}

在末尾添加-i

[root@localhost myDocker]# docker run myip2 -i
HTTP/1.1 200 OK
Date: Mon, 25 Nov 2019 13:56:30 GMT
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d66201e01a5389c244826811f2a98b9d31574690190; expires=Wed, 25-Dec-19 13:56:30 GMT; path=/; domain=.ip.cn; HttpOnly
CF-Cache-Status: DYNAMIC
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 53b4205b9fc8eb91-LAX

{"ip": "118.113.40.151", "country": "四川省成都市", "city": "电信"}

可以证明ENTRYPOINT后面的写的命令,并没有被我后面添加的-i指令覆盖,而是被追加在了后面,相当于最后的命令变为了 curl -s https://ip.cn -i

### Dockerfile 指令与镜像层创建总结 在 Dockerfile 中,不同的指令对镜像层的创建有不同的影响。以下是对常见指令是否生成新镜像层的总结: | Dockerfile 指令 | 是否生成新镜像层 | 说明 | |------------------|------------------|------| | `FROM` | 否 | 指定基础镜像,作为构建的起点,不创建新层 [^1]。 | | `RUN` | 是 | 执行命令并生成新的镜像层,包含命令执行后的文件系统变化 。 | | `COPY` | 是 | 将本地文件复制到镜像中,生成新的镜像层 [^1]。 | | `ADD` | 是 | 类似于 `COPY`,但支持额外功能(如解压归档文件),生成新层 。 | | `CMD` | 否 | 设置容器启动时的默认命令,仅修改镜像的元数据 [^1]。 | | `ENTRYPOINT` | 否 | 定义容器启动时执行的主要命令,与 `CMD` 配合使用,不生成新层 [^1]。 | | `EXPOSE` | 否 | 声明容器监听的端口,仅用于文档运行时提示,不生成新层 [^1]。 | | `ENV` | 否 | 设置环境变量,仅修改元数据,不生成新层 。 | | `ARG` | 否 | 定义构建时的变量,不生成新层 [^1]。 | | `VOLUME` | 否 | 声明容器使用的持久化卷,不生成新层 [^1]。 | | `WORKDIR` | 否 | 设置工作目录,仅修改元数据,不生成新层 [^1]。 | | `LABEL` | 否 | 添加元数据标签,不生成新层 。 | | `ONBUILD` | 否 | 定义触发器指令,仅在构建子镜像时执行,不直接生成新层 。 | ### 镜像层构建示例 ```dockerfile FROM ubuntu:latest COPY . /app # 创建新层 RUN apt-get update && apt-get install -y python3 # 创建新层 CMD ["python", "app.py"] # 不创建新层 ``` ### 镜像层优化建议 为了减少镜像的层数并优化构建效率,可以合并多个操作到单条 `RUN` 指令中,例如: ```dockerfile RUN apt-get update && \ apt-get install -y python3 && \ rm -rf /var/lib/apt/lists/ ``` 这样可以避免每次 `RUN` 都生成一个独立的层,有助于减小镜像体积并提升构建速度 [^1]。 ### 镜像层缓存机制 Dockerfile 中的每个指令都会创建一个新的镜像层,镜像层将被缓存复用。如果某一层的指令发生变化,其缓存失效,并且该层之后的所有镜像层缓存也会失效。镜像层是不可变的,即使在后续层中删除了某个文件,该文件仍会存在于镜像中 。 ### 相关问题 1. Dockerfile 中哪些指令会影响镜像的构建缓存? 2. 如何优化 Dockerfile 以减少镜像的大小? 3. DockerfileENTRYPOINT CMD区别是什么? 4. 如何查看 Docker 镜像的构建历史每一层的信息? 5. 在 Dockerfile 中,为什么有时候需要清理 apt 缓存?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值