48-Dockerfile-CMD/ENTRYPOINT指令

CMD用于设置容器启动时默认执行的命令,可被dockerrun覆盖。ENTRYPOINT则定义容器的入口命令,所有其他参数都将作为其参数。一个Dockerfile只能有一个有效的CMD或ENTRYPOINT。CMD示例包括ping命令和打印环境变量。ENTRYPOINT示例展示了如何设置ls-a命令作为入口。两者的区别在于CMD可以被覆盖,而ENTRYPOINT可以接受附加参数。


前言

  • 本篇来学习下Dockerfile中的CMD/ENTRYPOINT指令

CMD

作用
  • 启动容器时默认执行的命令

说明:

  • 一个 Dockerfile 只有一个 CMD 指令,只有最后一个 CMD 指令生效
  • 使用 docker run -d xxx CMD 命令是可以覆盖 Dockerfile 中的 CMD 指令的
格式
# exec 方式, 首选方式  CMD ["可执行命令", "参数1", "参数2"...]
CMD ["executable","param1","param2"]

# 为 ENTRYPOINT 提供默认参数
CMD ["param1","param2"]

# shell 形式  CMD 命令 参数1  参数2
CMD command param1 param2
使用示例
  • 新建dockerfile
FROM ubuntu
#  CMD 和 ENTRYPOINT 作为唯一入口,写多个,只有最后一个生效
# shell方式
CMD ping bing.com

# exec方式
CMD [ "sh", "-c", "echo $HOME" ]
  • 制作镜像
docker build -t test --force-rm --no-cache .
  • 运行容器
# --rm 表示容器退出,自动删除
docker run -it --rm test
  • 可以看到只执行了后面的echo $HOME,没执行ping 命令
    在这里插入图片描述

ENTRYPOINT

作用

  • 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有其他传入值作为该命令的参数

说明:

  • 一个 Dockerfile 只有一个 ENTRYPOINT 指令,只有最后一个 ENTRYPOINT 指令生效

格式

# exec 格式
ENTRYPOINT ["executable", "param1", "param2"]

# shell 格式
ENTRYPOINT command param1 param2

使用示例

  • 新建dockerfile
FROM ubuntu
#  CMD 和 ENTRYPOINT 作为唯一入口,写多个,只有最后一个生效
# shell方式
ENTRYPOINT ping baidu.com
# exec方式
ENTRYPOINT [ "sh", "-c", "echo $HOME" ]
  • 制作镜像
docker build -t test --force-rm --no-cache .
  • 运行容器
docker run -it --rm test

在这里插入图片描述

CMD/ENTRYPOINT区别

  • CMD :指定这个容器启动的时候要运行的命令,会覆盖原命令,不可以追加命令
  • ENTRYPOINT :指定这个容器启动的时候要运行的命令,可以追加命令
CMD使用示例
  • dockerfile
FROM ubuntu
CMD ["ls","-a"]
  • 制作镜像
docker build -t test --force-rm --no-cache .
  • 运行容器
# 覆盖 ls -a; -l命令是不存在的,所以会报错
docker run -it --rm test -l

在这里插入图片描述

ENTRYPOINT使用示例
  • dockerfile
FROM ubuntu
ENTRYPOINT ["ls","-a"]
  • 制作镜像
docker build -t test --force-rm --no-cache .
  • 运行容器
# 会追加命令 相当于执行  ls  -a -l
docker run -it --rm test -l

