ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Refine 项目 Docker 化实战:深入理解 ENTRYPOINT 与 CMD 的正确用法

Refine 项目 Docker 化实战:深入理解 ENTRYPOINT 与 CMD 的正确用法 Refine 项目 Docker 化实战深入理解 ENTRYPOINT 与 CMD 的正确用法【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine导读本文以 Docker 的ENTRYPOINT指令为主线系统讲解 shell 形式与 exec 形式的区别、ENTRYPOINT与CMD的协作规则、运行期参数覆盖行为以及如何用自定义脚本作为容器入口。文中除给出可直接复制的 Dockerfile 示例外还结合当前 Refine 仓库中真实存在的两个 Dockerfileexamples/with-material-ui-vite/Dockerfile、examples/store/Dockerfile进行源码级印证帮助你在容器化 Refine 前后端应用时写出行为可预期、易于运维的镜像。什么是 Docker ENTRYPOINTENTRYPOINT是 Dockerfile 众多指令之一用于配置容器启动之后必然要执行的程序。无论你在docker run时是否追加了命令行参数ENTRYPOINT指定的可执行文件都会运行——例如在容器启动时立即执行某个脚本或二进制工具。ENTRYPOINT指令有两种写法Shell 形式ENTRYPOINT node app.jsExec 形式ENTRYPOINT [node, app.js]两种形式在运行期行为上有显著差异核心区别在于运行命令时指定的参数是否经由 shell 解析以及进程是否直接成为容器内的 PID 1。ENTRYPOINT 的两种形式是如何工作的Exec 形式参数追加、无 shell 解析当通过 exec 形式声明ENTRYPOINT时你在docker run命令行中追加的参数会被拼接到 exec 形式所有元素的末尾作为该可执行文件的额外参数运行。举例来说docker run时传入的参数会被 Docker 当作 ENTRYPOINT 的参数处理。借助这一机制你可以把容器本身变成一个可执行文件把复杂的命令行工具封装成一条 docker run 命令即可调用的形态。exec 形式只负责直接运行你提供的二进制和参数不经过任何 shell 解析——因此不会为你展开环境变量、不会做管道/重定向、也不会执行多条命令的串联。Shell 形式经 /bin/sh -c 执行Shell 形式的ENTRYPOINT会把指令作为参数交给/bin/sh -c执行从而获得完整的 shell 能力变量展开、管道、子命令、命令串联等。代价也很明确容器启动时你无法通过docker run的命令行参数覆盖或追加参数因为 ENTRYPOINT 命令是作为/bin/sh -c的子命令运行的可执行文件的进程 ID 不再是容器的 PID 1当执行docker stop发送 SIGTERM 等 Unix 信号时信号首先到达的是 shell 进程你的程序是否收到信号取决于 shell 是否转发这会影响优雅停机graceful shutdown。覆盖与优先级规则启动容器时可以通过--entrypoint标志覆盖 Dockerfile 中的ENTRYPOINT指令如果 Dockerfile 中出现了多条ENTRYPOINT指令只有最后一条生效官方推荐的最稳妥组合是ENTRYPOINT用 exec 形式、RUN用 shell 形式、CMD用 exec 形式。实战示例用 ENTRYPOINT 封装一个基准测试工具下面这个 Dockerfile 把 Apache 自带的基准测试工具abApacheBench封装进镜像并把目标网址 http://google.com/ 硬编码在ENTRYPOINT中FROM centos:7 MAINTAINER Devopscube RUN yum -y update \ yum -y install httpd-tools \ yum clean all ENTRYPOINT [ab , http://google.com/ ]构建镜像假设 Dockerfile 名为Dockerfile位于directoryName目录中镜像名通过-t指定为testentrypointdocker build directoryName –t testentrypoint在构建过程中Docker daemon 会读取ENTRYPOINT指令并将其登记为容器启动时的默认程序——无论启动时是否附加命令行输入它都会执行。构建完成后直接运行容器docker run testentrypoint可以看到ab基准测试工具在容器启动时立即开始执行。若你想把 URL 从docker run命令行传入而不是硬编码只需把ENTRYPOINT简化为只声明可执行文件FROM centos:7 MAINTAINER Devopscube RUN yum -y update \ yum -y install httpd-tools \ yum clean all ENTRYPOINT [ab]此时运行docker run testentrypoint http://bing.com/docker run中追加的http://bing.com/会被追加到 Dockerfile 的ENTRYPOINT指令之后等效于执行ab http://bing.com/——这就是把容器变成可执行命令行工具的典型手法。ENTRYPOINT 与 CMD 的区别在展开区别前先看两者的共同点两者都在docker run时执行两者都定义了容器运行时要执行的命令两者都可以通过docker run追加参数来覆盖若存在多条声明只有最后一条CMD与最后一条ENTRYPOINT生效。核心差异在于参数覆盖行为场景CMD 行为ENTRYPOINT 行为docker run未追加参数执行 Dockerfile 中的CMD执行 Dockerfile 中的ENTRYPOINTdocker run追加了参数Dockerfile 中的CMD被整体忽略改用命令行参数命令行参数被追加到ENTRYPOINT之后作为其参数一句话概括ENTRYPOINT 指定容器启动时要调用的可执行文件CMD 指定传递给 ENTRYPOINT 的默认参数当没有显式命令行参数时。用 CMD 改写基准测试示例把前面的ENTRYPOINT改成CMD后行为并不等价FROM centos:7 MAINTAINER Devopscube RUN yum -y update \ yum -y install httpd-tools \ yum clean all CMD [ab] [http://google.com/]此时如果执行docker run testentrypoint ab http://bing.com/Dockerfile 中的整条CMD都会被忽略docker run提供的ab http://bing.com/成为容器的启动命令。这正是CMD与ENTRYPOINT最直观的差异CMD 可被完全覆盖ENTRYPOINT 只会被追加参数。组合使用ENTRYPOINT 定程序、CMD 定默认参数把两者结合是最常见的生产实践FROM centos:7 MAINTAINER Devopscube RUN yum -y update \ yum -y install httpd-tools \ yum clean all ENTRYPOINT [ab] CMD [http://bing.com]当ENTRYPOINT与CMD同时出现在同一个 Dockerfile 中时CMD中的全部内容会被作为参数追加到ENTRYPOINT末尾直接运行docker run testentrypoint→ 执行ab http://bing.com运行docker run testentrypoint http://example.com/→ 执行ab http://example.com/CMD默认参数被覆盖。什么时候该用 ENTRYPOINT什么时候该用 CMD适合使用 ENTRYPOINT 的场景单用途single-purpose或多模式multi-mode镜像希望在容器启动时必然运行某个特定命令构建包装容器wrapper image把遗留程序封装进容器确保该程序每次都会运行想让容器本身表现得像一个可执行命令外部调用者只需追加参数。适合使用 CMD 的场景为容器提供默认启动程序或默认参数当用户在docker run中提供了显式输入参数时默认值自动让位。结论可以浓缩为两条需要必须始终执行的命令用ENTRYPOINT需要可被命令行参数替换的默认参数用CMD。用自定义脚本作为 ENTRYPOINT在实际工程中用 shell 脚本作为容器入口非常常见特别是需要做环境准备、等待依赖就绪、多步初始化等场景。步骤如下第 1 步创建脚本文件例如script.sh放在与 Dockerfile 相同的目录中脚本按约定接收两个输入参数。第 2 步编写 Dockerfile把脚本拷贝进容器、赋予可执行权限并用ENTRYPOINT声明它为入口同时用CMD提供默认参数FROM centos:7 MAINTAINER Devopscube RUN yum -y update \ yum -y install httpd \ yum clean all COPY ./script.sh / RUN chmod x /script.sh ENTRYPOINT [/script.sh] CMD [param1, param2]关键点说明COPY ./script.sh /将宿主机上的脚本放入容器根目录RUN chmod x /script.sh赋予执行权限否则 exec 形式无法直接启动它ENTRYPOINT [/script.sh]使用 exec 形式保证脚本以 PID 1 身份运行、能正确接收docker stop发出的信号CMD [param1, param2]提供默认参数可被docker run追加的参数覆盖。第 3 步构建镜像docker build -t imageName第 4 步运行容器使用默认参数docker run --name containerName -d imageName第 5 步通过docker run覆盖CMD中的默认参数docker run --name containerName -d imageName param1 param2这里docker run末尾的param1 param2会替换 Dockerfile 中CMD的默认参数并作为ENTRYPOINT即/script.sh的参数传入——默认参数被覆盖但入口脚本始终执行。仓库中的真实印证Refine 官方示例如何写容器启动命令Refine 仓库中可以直接找到两个符合上述最佳实践的 Dockerfile它们都采用exec 形式的 CMD与官方推荐的CMD 用 exec 形式完全一致。第一个是 examples/with-material-ui-vite/Dockerfile多阶段构建先安装依赖、构建静态产物最后在 runner 阶段全局安装serve静态文件服务器并以USER refine降权运行最后一行CMD [serve]由于该阶段只声明了CMD而没有ENTRYPOINTserve即作为容器的默认启动程序若运行时追加参数如docker run ... serve -l 8080则CMD被覆盖参数直接作用于serve。第二个是 examples/store/Dockerfile同样采用多阶段构建runner 阶段拷贝 Next.js 的 standalone 产物设置PORT 3000与HOSTNAME 0.0.0.0环境变量并以CMD [node, ./examples/store/server.js]启动 Node 服务进程。exec 形式保证了node进程直接成为容器 PID 1从而能正确接收来自docker stop的 SIGTERM 信号实现优雅退出——这正是 exec 形式相比 shell 形式在运维层面的优势所在。如果你把这类镜像部署到 Kubernetes可以参考仓库中的 documentation/k8s/refine-documentation/templates/deployment.yaml其中通过livenessProbe与readinessProbe对容器端口80进行 HTTP 探活。可以推断ENTRYPOINT/CMD的选择会直接影响探活语义——使用 exec 形式让服务进程成为 PID 1探针与信号处理都会更稳定可控。小结ENTRYPOINT定义容器启动后必然执行的可执行程序docker run追加的参数只会拼接到其后不会被忽略CMD定义默认参数或默认程序一旦docker run提供了显式命令/参数CMD就会被整体替换exec 形式让进程成为 PID 1信号处理正确、无 shell 干扰是ENTRYPOINT与CMD的首选写法shell 形式适合需要变量展开、管道、命令串联的初始化场景但要承担信号与 PID 语义的变化两者的黄金组合是ENTRYPOINT定程序CMD定默认参数外部调用方只需追加参数即可复用镜像以脚本作为入口时务必COPY脚本并chmod x再用 exec 形式声明ENTRYPOINTRefine 仓库自带的 examples/with-material-ui-vite/Dockerfile 与 examples/store/Dockerfile 即为 exec 形式 CMD 的落地范例可作为容器化 Refine 应用时的直接参考。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表