2016-11-26 02:02:43 +08:00
# # # CMD 容 器 启 动 命 令
` CMD ` 指 令 的 格 式 和 ` RUN ` 相 似 , 也 是 两 种 格 式 :
* ` shell ` 格 式 : ` CMD <命令> `
* ` exec ` 格 式 : ` CMD ["可执行文件", "参数1", "参数2"...] `
* 参 数 列 表 格 式 : ` CMD ["参数1", "参数2"...] ` 。 在 指 定 了 ` ENTRYPOINT ` 指 令 后 , 用 ` CMD ` 指 定 具 体 的 参 数 。
之 前 介 绍 容 器 的 时 候 曾 经 说 过 , Docker 不 是 虚 拟 机 , 容 器 就 是 进 程 。 既 然 是 进 程 , 那 么 在 启 动 容 器 的 时 候 , 需 要 指 定 所 运 行 的 程 序 及 参 数 。 ` CMD ` 指 令 就 是 用 于 指 定 默 认 的 容 器 主 进 程 的 启 动 命 令 的 。
在 运 行 时 可 以 指 定 新 的 命 令 来 替 代 镜 像 设 置 中 的 这 个 默 认 命 令 , 比 如 , ` ubuntu ` 镜 像 默 认 的 ` CMD ` 是 ` /bin/bash ` , 如 果 我 们 直 接 ` docker run -it ubuntu ` 的 话 , 会 直 接 进 入 ` bash ` 。 我 们 也 可 以 在 运 行 时 指 定 运 行 别 的 命 令 , 如 ` docker run -it ubuntu cat /etc/os-release ` 。 这 就 是 用 ` cat /etc/os-release ` 命 令 替 换 了 默 认 的 ` /bin/bash ` 命 令 了 , 输 出 了 系 统 版 本 信 息 。
在 指 令 格 式 上 , 一 般 推 荐 使 用 ` exec ` 格 式 , 这 类 格 式 在 解 析 时 会 被 解 析 为 JSON 数 组 , 因 此 一 定 要 使 用 双 引 号 ` " ` , 而 不 要 使 用 单 引 号 。
如 果 使 用 ` shell ` 格 式 的 话 , 实 际 的 命 令 会 被 包 装 为 ` sh -c ` 的 参 数 的 形 式 进 行 执 行 。 比 如 :
2019-10-29 14:31:45 +08:00
` ` ` docker
2016-11-26 02:02:43 +08:00
CMD echo $ HOME
` ` `
在 实 际 执 行 中 , 会 将 其 变 更 为 :
2019-10-29 14:31:45 +08:00
` ` ` docker
2016-11-26 02:02:43 +08:00
CMD [ "sh" , "-c" , "echo $HOME" ]
` ` `
这 就 是 为 什 么 我 们 可 以 使 用 环 境 变 量 的 原 因 , 因 为 这 些 环 境 变 量 会 被 shell 进 行 解 析 处 理 。
提 到 ` CMD ` 就 不 得 不 提 容 器 中 应 用 在 前 台 执 行 和 后 台 执 行 的 问 题 。 这 是 初 学 者 常 出 现 的 一 个 混 淆 。
2019-03-08 12:21:07 +08:00
Docker 不 是 虚 拟 机 , 容 器 中 的 应 用 都 应 该 以 前 台 执 行 , 而 不 是 像 虚 拟 机 、 物 理 机 里 面 那 样 , 用 ` systemd ` 去 启 动 后 台 服 务 , 容 器 内 没 有 后 台 服 务 的 概 念 。
2016-11-26 02:02:43 +08:00
一 些 初 学 者 将 ` CMD ` 写 为 :
2019-10-29 14:31:45 +08:00
` ` ` docker
2016-11-26 02:02:43 +08:00
CMD service nginx start
` ` `
然 后 发 现 容 器 执 行 后 就 立 即 退 出 了 。 甚 至 在 容 器 内 去 使 用 ` systemctl ` 命 令 结 果 却 发 现 根 本 执 行 不 了 。 这 就 是 因 为 没 有 搞 明 白 前 台 、 后 台 的 概 念 , 没 有 区 分 容 器 和 虚 拟 机 的 差 异 , 依 旧 在 以 传 统 虚 拟 机 的 角 度 去 理 解 容 器 。
对 于 容 器 而 言 , 其 启 动 程 序 就 是 容 器 应 用 进 程 , 容 器 就 是 为 了 主 进 程 而 存 在 的 , 主 进 程 退 出 , 容 器 就 失 去 了 存 在 的 意 义 , 从 而 退 出 , 其 它 辅 助 进 程 不 是 它 需 要 关 心 的 东 西 。
而 使 用 ` service nginx start ` 命 令 , 则 是 希 望 upstart 来 以 后 台 守 护 进 程 形 式 启 动 ` nginx ` 服 务 。 而 刚 才 说 了 ` CMD service nginx start ` 会 被 理 解 为 ` CMD [ "sh", "-c", "service nginx start"] ` , 因 此 主 进 程 实 际 上 是 ` sh ` 。 那 么 当 ` service nginx start ` 命 令 结 束 后 , ` sh ` 也 就 结 束 了 , ` sh ` 作 为 主 进 程 退 出 了 , 自 然 就 会 令 容 器 退 出 。
正 确 的 做 法 是 直 接 执 行 ` nginx ` 可 执 行 文 件 , 并 且 要 求 以 前 台 形 式 运 行 。 比 如 :
2019-10-29 14:31:45 +08:00
` ` ` docker
2017-01-13 14:21:35 +08:00
CMD [ "nginx" , "-g" , "daemon off;" ]
2016-11-26 02:02:43 +08:00
` ` `