在这里插入图片描述
`

<think>我们正在分析一个Dockerfile,其内容如下: FROM centos VOLUME ["volume1","volume2"] CMD echo "--end--" CMD /bin/bash 根据引用[1][2][4]中提供的Dockerfile示例,我们可以逐条解释每个指令的作用: 1. **`FROM centos`**: - 这是Dockerfile的起始指令,指定基础镜像为官方CentOS镜像(通常是latest标签)[^1][^4]。 - 后续指令将在这个基础镜像上添加修改。 2. **`VOLUME ["volume1","volume2"]`**: -指令创建两个匿名卷:`volume1`和`volume2`(容器内的路径)[^1]。 - 当容器运行时,如果没有通过`-v`选项显式挂载,Docker会自动创建匿名卷(在主机上的随机目录)挂载到这两个路径。 - 作用:避免容器内的重要数据因容器销毁而丢失(如数据库文件、日志等),同时避免向容器层写入大量数据(影响性能)[^4]。 3. **`CMD echo "--end--"`**: - `CMD`指令指定容器启动时的默认执行命令。这里尝试输出字符串`--end--`。 - 注意:Dockerfile中只能有一个`CMD`生效(若有多个,仅最后一个有效)。因此,这个指令会被后面的`CMD /bin/bash`覆盖[^1][^3]。 4. **`CMD /bin/bash`**: - 这是最后一个`CMD`指令,覆盖了前面的`echo "--end--"`。 - 容器启动后会执行`/bin/bash`,进入交互式shell环境。 ### 问题分析 - **指令覆盖问题**:由于存在两个`CMD`指令,只有最后一个`CMD /bin/bash`会生效。因此,容器启动时不会输出`--end--`。 - **匿名卷的使用**:虽然在Dockerfile中声明了卷,但实际运行时仍需注意: - 如果主机目录未显式挂载到`volume1`或`volume2`,则每次容器启动都会初始化这两个目录(使用基础镜像中的内容)。 - 显式挂载可避免数据丢失,例如:`docker run -v host_dir1:/volume1 -v host_dir2:/volume2 ...` ### 修正后的Dockerfile建议 若希望同时输出`--end--`并启动bash,可改为: ```dockerfile FROM centos VOLUME ["volume1","volume2"] CMD ["/bin/sh", "-c", "echo '--end--' && /bin/bash"] ``` 这样,容器启动时会先执行`echo '--end--'`,然后启动bash。 ### 构建与运行 1. 构建镜像: ```bash docker build -t mycentos:1.0 . ``` 2. 运行容器: ```bash docker run -it mycentos:1.0 ``` 输出: ``` --end-- [root@container_id /]# ``` --- ### §§相关问题§§ 1. Dockerfile中`VOLUME`指令与`docker run -v`参数有何联系与区别? 2. 如何在Dockerfile中设置多个命令而避免`CMD`覆盖问题? 3. 匿名卷和具名卷在数据持久化中各有什么优缺点? 4. 如何查看由`VOLUME`指令创建的匿名卷在主机上的实际存储路径? </think>### Dockerfile 分析:`FROM centos`, `VOLUME ["volume1","volume2"]`, `CMD echo "--end--"`, `CMD /bin/bash` #### 1. **基础指令解析** - **`FROM centos`** - 指定基础镜像为官方 CentOS 镜像(通常是 `centos:latest`)[^4] - 后续操作在此镜像基础上构建新镜像 - 若需特定版本,应明确标签如 `FROM centos:7` - **`VOLUME ["volume1","volume2"]`** - 声明匿名数据卷(容器内路径)[^1] - 功能: - 容器运行时自动挂载主机匿名卷到 `/volume1` 和 `/volume2` - 避免容器层写入大量数据(提高性能) - 实现数据持久化(容器删除后数据保留) - **`CMD` 指令问题** ```dockerfile CMD echo "--end--" CMD /bin/bash ``` - **严重错误**:多个 `CMD` 指令会导致只有最后一个生效 - 最终仅执行 `/bin/bash`,`echo "--end--"` 被覆盖 - 修正方案: ```dockerfile # 合并为单条CMD CMD ["/bin/sh", "-c", "echo '--end--' && /bin/bash"] # 或用ENTRYPOINT+CMD组合 ENTRYPOINT ["echo", "--end--"] CMD ["/bin/bash"] ``` #### 2. **构建与运行示例** 1. **正确 Dockerfile**: ```dockerfile FROM centos VOLUME ["volume1","volume2"] CMD ["/bin/sh", "-c", "echo '--end--' && /bin/bash"] ``` 2. **构建镜像**: ```bash docker build -t mycentos:1.0 . ``` 3. **运行容器**: ```bash docker run -it --name test mycentos:1.0 ``` - 输出: ``` --end-- [root@container-id /]# ``` - 验证卷挂载: ```bash docker inspect test | grep Mounts -A 15 ``` #### 3. **关键注意事项** 1. **卷的实际行为**: - `VOLUME` 声明的是匿名卷(主机路径随机生成) - 显式挂载需在运行时指定: ```bash docker run -v /host/path:/volume1 ... ``` 2. **多命令执行**: - 避免多个 `CMD`,改用: - `&&` 连接命令(需通过 shell 执行) - `ENTRYPOINT` 定义主进程 + `CMD` 传参 - 初始化脚本(复杂场景) 3. **镜像优化建议**: - 清理缓存:`RUN yum install ... && yum clean all` - 合并指令:减少镜像层数 - 明确标签:避免 `latest` 版本漂移 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱学习de测试小白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值