[{"data":1,"prerenderedAt":1355},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fdocker\u002Fusage\u002Fdocker-dockerfile":158,"\u002Fdocs\u002Fdocker\u002Fusage\u002Fdocker-dockerfile-description":1345},[4],{"title":5,"path":6,"stem":7,"children":8,"page":36},"Docs","\u002Fdocs","docs",[9,37,45,65,148],{"title":10,"description":11,"icon":12,"path":13,"stem":14,"children":15,"page":36},"Redis","Redis是一个开源的高性能键值存储数据库，它提供了多种数据结构来存储数据，如字符串、哈希、列表、集合、有序集合等。Redis将数据存储在内存中，以提供快速的读写访问速度，并且能够通过异步的方式将数据持久化到磁盘上。它支持复制、Lua脚本、事务处理、不同级别的持久化选项以及多种客户端语言的接口。Redis广泛用于缓存、消息队列、短时数据存储和高性能的应用场景中。","skill-icons:redis-light","\u002Fdocs\u002Fredis","docs\u002F1.redis",[16],{"title":17,"path":18,"stem":19,"children":20,"description":34,"icon":35},"install","\u002Fdocs\u002Fredis\u002Finstall","docs\u002F1.redis\u002F1.install\u002F1.index",[21,24,29],{"title":22,"path":18,"stem":19,"description":23},"Introduction","The powerful Git-based CMS designed specifically for Nuxt developers.",{"title":25,"path":26,"stem":27,"description":28},"Installation","\u002Fdocs\u002Fredis\u002Finstall\u002Finstallation","docs\u002F1.redis\u002F1.install\u002F2.installation","Get started with Nuxt Content v3 in your Nuxt application.",{"title":30,"path":31,"stem":32,"description":33},"Configuration","\u002Fdocs\u002Fredis\u002Finstall\u002Fconfiguration","docs\u002F1.redis\u002F1.install\u002F3.configuration","Nuxt Content is configured with sensible defaults.",null,"icon-park-outline:install",false,{"title":38,"path":39,"stem":40,"children":41,"description":43,"icon":44},"SpringBoot","\u002Fdocs\u002Fspringboot","docs\u002F2.springboot\u002F1.index",[42],{"title":22,"path":39,"stem":40,"description":23},"Spring Boot 是一个基于 Spring 框架的‌开箱即用型 Java 开发框架‌，由 Pivotal 团队于 2014 年推出，旨在彻底简化 Spring 应用的初始搭建、配置和部署流程。其核心理念是 ‌\"约定优于配置\"‌，通过自动化机制减少开发者的样板代码工作，显著提升效率。","simple-icons:springboot",{"title":46,"path":47,"stem":48,"children":49,"description":63,"icon":64},"Rocky Linux","\u002Fdocs\u002Frocky","docs\u002F3.rocky\u002F1.index",[50,53,58],{"title":51,"path":47,"stem":48,"description":52},"1 Rocky Linux 概述","Rocky Linux 是一个开源、免费的企业级 Linux 操作系统。它的核心目标是与 Red Hat Enterprise Linux (RHEL) 100% 完全兼容，可以看作是原本广受欢迎的 CentOS 的“替代者”和“精神继承者.",{"title":54,"path":55,"stem":56,"description":57},"2 VMware安装Rocky Linux","\u002Fdocs\u002Frocky\u002Finstall","docs\u002F3.rocky\u002F2.install","本文主要介绍了VMware Workstation 17.x 虚拟机如何快速安装Rocky Linux 10.x 版本的Linux操作系统。",{"title":59,"path":60,"stem":61,"description":62},"3 Rocky Linux 10安装Docker","\u002Fdocs\u002Frocky\u002Fdocker","docs\u002F3.rocky\u002F3.docker","在 Rocky Linux 10 上安装 Docker 的推荐方式是使用其官方仓库。下面是完整的安装步骤。","Rocky Linux 是一个开源、免费的企业级 Linux 操作系统。它的核心目标是与 Red Hat Enterprise Linux (RHEL) 100% 完全兼容，可以看作是原本广受欢迎的 CentOS 的“替代者”和“精神继承者”","logos:rocky-linux-icon",{"title":66,"description":67,"icon":68,"path":69,"stem":70,"children":71,"page":36},"Docker","Docker是一个开源的应用容器引擎，可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中，然后发布到Docker容器中运行，也可以实现虚拟化。","devicon:docker","\u002Fdocs\u002Fdocker","docs\u002F4.docker",[72,96,111,137],{"title":73,"path":74,"stem":75,"children":76,"description":34,"icon":95},"Docker 基础","\u002Fdocs\u002Fdocker\u002Fbasic","docs\u002F4.docker\u002F1.basic\u002F1.index",[77,80,85,90],{"title":78,"path":74,"stem":75,"description":79},"Docker基础概念","Docker是一个基于Go语言开发并遵从 Apache2.0 协议开源的应用容器引擎，可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中，然后发布到Docker环境中运行，容器彼此隔离，但可以通过特定的通道相互传递信息。保证了在任何环境下运行的应用程序具有相同的行为，这极大地减少了环境差异导致的“在我机器上可以运行”的问题。",{"title":81,"path":82,"stem":83,"description":84},"Docker核心架构","\u002Fdocs\u002Fdocker\u002Fbasic\u002Fdocker-architecture","docs\u002F4.docker\u002F1.basic\u002F2.docker-architecture","Docker 采用 C\u002FS 架构，客户端通过 REST API 将指令下达给常驻后台的守护进程（dockerd）；守护进程则依靠 Linux 内核的 Namespace 实现环境隔离、Cgroups 实现资源配额，并利用 UnionFS 的分层存储机制构建镜像和容器，从而在单台宿主机上实现了轻量级、高性能的应用沙箱。",{"title":86,"path":87,"stem":88,"description":89},"Docker镜像加速","\u002Fdocs\u002Fdocker\u002Fbasic\u002Fdocker-mirror-acceleration","docs\u002F4.docker\u002F1.basic\u002F3.docker-mirror-acceleration","Docker安装完成后默认的官方镜像仓库是[Docker Hub‌](https:\u002F\u002Fhub.docker.com\u002F){target=blank}，这是Docker官方维护的公共镜像注册中心。但对于国内Docker用户而言，在没有魔法的情况下是无法访问Docker Hub网站的，也无法从Docker Hub仓库拉取镜像。目前国内常用的2种方法：**Docker镜像加速源** 和 **配置Docker代理**。",{"title":91,"path":92,"stem":93,"description":94},"Docker Context","\u002Fdocs\u002Fdocker\u002Fbasic\u002Fdocker-context","docs\u002F4.docker\u002F1.basic\u002F4.docker-context","Docker Context 是 Docker 19.03 版本引入的一项功能，它为 Docker 客户端（CLI）提供了一套标准化的“连接配置”机制。通过 Context，你可以轻松地在本地开发环境、远程服务器、云服务等多个 Docker 环境之间快速切换，极大地提升了多环境管理的效率。","mdi:information-box-outline",{"title":97,"description":34,"icon":35,"path":98,"stem":99,"children":100,"page":36},"Docker 安装","\u002Fdocs\u002Fdocker\u002Finstall","docs\u002F4.docker\u002F2.install",[101,106],{"title":102,"path":103,"stem":104,"description":105},"CentOS安装Docker","\u002Fdocs\u002Fdocker\u002Finstall\u002Fcentos-docker-install","docs\u002F4.docker\u002F2.install\u002F1.centos-docker-install","在 CentOS 上安装 Docker，准确的说是安装 Docker Engine, 本文主要介绍如何在CentOS上安装Docker。",{"title":107,"path":108,"stem":109,"description":110},"Rocky安装Docker","\u002Fdocs\u002Fdocker\u002Finstall\u002Frocky-docker-install","docs\u002F4.docker\u002F2.install\u002F2.rocky-docker-install","在 Rocky Linux 10 上安装 Docker 和 Centos 安装 Docker 步骤基本类似的，推荐方式是使用其官方仓库。下面是完整的安装步骤。",{"title":112,"description":34,"icon":113,"path":114,"stem":115,"children":116,"page":36},"Docker 使用","fluent:data-usage-24-regular","\u002Fdocs\u002Fdocker\u002Fusage","docs\u002F4.docker\u002F3.usage",[117,122,127,132],{"title":118,"path":119,"stem":120,"description":121},"Docker持久化","\u002Fdocs\u002Fdocker\u002Fusage\u002Fdocker-persistence","docs\u002F4.docker\u002F3.usage\u002F1.docker-persistence","在 Docker 中，容器默认是无状态的，容器删除后内部数据会直接丢失，Docker 官方提供了三类核心数据持久化方案，分别适配不同的使用场景：卷（Volumes）、绑定挂载（Bind Mounts） 和 tmpfs 挂载。",{"title":123,"path":124,"stem":125,"description":126},"Docker容器自启动","\u002Fdocs\u002Fdocker\u002Fusage\u002Fcontainer-restart","docs\u002F4.docker\u002F3.usage\u002F2.container-restart","Docker容器自启动策略是指Docker服务运行期间，特定容器在退出、崩溃或宿主机重启后，容器是否自动重新运行。",{"title":128,"path":129,"stem":130,"description":131},"Docker Dockerfile","\u002Fdocs\u002Fdocker\u002Fusage\u002Fdocker-dockerfile","docs\u002F4.docker\u002F3.usage\u002F3.docker-dockerfile","本文旨在探讨Dockerfile的功能定位与指令体系，并在此基础上，给出基于Dockerfile实现自定义镜像构建的具体方法。",{"title":133,"path":134,"stem":135,"description":136},"连接远程Docker服务","\u002Fdocs\u002Fdocker\u002Fusage\u002Fconnect-remote-docker","docs\u002F4.docker\u002F3.usage\u002F4.connect-remote-docker","在日常开发或测试中，我们经常需要在本地开发环境中直接操作远程 Docker 服务——执行镜像构建、容器启停等命令，效果与直接在远程服务器上操作完全一致。这能极大提升调试与部署效率，同时避免频繁登录远程服务器的繁琐。",{"title":138,"description":34,"icon":139,"path":140,"stem":141,"children":142,"page":36},"Docker 参考手册","material-symbols-light:docs-outline","\u002Fdocs\u002Fdocker\u002Fresources","docs\u002F4.docker\u002F5.resources",[143],{"title":144,"path":145,"stem":146,"description":147},"Docker 命令大全","\u002Fdocs\u002Fdocker\u002Fresources\u002Fdocker-command","docs\u002F4.docker\u002F5.resources\u002F1.docker-command","下面介绍Docker常见的基础命令。",{"title":149,"path":150,"stem":151,"children":152,"description":156,"icon":157},"Linux","\u002Fdocs\u002Flinux","docs\u002F5.Linux\u002F1.index",[153],{"title":154,"path":150,"stem":151,"description":155},"1.dnf和yum区别","一句话概括：dnf 是 yum 的下一代升级版，你可以把 dnf 看作\"优化重构后的yum\"","Linux是免费开源、多用户多任务、高稳定性与安全性、支持多平台硬件的Unix操作系统。文档整理了Linux相关的命令和常见问题处理方法。","logos:linux-tux",{"id":159,"title":128,"body":160,"createDate":1335,"description":131,"extension":1336,"links":34,"meta":1337,"navigation":1338,"path":129,"readingTime":1339,"seo":1340,"sitemap":1341,"stem":130,"updateDate":1342,"wordCount":1343,"__hash__":1344},"docs\u002Fdocs\u002F4.docker\u002F3.usage\u002F3.docker-dockerfile.md",{"type":161,"value":162,"toc":1329},"minimark",[163,168,172,175,178,182,185,463,469,478,493,501,543,551,559,567,572,580,585,589,592,634,638,641,648,651,868,903,910,913,1077,1080,1188,1195,1198,1203,1229,1234,1264,1294,1299,1307,1314,1317,1325],[164,165,167],"h2",{"id":166},"_1-什么是-dockerfile","1. 什么是 Dockerfile",[169,170,171],"p",{},"Dockerfile 是一种用于构建 Docker 镜像的文本配置文件，其中逐条记录了构建所需的指令与参数。它通过明确的命令序列，指导 Docker 将应用程序及其运行环境逐层打包，最终生成一个可用的自定义镜像。可以说，Dockerfile 就是构建镜像的“蓝图”或“自动化脚本”。",[169,173,174],{},"Dockerfile 文件‌默认没有后缀名‌，纯文本文件，首字母大写，无扩展名，在执行 docker build 命令时，如果未指定文件名，Docker 会自动在当前目录下寻找名为 Dockerfile 的文件进行构建。",[169,176,177],{},"如果需要区分不同环境（如开发、测试、生产），可以使用带后缀或特定名称的文件，例如：Dockerfile.dev，使用非默认名称时，必须在构建命令中通过 -f 参数显式指定文件路径：docker build -f Dockerfile.dev -t my-app:dev .\n日常开发中，直接创建名为 ‌Dockerfile‌（无后缀）的文件是最标准、最通用的做法。",[164,179,181],{"id":180},"_2-dockerfile-指令详解表","2. Dockerfile 指令详解表",[169,183,184],{},"Dockerfile 中的指令虽然在文件中按顺序书写，但它们的‌执行时机‌和‌作用阶段‌有所不同。为了更清晰地理解，下表按照‌构建与运行时的逻辑执行顺序‌对 Dockerfile 的核心指令进行了汇总和排序：",[186,187,188,207],"table",{},[189,190,191],"thead",{},[192,193,194,198,201,204],"tr",{},[195,196,197],"th",{},"执行阶段",[195,199,200],{},"指令",[195,202,203],{},"具体含义与作用",[195,205,206],{},"使用示例",[208,209,210,225,238,251,265,278,291,305,318,335,349,363,383,397,413,433,447],"tbody",{},[192,211,212,216,219,222],{},[213,214,215],"td",{},"‌1. 基础定义‌",[213,217,218],{},"‌FROM‌",[213,220,221],{},"‌指定基础镜像‌。必须是 Dockerfile 的第一条有效指令。它定义了后续所有操作基于哪个操作系统或环境层进行。支持多阶段构建命名。",[213,223,224],{},"FROM python:3.9-slim AS builder",[192,226,227,229,232,235],{},[213,228],{},[213,230,231],{},"‌ARG‌",[213,233,234],{},"‌定义构建参数‌。仅在镜像‌构建期间‌有效的变量。可以通过 docker build --build-arg 传入值，用于动态控制构建过程（如版本号）。容器运行时不可见。",[213,236,237],{},"ARG VERSION=1.0 FROM python:${VERSION}",[192,239,240,242,245,248],{},[213,241],{},[213,243,244],{},"‌LABEL‌",[213,246,247],{},"‌添加元数据‌。以键值对形式为镜像添加描述信息（如作者、版本、描述），替代已废弃的 MAINTAINER。",[213,249,250],{},"LABEL maintainer=\"anyfork\" version=\"2.0\"",[192,252,253,256,259,262],{},[213,254,255],{},"‌2. 环境配置‌",[213,257,258],{},"‌ENV‌",[213,260,261],{},"‌设置环境变量‌。在‌构建期‌和‌运行期‌都有效。后续指令（如 RUN, COPY）可以使用这些变量，容器启动后应用也可以读取。",[213,263,264],{},"ENV APP_HOME=\u002FappENV DEBUG=true",[192,266,267,269,272,275],{},[213,268],{},[213,270,271],{},"‌WORKDIR‌",[213,273,274],{},"‌设置工作目录‌。为后续的 RUN, CMD, ENTRYPOINT, COPY, ADD 指令指定执行或操作的目录。若目录不存在则自动创建。",[213,276,277],{},"WORKDIR \u002Fusr\u002Fsrc\u002Fapp",[192,279,280,282,285,288],{},[213,281],{},[213,283,284],{},"‌USER‌",[213,286,287],{},"‌指定用户‌。指定后续 RUN, CMD, ENTRYPOINT 指令执行时的用户身份（UID\u002FGID）。出于安全考虑，建议最后切换为非 root 用户。",[213,289,290],{},"USER nobodyUSER 1001:1001",[192,292,293,296,299,302],{},[213,294,295],{},"‌3. 文件操作‌",[213,297,298],{},"‌COPY‌",[213,300,301],{},"‌复制文件‌。将宿主机文件或目录复制到镜像中。行为简单透明，是推荐的文件复制方式。",[213,303,304],{},"COPY requirements.txt .COPY . \u002Fusr\u002Fsrc\u002Fapp",[192,306,307,309,312,315],{},[213,308],{},[213,310,311],{},"‌ADD‌",[213,313,314],{},"‌高级复制‌。功能比 COPY 强，支持自动解压 tar 包或从 URL 下载文件。因行为复杂，官方建议优先使用 COPY。",[213,316,317],{},"ADD app.tar.gz \u002Fopt\u002F",[192,319,320,322,325,328],{},[213,321],{},[213,323,324],{},"‌VOLUME‌",[213,326,327],{},"‌创建挂载点‌。声明容器运行时的数据卷挂载点，用于持久化数据或共享数据，避免数据写入联合文件系统层。",[213,329,330,331],{},"VOLUME ",[332,333,334],"span",{},"\"\u002Fdata\"",[192,336,337,340,343,346],{},[213,338,339],{},"‌4. 构建执行‌",[213,341,342],{},"‌RUN‌",[213,344,345],{},"‌执行命令‌。在‌镜像构建阶段‌执行 Shell 命令。每执行一条 RUN 指令会生成一个新的镜像层。常用于安装依赖、编译代码。",[213,347,348],{},"RUN apt-get update && apt-get install -y curlRUN pip install -r requirements.txt",[192,350,351,354,357,360],{},[213,352,353],{},"‌5. 网络与端口‌",[213,355,356],{},"‌EXPOSE‌",[213,358,359],{},"‌声明端口‌。文档化地声明容器运行时监听的端口，并不实际映射端口。实际映射需在 docker run -p 中指定。",[213,361,362],{},"EXPOSE 80EXPOSE 8080\u002Ftcp",[192,364,365,368,371,374],{},[213,366,367],{},"‌6. 健康检查‌",[213,369,370],{},"‌HEALTHCHECK‌",[213,372,373],{},"‌健康检查‌。定义周期性检查容器健康状态的命令。如果检查失败，容器状态变为 unhealthy。",[213,375,376,377],{},"`HEALTHCHECK --interval=30s CMD curl -f ",[378,379,380],"a",{"href":380,"rel":381},"http:\u002F\u002Flocalhost\u002F",[382],"nofollow",[192,384,385,388,391,394],{},[213,386,387],{},"‌7. 启动配置‌",[213,389,390],{},"‌STOPSIGNAL‌",[213,392,393],{},"‌停止信号‌。设置发送给容器以使其退出的系统调用信号。默认是 SIGTERM。",[213,395,396],{},"STOPSIGNAL SIGQUIT",[192,398,399,401,404,407],{},[213,400],{},[213,402,403],{},"‌ENTRYPOINT‌",[213,405,406],{},"‌入口命令‌。配置容器启动时的主程序。它‌不会‌被 docker run 的参数直接覆盖，而是将参数追加其后。常与 CMD 配合使用。",[213,408,409,410],{},"ENTRYPOINT ",[332,411,412],{},"\"nginx\", \"-g\", \"daemon off;\"",[192,414,415,417,420,423],{},[213,416],{},[213,418,419],{},"‌CMD‌",[213,421,422],{},"‌默认启动命令‌。指定容器‌启动时‌默认执行的命令或参数。如果用户运行 docker run 时指定了其他命令，CMD 会被覆盖。每个 Dockerfile 只能有一个生效的 CMD。",[213,424,425,426,425,429,432],{},"CMD ",[332,427,428],{},"\"python\", \"app.py\"",[332,430,431],{},"\"--help\""," (作为 ENTRYPOINT 的参数)",[192,434,435,438,441,444],{},[213,436,437],{},"‌8. 触发器‌",[213,439,440],{},"‌ONBUILD‌",[213,442,443],{},"‌触发器‌。当当前镜像被用作‌其他‌ Dockerfile 的 FROM 基础镜像时，才会执行指定的指令。常用于构建通用基础镜像。",[213,445,446],{},"ONBUILD COPY . \u002FappONBUILD RUN npm install",[192,448,449,451,454,457],{},[213,450],{},[213,452,453],{},"‌SHELL‌",[213,455,456],{},"‌指定 Shell‌。覆盖默认的 Shell（Linux 默认为 \u002Fbin\u002Fsh -c，Windows 为 cmd \u002FS \u002FC）。影响后续 RUN, CMD, ENTRYPOINT 的执行方式。",[213,458,459,460],{},"SHELL ",[332,461,462],{},"\"\u002Fbin\u002Fbash\", \"-c\"",[169,464,465],{},[466,467,468],"strong",{},"关键逻辑说明",[470,471,472],"ol",{},[473,474,475],"li",{},[466,476,477],{},"执行顺序的逻辑性‌：",[479,480,481,487],"ul",{},[473,482,483,486],{},[466,484,485],{},"构建时执行‌："," FROM, ARG, ENV, WORKDIR, USER, COPY, ADD, RUN, VOLUME, EXPOSE, HEALTHCHECK, STOPSIGNAL, SHELL, ONBUILD 等指令主要在镜像构建阶段处理，确定镜像的静态结构。",[473,488,489,492],{},[466,490,491],{},"‌运行时执行‌："," ENTRYPOINT 和 CMD 定义的是容器‌启动时‌的行为。ENV 和 USER 既影响构建也影响运行。",[470,494,496],{"start":495},2,[473,497,498],{},[466,499,500],{},"‌CMD 与 ENTRYPOINT 的区别：",[479,502,503,509,515,529],{},[473,504,505,508],{},[466,506,507],{},"CMD",": CMD 在docker run 时运行，为启动的容器指定默认要运行的程序，程序运行结束，容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。",[473,510,511,514],{},[466,512,513],{},"ENTRYPOINT："," 类似于 CMD 指令，但其不会被 docker run 的命令行参数指定的指令所覆盖，而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项，将覆盖 ENTRYPOINT 指令指定的程序。如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令，仅最后一个生效。",[473,516,517,520,521,524,525,528],{},[466,518,519],{},"推荐使用组合："," ENTRYPOINT ",[332,522,523],{},"\"executable\""," + CMD ",[332,526,527],{},"\"param\"","，这样既固定了主程序，又提供了可覆盖的默认参数。一般是变参才会使用 CMD ，这里的 CMD 等于是在给 ENTRYPOINT 传参",[473,530,531,534,535,538,539,542],{},[466,532,533],{},"同时存在："," 如果同时存在 ENTRYPOINT 和 CMD，CMD 的内容会作为参数传递给 ENTRYPOINT。 例如：ENTRYPOINT ",[332,536,537],{},"\"echo\""," 和 CMD ",[332,540,541],{},"\"Hello\"","，容器启动时会执行 echo Hello。",[470,544,546],{"start":545},3,[473,547,548],{},[466,549,550],{},"ARG 与 ENV 的区别‌：",[479,552,553,556],{},[473,554,555],{},"ARG 仅在构建时有效，构建完成后消失，适合传递版本号、代理地址等构建期变量。",[473,557,558],{},"ENV 在构建和运行时都有效，适合设置应用运行所需的环境变量（如 NODE_ENV）。",[470,560,562],{"start":561},4,[473,563,564],{},[466,565,566],{},"ONBUILD 的特殊性‌：",[479,568,569],{},[473,570,571],{},"ONBUILD 指令在当前镜像构建时‌不执行‌，只有当别的 Dockerfile 使用 FROM \u003C当前镜像> 时，这些指令才会在子镜像的构建过程中触发。",[470,573,575],{"start":574},5,[473,576,577],{},[466,578,579],{},"COPY vs ADD‌：",[479,581,582],{},[473,583,584],{},"除非需要自动解压 tar 包或从 URL 下载，否则始终使用 COPY，因为它更透明且可预测。",[164,586,588],{"id":587},"_3-最佳实践与优化技巧","3. 最佳实践与优化技巧",[169,590,591],{},"优化 Dockerfile 以提高构建速度，核心在于‌最大化利用 Docker 的层缓存机制‌、‌减小构建上下文体积‌以及‌减少不必要的指令执行‌。以下是经过验证的最佳实践策略：",[470,593,594,600,606,612,618,628],{},[473,595,596,599],{},[466,597,598],{},"优化指令顺序以命中缓存‌："," Docker 会缓存每一层镜像。如果某一层及其之前的层没有变化，构建时会直接使用缓存。因此，应将变化频率低的内容（如安装依赖）放在前面，变化频率高的内容（如复制源代码）放在后面。\n示例：先 COPY package.json 并 RUN npm install，再 COPY . .。这样只要 package.json 不变，依赖安装层就会命中缓存。",[473,601,602,605],{},[466,603,604],{},"合并 RUN 指令以减少层数与开销‌："," 虽然现代 Docker 版本对层数限制较宽松，但合并 RUN 指令仍能减小镜像体积并提高构建效率。",[473,607,608,611],{},[466,609,610],{},"使用多阶段构建（Multi-stage Builds）‌："," 多阶段构建允许你在一个阶段编译应用，而在另一个阶段仅复制最终产物。这避免了将编译工具链、中间文件和源码带入最终镜像，显著减小镜像体积，从而加快推送和拉取速度。对于编译型语言（如 Go、Java、C++），可以在一个阶段编译代码，在另一个阶段仅复制二进制文件到最小的基础镜像（如 Alpine）中。这能显著减小最终镜像的体积。",[473,613,614,617],{},[466,615,616],{},"减小构建上下文（Build Context）："," 在项目根目录创建 .dockerignore 文件，排除不需要复制到镜像中的文件（如 .git、node_modules、日志文件等），以加快构建速度并减小镜像体积。",[473,619,620,623,624,627],{},[466,621,622],{},"优先使用 JSON 数组格式‌："," 对于 CMD 和 ENTRYPOINT，推荐使用 ",[332,625,626],{},"\"executable\", \"param1\""," 格式，避免 Shell 形式（\u002Fbin\u002Fsh -c）带来的信号处理问题和变量扩展意外。",[473,629,630,633],{},[466,631,632],{},"‌并行构建与 BuildKit‌："," 确保启用 Docker BuildKit（Docker 18.09+ 默认启用，可通过设置环境变量 DOCKER_BUILDKIT=1 强制开启）。BuildKit 支持并行构建独立层、更高效的缓存管理和更详细的构建输出，能显著提升构建性能。",[164,635,637],{"id":636},"_4-最佳实践优化示例","4. 最佳实践优化示例",[169,639,640],{},"基于前文关于 ‌Dockerfile 指令‌、‌构建优化技巧，以下是为 Nuxt 4（基于 Nitro 引擎）生成生产级 Docker 镜像的完整方案。Nuxt 4 通常采用 SSR（服务端渲染）或静态生成，下面分别介绍2种模式下Dockerfile配置。",[470,642,643],{},[473,644,645],{},[466,646,647],{},"SSR 模式‌下核心 Dockerfile 配置",[169,649,650],{},"为了实现最小化镜像体积和最快启动速度，推荐使用 ‌多阶段构建（Multi-stage Builds）‌。",[652,653,658],"pre",{"className":654,"code":655,"language":656,"meta":657,"style":657},"language-Dockerfile shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# 阶段 1：构建依赖与编译\nFROM node:20-alpine AS builder\n\n# 1. 安装 pnpm (Alpine 镜像默认不含 pnpm)\nRUN npm install -g pnpm\n\nWORKDIR \u002Fapp\n\n# 2. 复制 pnpm 锁文件和 package.json\nCOPY package.json pnpm-lock.yaml .\u002F\n\n# 3. 安装依赖 (使用 --frozen-lockfile 确保一致性)\nRUN pnpm install --frozen-lockfile\n\n# 4. 复制源代码并构建\nCOPY . .\nRUN pnpm run build\n\n# 阶段 2：生产运行环境\nFROM node:20-alpine AS runner\n\n# 1. 安装 pnpm (若启动脚本依赖 pnpm，否则可省略，但建议保留以保持一致性)\nRUN npm install -g pnpm\n\nWORKDIR \u002Fapp\n\nENV NODE_ENV=production\nENV HOST=0.0.0.0\nENV PORT=3000\n\n# 2. 仅复制构建产物\nCOPY --from=builder \u002Fapp\u002F.output .\u002F\n\nEXPOSE 3000\n\n# 3. 启动命令 (Nuxt\u002FNitro 标准入口)\nCMD [\"node\", \"server\u002Findex.mjs\"]\n","Dockerfile","",[659,660,661,668,673,679,684,689,694,700,705,711,717,722,728,734,739,745,751,757,762,768,774,779,785,790,795,800,805,811,817,823,828,834,840,845,851,856,862],"code",{"__ignoreMap":657},[332,662,665],{"class":663,"line":664},"line",1,[332,666,667],{},"# 阶段 1：构建依赖与编译\n",[332,669,670],{"class":663,"line":495},[332,671,672],{},"FROM node:20-alpine AS builder\n",[332,674,675],{"class":663,"line":545},[332,676,678],{"emptyLinePlaceholder":677},true,"\n",[332,680,681],{"class":663,"line":561},[332,682,683],{},"# 1. 安装 pnpm (Alpine 镜像默认不含 pnpm)\n",[332,685,686],{"class":663,"line":574},[332,687,688],{},"RUN npm install -g pnpm\n",[332,690,692],{"class":663,"line":691},6,[332,693,678],{"emptyLinePlaceholder":677},[332,695,697],{"class":663,"line":696},7,[332,698,699],{},"WORKDIR \u002Fapp\n",[332,701,703],{"class":663,"line":702},8,[332,704,678],{"emptyLinePlaceholder":677},[332,706,708],{"class":663,"line":707},9,[332,709,710],{},"# 2. 复制 pnpm 锁文件和 package.json\n",[332,712,714],{"class":663,"line":713},10,[332,715,716],{},"COPY package.json pnpm-lock.yaml .\u002F\n",[332,718,720],{"class":663,"line":719},11,[332,721,678],{"emptyLinePlaceholder":677},[332,723,725],{"class":663,"line":724},12,[332,726,727],{},"# 3. 安装依赖 (使用 --frozen-lockfile 确保一致性)\n",[332,729,731],{"class":663,"line":730},13,[332,732,733],{},"RUN pnpm install --frozen-lockfile\n",[332,735,737],{"class":663,"line":736},14,[332,738,678],{"emptyLinePlaceholder":677},[332,740,742],{"class":663,"line":741},15,[332,743,744],{},"# 4. 复制源代码并构建\n",[332,746,748],{"class":663,"line":747},16,[332,749,750],{},"COPY . .\n",[332,752,754],{"class":663,"line":753},17,[332,755,756],{},"RUN pnpm run build\n",[332,758,760],{"class":663,"line":759},18,[332,761,678],{"emptyLinePlaceholder":677},[332,763,765],{"class":663,"line":764},19,[332,766,767],{},"# 阶段 2：生产运行环境\n",[332,769,771],{"class":663,"line":770},20,[332,772,773],{},"FROM node:20-alpine AS runner\n",[332,775,777],{"class":663,"line":776},21,[332,778,678],{"emptyLinePlaceholder":677},[332,780,782],{"class":663,"line":781},22,[332,783,784],{},"# 1. 安装 pnpm (若启动脚本依赖 pnpm，否则可省略，但建议保留以保持一致性)\n",[332,786,788],{"class":663,"line":787},23,[332,789,688],{},[332,791,793],{"class":663,"line":792},24,[332,794,678],{"emptyLinePlaceholder":677},[332,796,798],{"class":663,"line":797},25,[332,799,699],{},[332,801,803],{"class":663,"line":802},26,[332,804,678],{"emptyLinePlaceholder":677},[332,806,808],{"class":663,"line":807},27,[332,809,810],{},"ENV NODE_ENV=production\n",[332,812,814],{"class":663,"line":813},28,[332,815,816],{},"ENV HOST=0.0.0.0\n",[332,818,820],{"class":663,"line":819},29,[332,821,822],{},"ENV PORT=3000\n",[332,824,826],{"class":663,"line":825},30,[332,827,678],{"emptyLinePlaceholder":677},[332,829,831],{"class":663,"line":830},31,[332,832,833],{},"# 2. 仅复制构建产物\n",[332,835,837],{"class":663,"line":836},32,[332,838,839],{},"COPY --from=builder \u002Fapp\u002F.output .\u002F\n",[332,841,843],{"class":663,"line":842},33,[332,844,678],{"emptyLinePlaceholder":677},[332,846,848],{"class":663,"line":847},34,[332,849,850],{},"EXPOSE 3000\n",[332,852,854],{"class":663,"line":853},35,[332,855,678],{"emptyLinePlaceholder":677},[332,857,859],{"class":663,"line":858},36,[332,860,861],{},"# 3. 启动命令 (Nuxt\u002FNitro 标准入口)\n",[332,863,865],{"class":663,"line":864},37,[332,866,867],{},"CMD [\"node\", \"server\u002Findex.mjs\"]\n",[869,870,871,877,882,890,895],"tip",{},[169,872,873,874],{},"注意：",[875,876],"br",{},[470,878,879],{},[473,880,881],{},"AS runner 的作用是给当前的构建阶段起一个别名（Name），以便在后续阶段中通过 COPY --from=runner 引用该阶段的文件。在多阶段构建中，你可以定义多个 FROM 指令，每个 FROM 开启一个新的构建阶段。通过 AS \u003C名称>，你可以：",[479,883,884,887],{},[473,885,886],{},"标识阶段‌：清晰区分“构建环境”和“运行环境”。",[473,888,889],{},"‌跨阶段复制‌：在最后一个阶段使用 COPY --from=builder 或 COPY --from=runner 从指定阶段提取文件。",[470,891,892],{"start":495},[473,893,894],{},"安装命令使用pnpm install --frozen-lockfile‌",[479,896,897,900],{},[473,898,899],{},"--frozen-lockfile：等同于 npm 的 ci 模式，确保严格依据锁文件安装，不更新锁文件，若锁文件与 package.json 不匹配则报错。这是 CI\u002FCD 和 Docker 构建的最佳实践。",[473,901,902],{},"pnpm 也有 pnpm ci 命令，其行为与 pnpm install --frozen-lockfile 类似，但显式使用 install --frozen-lockfile 更为通用且清晰。",[470,904,905],{"start":495},[473,906,907],{},[466,908,909],{},"SSG静态模式‌下核心 Dockerfile 配置",[169,911,912],{},"在静态模式下，Nuxt 会预渲染所有页面为 HTML\u002FCSS\u002FJS 文件，无需 Node.js 运行时服务器，因此推荐使用 ‌Nginx‌ 作为轻量级 Web 服务器托管这些静态资源。",[652,914,916],{"className":654,"code":915,"language":656,"meta":657,"style":657},"# 阶段 1：构建静态资源\nFROM node:20-alpine AS builder\n\nWORKDIR \u002Fapp\n\n# 1. 安装 pnpm (若使用 npm\u002Fyarn 请调整对应指令)\nRUN npm install -g pnpm\n\n# 2. 复制依赖文件并安装\nCOPY package.json pnpm-lock.yaml .\u002F\nRUN pnpm install --frozen-lockfile\n\n# 3. 复制源码并生成静态文件\nCOPY . .\n# Nuxt 静态生成命令通常为 generate，输出目录默认为 .output\u002Fpublic 或 dist\nRUN pnpm run generate\n\n# 阶段 2：Nginx 托管静态文件\nFROM nginx:alpine AS runner\n\n# 1. 移除 Nginx 默认配置\nRUN rm \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n\n# 2. 复制自定义 Nginx 配置 (可选，见下方说明)\nCOPY nginx.conf \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n\n# 3. 将构建产物复制到 Nginx 默认网页目录\n# 注意：Nuxt 4 (Nitro) 静态输出通常在 .output\u002Fpublic\nCOPY --from=builder \u002Fapp\u002F.output\u002Fpublic \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n\n# 4. 暴露 80 端口\nEXPOSE 80\n\n# 5. 启动 Nginx\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n\n",[659,917,918,923,927,931,935,939,944,948,952,957,961,965,969,974,978,983,988,992,997,1002,1006,1011,1016,1020,1025,1030,1034,1039,1044,1049,1053,1058,1063,1067,1072],{"__ignoreMap":657},[332,919,920],{"class":663,"line":664},[332,921,922],{},"# 阶段 1：构建静态资源\n",[332,924,925],{"class":663,"line":495},[332,926,672],{},[332,928,929],{"class":663,"line":545},[332,930,678],{"emptyLinePlaceholder":677},[332,932,933],{"class":663,"line":561},[332,934,699],{},[332,936,937],{"class":663,"line":574},[332,938,678],{"emptyLinePlaceholder":677},[332,940,941],{"class":663,"line":691},[332,942,943],{},"# 1. 安装 pnpm (若使用 npm\u002Fyarn 请调整对应指令)\n",[332,945,946],{"class":663,"line":696},[332,947,688],{},[332,949,950],{"class":663,"line":702},[332,951,678],{"emptyLinePlaceholder":677},[332,953,954],{"class":663,"line":707},[332,955,956],{},"# 2. 复制依赖文件并安装\n",[332,958,959],{"class":663,"line":713},[332,960,716],{},[332,962,963],{"class":663,"line":719},[332,964,733],{},[332,966,967],{"class":663,"line":724},[332,968,678],{"emptyLinePlaceholder":677},[332,970,971],{"class":663,"line":730},[332,972,973],{},"# 3. 复制源码并生成静态文件\n",[332,975,976],{"class":663,"line":736},[332,977,750],{},[332,979,980],{"class":663,"line":741},[332,981,982],{},"# Nuxt 静态生成命令通常为 generate，输出目录默认为 .output\u002Fpublic 或 dist\n",[332,984,985],{"class":663,"line":747},[332,986,987],{},"RUN pnpm run generate\n",[332,989,990],{"class":663,"line":753},[332,991,678],{"emptyLinePlaceholder":677},[332,993,994],{"class":663,"line":759},[332,995,996],{},"# 阶段 2：Nginx 托管静态文件\n",[332,998,999],{"class":663,"line":764},[332,1000,1001],{},"FROM nginx:alpine AS runner\n",[332,1003,1004],{"class":663,"line":770},[332,1005,678],{"emptyLinePlaceholder":677},[332,1007,1008],{"class":663,"line":776},[332,1009,1010],{},"# 1. 移除 Nginx 默认配置\n",[332,1012,1013],{"class":663,"line":781},[332,1014,1015],{},"RUN rm \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n",[332,1017,1018],{"class":663,"line":787},[332,1019,678],{"emptyLinePlaceholder":677},[332,1021,1022],{"class":663,"line":792},[332,1023,1024],{},"# 2. 复制自定义 Nginx 配置 (可选，见下方说明)\n",[332,1026,1027],{"class":663,"line":797},[332,1028,1029],{},"COPY nginx.conf \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n",[332,1031,1032],{"class":663,"line":802},[332,1033,678],{"emptyLinePlaceholder":677},[332,1035,1036],{"class":663,"line":807},[332,1037,1038],{},"# 3. 将构建产物复制到 Nginx 默认网页目录\n",[332,1040,1041],{"class":663,"line":813},[332,1042,1043],{},"# 注意：Nuxt 4 (Nitro) 静态输出通常在 .output\u002Fpublic\n",[332,1045,1046],{"class":663,"line":819},[332,1047,1048],{},"COPY --from=builder \u002Fapp\u002F.output\u002Fpublic \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n",[332,1050,1051],{"class":663,"line":825},[332,1052,678],{"emptyLinePlaceholder":677},[332,1054,1055],{"class":663,"line":830},[332,1056,1057],{},"# 4. 暴露 80 端口\n",[332,1059,1060],{"class":663,"line":836},[332,1061,1062],{},"EXPOSE 80\n",[332,1064,1065],{"class":663,"line":842},[332,1066,678],{"emptyLinePlaceholder":677},[332,1068,1069],{"class":663,"line":847},[332,1070,1071],{},"# 5. 启动 Nginx\n",[332,1073,1074],{"class":663,"line":853},[332,1075,1076],{},"CMD [\"nginx\", \"-g\", \"daemon off;\"]\n",[169,1078,1079],{},"配套 Nginx 配置 (nginx.conf)，为了确保 SPA（单页应用）或预渲染页面在刷新时不出现 404，建议添加以下 nginx.conf 文件到项目根目录：",[652,1081,1085],{"className":1082,"code":1083,"language":1084,"meta":657,"style":657},"language-conf shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","server {\n    listen 80;\n    server_name localhost;\n    root \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n    index index.html;\n\n    # 启用 Gzip 压缩\n    gzip on;\n    gzip_types text\u002Fplain text\u002Fcss application\u002Fjson application\u002Fjavascript text\u002Fxml application\u002Fxml application\u002Fxml+rss text\u002Fjavascript;\n\n    # 处理 SPA 路由回退：如果文件不存在，返回 index.html\n    location \u002F {\n        try_files $uri $uri\u002F \u002Findex.html;\n    }\n\n    # 缓存静态资源\n    location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ {\n        expires 1y;\n        add_header Cache-Control \"public, immutable\";\n    }\n}\n","conf",[659,1086,1087,1092,1097,1102,1107,1112,1116,1121,1126,1131,1135,1140,1145,1150,1155,1159,1164,1169,1174,1179,1183],{"__ignoreMap":657},[332,1088,1089],{"class":663,"line":664},[332,1090,1091],{},"server {\n",[332,1093,1094],{"class":663,"line":495},[332,1095,1096],{},"    listen 80;\n",[332,1098,1099],{"class":663,"line":545},[332,1100,1101],{},"    server_name localhost;\n",[332,1103,1104],{"class":663,"line":561},[332,1105,1106],{},"    root \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n",[332,1108,1109],{"class":663,"line":574},[332,1110,1111],{},"    index index.html;\n",[332,1113,1114],{"class":663,"line":691},[332,1115,678],{"emptyLinePlaceholder":677},[332,1117,1118],{"class":663,"line":696},[332,1119,1120],{},"    # 启用 Gzip 压缩\n",[332,1122,1123],{"class":663,"line":702},[332,1124,1125],{},"    gzip on;\n",[332,1127,1128],{"class":663,"line":707},[332,1129,1130],{},"    gzip_types text\u002Fplain text\u002Fcss application\u002Fjson application\u002Fjavascript text\u002Fxml application\u002Fxml application\u002Fxml+rss text\u002Fjavascript;\n",[332,1132,1133],{"class":663,"line":713},[332,1134,678],{"emptyLinePlaceholder":677},[332,1136,1137],{"class":663,"line":719},[332,1138,1139],{},"    # 处理 SPA 路由回退：如果文件不存在，返回 index.html\n",[332,1141,1142],{"class":663,"line":724},[332,1143,1144],{},"    location \u002F {\n",[332,1146,1147],{"class":663,"line":730},[332,1148,1149],{},"        try_files $uri $uri\u002F \u002Findex.html;\n",[332,1151,1152],{"class":663,"line":736},[332,1153,1154],{},"    }\n",[332,1156,1157],{"class":663,"line":741},[332,1158,678],{"emptyLinePlaceholder":677},[332,1160,1161],{"class":663,"line":747},[332,1162,1163],{},"    # 缓存静态资源\n",[332,1165,1166],{"class":663,"line":753},[332,1167,1168],{},"    location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ {\n",[332,1170,1171],{"class":663,"line":759},[332,1172,1173],{},"        expires 1y;\n",[332,1175,1176],{"class":663,"line":764},[332,1177,1178],{},"        add_header Cache-Control \"public, immutable\";\n",[332,1180,1181],{"class":663,"line":770},[332,1182,1154],{},[332,1184,1185],{"class":663,"line":776},[332,1186,1187],{},"}\n",[470,1189,1190],{"start":545},[473,1191,1192],{},[466,1193,1194],{},"构建与运行命令",[169,1196,1197],{},"在项目根目录执行以下命令：",[479,1199,1200],{},[473,1201,1202],{},"构建镜像‌：",[652,1204,1208],{"className":1205,"code":1206,"language":1207,"meta":657,"style":657},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","docker build -t nuxt4-app:latest .\n","bash",[659,1209,1210],{"__ignoreMap":657},[332,1211,1212,1216,1220,1223,1226],{"class":663,"line":664},[332,1213,1215],{"class":1214},"sBMFI","docker",[332,1217,1219],{"class":1218},"sfazB"," build",[332,1221,1222],{"class":1218}," -t",[332,1224,1225],{"class":1218}," nuxt4-app:latest",[332,1227,1228],{"class":1218}," .\n",[479,1230,1231],{},[473,1232,1233],{},"‌运行容器‌：",[652,1235,1237],{"className":1205,"code":1236,"language":1207,"meta":657,"style":657},"docker run -d -p 3000:3000 --name my-nuxt-app nuxt4-app:latest\n",[659,1238,1239],{"__ignoreMap":657},[332,1240,1241,1243,1246,1249,1252,1255,1258,1261],{"class":663,"line":664},[332,1242,1215],{"class":1214},[332,1244,1245],{"class":1218}," run",[332,1247,1248],{"class":1218}," -d",[332,1250,1251],{"class":1218}," -p",[332,1253,1254],{"class":1218}," 3000:3000",[332,1256,1257],{"class":1218}," --name",[332,1259,1260],{"class":1218}," my-nuxt-app",[332,1262,1263],{"class":1218}," nuxt4-app:latest\n",[869,1265,1266,1270,1275,1286],{},[169,1267,873,1268],{},[875,1269],{},[470,1271,1272],{},[473,1273,1274],{},"上面构建命令最后的点（.）代表当前目录‌，即 ‌Docker 构建上下文（Build Context）‌的路径。具体含义如下：",[479,1276,1277,1280,1283],{},[473,1278,1279],{},"指定上下文根目录‌： Docker 引擎在执行构建时，需要将客户端指定的目录及其子目录中的所有文件（受 .dockerignore 限制）发送给 Docker 守护进程。这个目录就是“构建上下文”。",[473,1281,1282],{},"相对路径引用‌：. 是 Linux\u002FUnix 系统中表示“当前工作目录”的标准符号。如果你在项目根目录下执行命令，. 就指代项目根目录。",[473,1284,1285],{},"Dockerfile 的默认查找位置‌：除非使用 -f 参数指定其他路径，否则 Docker 会默认在构建上下文（即 . 指向的目录）的根目录下寻找名为 Dockerfile 的文件。",[470,1287,1288,1291],{"start":495},[473,1289,1290],{},"精简上下文路径‌：避免使用根目录 \u002F 或包含大量无关文件（如日志、数据集）的目录作为构建上下文，否则会导致传输缓慢甚至构建失败。",[473,1292,1293],{},"‌强制使用 .dockerignore‌：Docker 会先将上下文所有文件发送给守护进程，再执行过滤。‌未被 COPY 的文件若未在 .dockerignore 中排除，仍会被传输‌，从而浪费带宽和内存。务必通过 .dockerignore 排除非必要文件，以提升构建效率。",[479,1295,1296],{},[473,1297,1298],{},"验证服务‌",[169,1300,1301,1302,1306],{},"访问 ",[378,1303,1304],{"href":1304,"rel":1305},"http:\u002F\u002Flocalhost:3000",[382]," 即可看到 Nuxt 应用。",[470,1308,1309],{"start":561},[473,1310,1311],{},[466,1312,1313],{},"注意事项",[169,1315,1316],{},"务必在项目根目录创建 .dockerignore，排除 node_modules、.git、.nuxt 等无关文件，加速构建上下文传输。",[652,1318,1323],{"className":1319,"code":1321,"language":1322,"meta":657},[1320],"language-text","node_modules\n.git\n.nuxt\n.output\ndist\n*.md\n.env\n","text",[659,1324,1321],{"__ignoreMap":657},[1326,1327,1328],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":657,"searchDepth":545,"depth":545,"links":1330},[1331,1332,1333,1334],{"id":166,"depth":495,"text":167},{"id":180,"depth":495,"text":181},{"id":587,"depth":495,"text":588},{"id":636,"depth":495,"text":637},"2026-07-22 12:06:00","md",{},{"title":128},17.8,{"title":128,"description":131},{"loc":129},"2026-07-24 11:23:00",3208,"Y1mmvRH9zIs0jUN69eEcqKrPbIrGjl_8I6eCGvRThx4",{"data":1346,"body":1347},{},{"type":1348,"children":1349},"root",[1350],{"type":1351,"tag":169,"props":1352,"children":1353},"element",{},[1354],{"type":1322,"value":131},1787625813022]