1. 概述

Docker 容器在启动时会执行一个应用或命令。这个命令通常来源于镜像的配置。此外,我们也可以在运行容器时通过命令行参数来指定或覆盖这个命令。通常,我们构建的镜像来自于公共仓库中的父镜像,作者可能已经定义了默认命令。定义默认命令的主要方式是通过 Dockerfile 中的 ENTRYPOINTCMD 指令。

本教程将简要介绍 ENTRYPOINTCMD 的作用,并演示如何在不同场景下覆盖它们。


2. CMDENTRYPOINT 指令

我们可以使用 CMDENTRYPOINT 来指定容器启动时执行的命令。它们可以单独使用,也可以配合使用。

2.1 ENTRYPOINT 指令

ENTRYPOINT 的作用是定义容器启动时执行的主程序。 它有两种写法:

  • exec 形式(推荐):
ENTRYPOINT ["echo", "Hello World of Docker"]
  • shell 形式:
ENTRYPOINT echo Hello World of Docker

虽然两种形式执行结果相同,但 shell 形式会在 /bin/sh -c 中执行,且无法通过 CMDdocker run 添加额外参数。

2.2 CMD 指令

CMD 有两个主要用途:

  • 定义容器默认执行命令(可被覆盖)
  • ENTRYPOINT 配合使用,提供默认参数

示例:

CMD ["echo","Hello World of Docker with CMD"]

或配合 ENTRYPOINT 使用:

ENTRYPOINT ["echo","-e"]
CMD ["Hello\tWorld"]

此时容器执行的完整命令是:echo -e Hello\tWorld


3. 使用 docker run 命令覆盖命令

docker run 提供了参数用于覆盖 Dockerfile 中的 CMDENTRYPOINT

3.1 构建一个示例 Dockerfile

我们创建一个简单的 Dockerfile:

FROM ubuntu:latest
ENTRYPOINT ["echo","-e"]
CMD ["Hello\tWorld"]

构建并运行容器:

$ sudo docker run -it example1
Hello   World

3.2 覆盖 CMD 内容

我们可以通过在 docker run 后面添加参数来覆盖 CMD

$ sudo docker run -it example1 "Hello\tWorld\tof Docker Run"
Hello   World   of Docker Run

✅ 这样无需重新构建镜像即可修改运行参数。


4. 通过继承父镜像覆盖 CMD

我们可以基于上一步构建的镜像 example1 创建新的 Dockerfile:

FROM example1:latest
CMD ["Hello World\tOverriding parent image"]

构建并运行新镜像:

$ sudo docker run -it example2
Hello World     Overriding parent image

✅ 父镜像中的 CMD 被成功覆盖。


5. 使用 Docker Compose 覆盖 CMD

Docker Compose 可以通过 command 字段覆盖镜像的默认命令。

创建 docker-compose.yaml 文件:

version: '2.2'
services:
  echoer:
    image: example1
    command: "Hello World, from docker-compose"

运行服务:

$ sudo docker-compose up
Creating network "example1_default" with the default driver
Creating example1_echoer_1 ... done
Attaching to example1_echoer_1
echoer_1  | Hello World, from docker-compose
example1_echoer_1 exited with code 0

CMD 被成功覆盖。


6. 使用 docker-compose run 覆盖 CMD

除了 docker-compose up,我们还可以使用 docker-compose run 命令覆盖命令:

$ sudo docker-compose run echoer "Hello World, CMD Overriden from docker-compose run"
Hello World, CMD Overriden from docker-compose run

✅ 效果等同于 docker run,适用于临时运行某个命令。


7. 小结

本文介绍了多种方式来覆盖 Docker 镜像的默认启动命令:

方式 覆盖目标 是否需要重建镜像
docker run 命令 CMD
继承父镜像 CMD
docker-compose.yaml CMD
docker-compose run CMD
--entrypoint 参数 ENTRYPOINT

✅ 推荐使用 ENTRYPOINT 固定程序入口,CMD 提供默认参数,便于灵活覆盖。

⚠️ 踩坑提醒:使用 shell 形式的 ENTRYPOINT 会导致参数无法传递,慎用!建议始终使用 exec 形式。


原始标题:Override CMD When Running a Docker Image