背景介绍
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,以其事件驱动、非阻塞 I/O 模型而闻名,广泛用于构建后端服务和前端应用。

Node.js 的特点使其非常适合容器化部署:

  • 轻量级运行时:相比传统后端语言,占用资源更少
  • 包管理系统:通过 npm 或 yarn 高效管理依赖
  • 异步非阻塞:天然适合高并发应用场景
  • 全栈开发:同一语言编写前后端,降低开发门槛

容器化 Node.js 应用需要特别关注以下几个方面:

  • 依赖管理:npm 或 yarn 的缓存和依赖安装策略
  • 环境隔离:开发、测试和生产环境的配置区分
  • 安全考量:避免使用 root 用户运行应用
  • 应用类型:区分不同应用类型的构建和部署方式

我们将遵循标准化的多阶段构建思想,为两种常见的 Node.js 应用场景创建优化、安全且高效的 Docker 镜像:

  1. 后端服务 (SSR 或 API): 通常基于 Express, Koa, NestJS 等框架,需要 Node.js 运行时环境
  2. 前端应用 (CSR 构建): 使用 React, Vue, Angular 等框架构建出静态文件,最终由 Nginx 托管

构建 Node 工具镜像

Node 工具环境负责提供完整的 Node.js 运行时和开发工具链,用于开发、测试和构建 Node.js 应用。

创建 Node 工具环境目录

首先创建 Node 工具镜像的目录:

mkdir -p common/tools/node
cd common/tools/node

Node 工具环境 Dockerfile 详解

FROM harbor.leops.local/common/os/debian:bullseyeARG NODE_VERSION=22.15.0 \YARN_VERSION=1.22.22LABEL org.opencontainers.image.authors="ops@leops.local"  \org.opencontainers.image.source="http://git.leops.local/ops/dockerfiles-base/common/tools/node/Dockerfile" \org.opencontainers.image.description="node ${NODE_VERSION} compiler environment."ENV NODE_VERSION=$NODE_VERSION \YARN_VERSION=$YARN_VERSION \NPM_REGISTRY="http://verdaccio.leops.local/" \YARN_REGISTRY="http://verdaccio.leops.local/"# install dependencies
RUN set -eux \&& apt-get update \&& apt-get install -y --no-install-recommends git python3 python3-pip gcc g++ make \&& apt-get clean \&& rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /tmp/* /var/tmp/* \&& truncate -s 0 /var/log/*log# install node
RUN set -eux \&& curl -fsSLO --compressed "http://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" \&& tar -zxf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 --no-same-owner \&& rm "node-v$NODE_VERSION-linux-x64.tar.gz" \&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \# smoke test&& node --version \&& npm --version \# set registry&& npm config set registry $NPM_REGISTRY \&& echo "disturl=${NPM_REGISTRY}/-/binary/node/" >> /root/.npmrc \&& echo "sass_binary_site=${NPM_REGISTRY}/-/binary/node-sass" >> /root/.npmrc \&& echo "canvas_binary_host_mirror=${NPM_REGISTRY}/-/binary/canvas" >> /root/.npmrc \&& echo "python_mirror=${NPM_REGISTRY}/-/binary/python/" >> /root/.npmrc \&& npm config list# install yarn
RUN set -eux \&& curl -fsSLO -k --compressed "https://github.com/yarnpkg/yarn/releases/download/v$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \&& mkdir -p /opt \&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \&& rm -fv yarn-v$YARN_VERSION.tar.gz \# smoke test&& yarn --version \# set registry&& yarn config set registry $YARN_REGISTRY \&& yarn config list

Dockerfile 关键点解析

该 Node.js 工具环境 Dockerfile 有以下几个重要特点:

  1. 基于 Debian:使用了标准化的 Debian bullseye 作为基础镜像
  2. 参数化版本:通过 ARG 参数化 Node.js 和 Yarn 版本,便于维护和更新
  3. 环境配置:设置了私有 NPM 和 Yarn 镜像源地址
  4. C/C++ 编译支持:安装了 gcc、g++、make 等编译工具,支持需要本地编译的模块
  5. 依赖管理:配置了预设的二进制下载镜像,加速 node-sass、canvas 等模块安装
  6. 验证安装:通过 smoke test 验证 Node.js 和 Yarn 安装成功
  7. 缓存清理:每个步骤后清理不必要的缓存文件,减小最终镜像体积

镜像构建脚本

使用以下脚本 (build.sh) 来构建和推送 Node 工具镜像:

#!/bin/bashset -e# 配置
REGISTRY="harbor.leops.local"
IMAGE_BASE_NAME="common/tools/node"
VERSION="22.15.0"# 声明镜像地址数组
declare -a IMAGE_PATHS
IMAGE_PATHS+=("${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION}""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%.*}""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%%.*}""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION}-debian11""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%.*}-debian11""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%%.*}-debian11"
)build_image() {echo "Building and pushing image:"for img in "${IMAGE_PATHS[@]}"; do echo -e " $img"; done# 构建镜像docker buildx build \$(for img in "${IMAGE_PATHS[@]}"; do echo -n "-t $img "; done) \--label "org.opencontainers.image.created=$(date --rfc-3339=seconds)" \--build-arg "NODE_VERSION=${VERSION}" \--add-host verdaccio.leops.local=192.168.77.140 \--provenance=false \--pull \--push \.echo "Build complete."
}# 参数处理
case "$1" in"list-tags")# 输出镜像标签列表printf '%s\n'"${IMAGE_PATHS[@]}";;*)build_image;;
esac

构建脚本通过灵活的标签生成逻辑,为镜像创建多个版本标签,包括:完整版本号(22.15.0)、主次版本号(22.15)、主版本号(22)以及带系统标识的组合标签,满足不同场景下的引用需求。

构建 Node.js 后端服务运行镜像 (SSR/API)

Node.js 后端服务运行镜像专注于安全、高效地运行 Node.js 服务端应用,采用 PM2 作为进程管理工具。这适用于 Express、Koa、NestJS、Nuxt 等需要服务端运行的框架。

为什么选择 PM2?

PM2 是一个强大的 Node.js 应用进程管理工具,提供以下关键特性:

  • 进程守护:自动重启崩溃的应用
  • 负载均衡:自动使用集群模式分发请求
  • 日志管理:集中管理应用日志
  • 监控功能:实时监控应用状态
  • 零停机重载:不中断服务的情况下更新应用

创建 PM2 工具环境目录

首先创建 PM2 工具镜像的目录:

mkdir -p common/runtime/pm2
cd common/runtime/pm2

PM2 工具环境 Dockerfile 详解

#syntax=harbor.leops.local/library/docker/dockerfile:1ARG NODE_VERSION=22FROM harbor.leops.local/common/tools/node:${NODE_VERSION}LABEL org.opencontainers.image.authors="ops@leops.local"  \org.opencontainers.image.source="http://git.leops.local/ops/dockerfiles-base/common/runtime/pm2/Dockerfile" \org.opencontainers.image.description="pm2 runtime environment."# install node
RUN set -eux \&& npm install -g pm2 \&& groupadd -r nonroot \&& useradd -r -m -g nonroot nonroot \&& mkdir -p /app/logs /home/nonroot/.pm2 \&& export PM2_HOME=/home/nonroot/.pm2  \&& chown nonroot:nonroot -R /app /home/nonrootUSER nonroot:nonrootCMD [ "pm2-runtime", "start", "ecosystem.config.js" ]

运行镜像重点解析

这个 PM2 运行镜像具有以下关键特点:

  1. 基于 Node 工具环境:继承我们前面创建的 Node.js 工具环境
  2. 全局安装 PM2:作为进程管理器确保应用稳定运行
  3. 非 root 用户:创建专用的 nonroot 用户,提高容器安全性
  4. 标准目录结构:预先创建 /app/logs 目录和 PM2 主目录
  5. 权限设置:确保应用目录归非 root 用户所有
  6. 默认启动命令:配置使用 PM2 运行时模式启动应用

镜像构建脚本

使用以下脚本 (build.sh) 来构建和推送 PM2 工具镜像:

#!/bin/bashset -e# 配置
REGISTRY="harbor.leops.local"
IMAGE_BASE_NAME="common/runtime/pm2"
VERSION="22"# 声明镜像地址数组
declare -a IMAGE_PATHS
IMAGE_PATHS+=("${REGISTRY}/${IMAGE_BASE_NAME}:node-${VERSION}""${REGISTRY}/${IMAGE_BASE_NAME}:node-${VERSION%.*}"
)build_image() {echo "Building and pushing image:"for img in "${IMAGE_PATHS[@]}"; do echo -e " $img"; done# 构建镜像docker buildx build \$(for img in "${IMAGE_PATHS[@]}"; do echo -n "-t $img "; done) \--label "org.opencontainers.image.created=$(date --rfc-3339=seconds)" \--add-host verdaccio.leops.local=192.168.77.140 \--build-arg "NODE_VERSION=${VERSION}" \--provenance=false \--pull \--push \.echo "Build complete."
}# 参数处理
case "$1" in"list-tags")# 输出镜像标签列表printf '%s\n'"${IMAGE_PATHS[@]}";;*)build_image;;
esac

构建前端应用静态文件镜像 (CSR)

对于前端应用(客户端渲染),最终产物是一堆静态的 HTML、CSS 和 JavaScript 文件,最适合使用 Nginx 这样的高性能 Web 服务器来托管。这适用于 React、Vue、Angular 等前端框架构建的静态应用。

为什么选择 Nginx?

Nginx 作为静态文件服务器有以下优势:

  • 高性能:能够高效处理并发连接
  • 低资源消耗:比动态服务占用更少的系统资源
  • 缓存能力:内置优秀的静态文件缓存机制
  • 简单配置:容易配置路由规则和重定向
  • 安全性:能够限制访问和隐藏敏感信息

创建 Nginx 工具环境目录

首先创建 Nginx 工具镜像的目录:

mkdir -p common/runtime/nginx-csr
cd common/runtime/nginx-csr

Nginx CSR Dockerfile 详解

#syntax=harbor.leops.local/library/docker/dockerfile:1FROM harbor.leops.local/common/os/debian:bullseyeARG NGINX_VERSION=1.26.3LABEL org.opencontainers.image.authors="ops@leops.local"  \org.opencontainers.image.source="http://git.leops.local/ops/dockerfiles-base/common/tools/node/Dockerfile" \org.opencontainers.image.description="nginx [engine x] is an HTTP and reverse proxy server"ENV NGINX_VERSION=$NGINX_VERSIONRUN echo 'deb [trusted=yes] https://nginx.org/packages/debian/ bullseye nginx' >> /etc/apt/sources.list.d/nginx.list \&& apt-get update \&& apt-get install -y nginx=${NGINX_VERSION}-1~bullseye \&& apt-get clean \&& chown www-data.www-data -R /var/cache/nginx \&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \&& ln -sf /dev/stdout /var/log/nginx/access.log \&& ln -sf /dev/stderr /var/log/nginx/error.logCOPY ./nginx.conf /etc/nginx/nginx.confEXPOSE80STOPSIGNAL SIGQUITCMD ["/usr/sbin/nginx", "-g", "daemon off;"]

Nginx 配置文件详解

nginx.conf 是一个针对前端单页应用(SPA)优化的配置文件,包含以下关键特性:

user  www-data;
worker_processes 1;
worker_rlimit_nofile 65535;error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;events {multi_accept on;worker_connections  65535;
}http {charset                utf-8;# MIMEinclude                mime.types;default_type           application/octet-stream;log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';log_format  main_json '{"@timestamp": "$time_iso8601", ''"remote_addr": "$remote_addr", ''"Remoteip": "$http_Remoteip", ''"http_x_forwarded_for": "$http_x_forwarded_for", ''"scheme": "$scheme", ''"request_method": "$request_method", ''"host": "$host", ''"request_uri": "$request_uri", ''"body_bytes_sent": $body_bytes_sent, ''"http_referer": "$http_referer", ''"http_user_agent": "$http_user_agent", ''"request_time": $request_time, ''"request_length": $request_length, ''"status": "$status"}';access_log  /var/log/nginx/access.log  main_json;sendfile               on;tcp_nopush             on;tcp_nodelay            on;log_not_found          off;types_hash_max_size    2048;types_hash_bucket_size 64;client_max_body_size 100M;client_header_buffer_size 32k;large_client_header_buffers 4 32k;underscores_in_headers on;# disable version in error messages and response headerserver_tokens off;proxy_hide_header X-Application-Context;# use etag with expireetag on;server {charset utf-8;listen 80 default_server;server_name _;index index.html;root /app/;# index.html fallbacklocation / {try_files $uri $uri/ $uri/index.html /index.html;}# no cache index.htmllocation ~* index.html {add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';add_header Pragma no-cache;if_modified_since off;etag off;}# favicon.icolocation = /favicon.ico {log_not_found off;access_log    off;}# robots.txtlocation = /robots.txt {log_not_found off;access_log    off;}# assets, medialocation ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {expires    7d;access_log off;}# svg, fontslocation ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {add_header Access-Control-Allow-Origin "*";expires    7d;access_log off;}# deny hidden filelocation ~ /\. {deny all;access_log off;}# gzipgzip            on;gzip_vary       on;gzip_proxied    any;gzip_comp_level 6;gzip_min_length 1k;gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;}
}

配置文件关键点解析

  1. SPA 路由支持:通过 try_files 指令将未匹配的路由重定向到 index.html,支持前端路由
  2. 缓存策略优化:
    • HTML 文件不缓存,确保内容始终最新
    • 静态资源(CSS、JS、图片等)设置 7 天缓存
    • 字体文件支持跨域请求和缓存
  3. 性能优化:
    • 开启 gzip 压缩减少传输数据量
    • 设置合理的 worker 连接数和文件处理参数
    • 使用 sendfile、tcp_nopush 等提升文件传输性能
  4. 安全设置:
    • 隐藏 Nginx 版本信息
    • 拒绝访问隐藏文件
    • 定制日志格式,便于安全审计和问题排查
  5. 日志优化:使用 JSON 格式记录访问日志,便于日志收集和分析系统处理

镜像构建脚本

使用以下脚本 (build.sh) 来构建和推送镜像:

#!/bin/bashset -e# 配置
REGISTRY="harbor.leops.local"
IMAGE_BASE_NAME="common/runtime/nginx-csr"
VERSION="1.26.3"# 声明镜像地址数组
declare -a IMAGE_PATHS
IMAGE_PATHS+=("${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION}""${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%.*}"
)build_image() {echo "Building and pushing image:"for img in "${IMAGE_PATHS[@]}"; do echo -e " $img"; done# 构建镜像docker buildx build \$(for img in "${IMAGE_PATHS[@]}"; do echo -n "-t $img "; done) \--label "org.opencontainers.image.created=$(date --rfc-3339=seconds)" \--build-arg "NGINX_VERSION=${VERSION}" \--provenance=false \--pull \--push \.echo "Build complete."
}# 参数处理
case "$1" in"list-tags")# 输出镜像标签列表printf '%s\n'"${IMAGE_PATHS[@]}";;*)build_image;;
esac

构建应用镜像 - 多阶段构建实战

在准备好基础工具镜像和运行环境镜像后,我们可以使用多阶段构建来创建最终的应用镜像。这种方法使我们能够在一个 Dockerfile 中同时处理构建和运行环境,大幅减小最终镜像体积。

Docker 多阶段构建简介:多阶段构建的核心优势:

  • 分离关注点:构建阶段专注于编译和打包,运行阶段专注于高效执行
  • 镜像体积优化:最终镜像只包含运行所需的文件,不含构建工具和中间产物
  • 构建缓存利用:合理的缓存策略可以大幅提升重复构建速度
  • 工作流简化:一个 Dockerfile 完成全部流程,无需额外脚本协调

准备示例应用 Vue

首先,我们获取一个简单的 Vue 应用示例:

git clone https://github.com/lework/ci-demo-vue.git
cd ci-demo-vue

Vue 应用 Dockerfile 详解

下面是一个 Vue 前端应用的多阶段构建 Dockerfile:

#
# ---- 编译环境 ----FROM harbor.leops.local/common/tools/node:22 AS builderARG APP_ENV=test \APP=undefine \GIT_BRANCH= \GIT_COMMIT_ID=ENV APP_ENV=$APP_ENV \APP=$APP \GIT_BRANCH=$GIT_BRANCH \GIT_COMMIT_ID=$GIT_COMMIT_IDWORKDIR /app_buildCOPY package.json package-lock.json ./RUN --mount=type=cache,id=${APP}-npm,target=/root/.npm \--mount=type=cache,id=${APP}-npm-modules,target=./node_modules \npm installCOPY ./ ./RUN --mount=type=cache,id=${APP}-npm,target=/root/.npm \--mount=type=cache,id=${APP}-npm-modules,target=./node_modules \npm run build:${APP_ENV}#
# ---- 运行环境 ----FROM harbor.leops.local/common/runtime/nginx-csr:1.26 AS runningARG APP_ENV=test \APP=undefine \GIT_BRANCH= \GIT_COMMIT_ID=ENV APP_ENV=$APP_ENV \APP=$APP \GIT_BRANCH=$GIT_BRANCH \GIT_COMMIT_ID=$GIT_COMMIT_IDWORKDIR /appCOPY --from=builder /app_build/dist /app/

Vue 多阶段构建关键点解析

这个 Dockerfile 分为两个明确的阶段:

  1. 编译阶段 (builder):
    • 使用我们创建的 Node.js 工具镜像
    • 接收构建参数(环境、应用名称、Git 信息等)
    • 先复制依赖描述文件安装依赖,最大化利用缓存
    • 使用 BuildKit 缓存加速 npm 依赖下载和安装
    • 执行对应环境的构建命令,生成静态文件
  2. 运行阶段 (running):
    • 使用我们准备的 Nginx CSR 运行环境镜像
    • 仅从编译阶段复制生成的 dist 目录中的静态文件
    • 继承环境变量用于版本跟踪和问题排查
    • 由 Nginx 提供高性能的静态文件服务

构建应用镜像

执行以下命令构建示例应用:

bash /data/dockerfiles-base/app-build/build-app.sh dev ci-demo-vue

构建完成后,会生成如下格式的镜像标签:
harbor.leops.local/dev/ci-demo-vue:master-256c81b-202504290330

准备示例应用 Nuxt

接下来,我们获取一个 Nuxt.js 应用示例,Nuxt 是基于 Vue.js 的服务端渲染框架:

git clone https://github.com/lework/ci-demo-nuxt.git
cd ci-demo-nuxt

Nuxt 应用 Dockerfile 详解

下面是一个 Nuxt SSR 应用的多阶段构建 Dockerfile:

#syntax=harbor.leops.local/library/docker/dockerfile:1
#
# ---- 编译环境 ----FROM harbor.leops.local/common/tools/node:22 AS builderARG APP_ENV=test \APP=undefine \GIT_BRANCH= \GIT_COMMIT_ID=ENV APP_ENV=$APP_ENV \APP=$APP \GIT_BRANCH=$GIT_BRANCH \GIT_COMMIT_ID=$GIT_COMMIT_IDWORKDIR /app_buildCOPY package.json package-lock.json ./RUN --mount=type=cache,id=${APP}-npm,target=/root/.npm \--mount=type=cache,id=${APP}-node_modules,target=/app_build/node_modules \npm installCOPY ./ ./RUN --mount=type=cache,id=${APP}-npm,target=/root/.npm \--mount=type=cache,id=${APP}-node_modules,target=/app_build/node_modules \npm run build:${APP_ENV}#
# ---- 运行环境 ----FROM harbor.leops.local/common/runtime/pm2:node-22 AS runningARG APP_ENV=test \APP=undefine \GIT_BRANCH= \GIT_COMMIT_ID=ENV APP_ENV=$APP_ENV \APP=$APP \GIT_BRANCH=$GIT_BRANCH \GIT_COMMIT_ID=$GIT_COMMIT_IDWORKDIR /appCOPY --from=builder --link --chown=999:999 /app_build/.output /appCMD ["bash", "-c", "exec pm2-runtime start ecosystem.config.js --json --env ${APP_ENV}"]

Nuxt 多阶段构建关键点解析

这个 Dockerfile 同样分为两个阶段,但与 Vue 应用不同:

  1. 编译阶段 (builder):
    • 同样使用 Node.js 工具环境,流程与 Vue 应用相似
    • 构建产物是 .output 目录,而非 dist 目录
  2. 运行阶段 (running):
    • 使用 PM2 运行环境镜像,而非 Nginx
    • 使用 --link 优化 BuildKit 缓存策略
    • 设置正确的文件所有权 (999:999 对应 nonroot 用户)
    • 使用 PM2 运行时启动服务端应用,支持环境变量切换

构建 Nuxt 应用镜像

执行以下命令构建示例应用:

bash /data/dockerfiles-base/app-build/build-app.sh dev ci-demo-nuxt

构建完成后,会生成如下格式的镜像标签:
harbor.leops.local/dev/ci-demo-nuxt:master-e13ed12-202504292036

版本控制

完成构建后,将所有文件提交到 Git 仓库进行版本控制:

git add -A .
git commit -m "feat: add node"
git push

运行应用容器

最终,我们可以运行构建好的应用容器,并验证其功能。

容器运行与验证

# 运行 Vue 前端容器
docker run --rm -d --name ci-demo-vue -p 18084:80 harbor.leops.local/dev/ci-demo-vue:master-256c81b-202504290330# 运行 Nuxt 服务端容器
docker run --rm -d --name ci-demo-nuxt -p 18085:3000 harbor.leops.local/dev/ci-demo-nuxt:master-e13ed12-202504292036# 访问应用
curl http://localhost:18084/
curl http://localhost:18085/# 查看日志
docker logs ci-demo-vue
docker logs ci-demo-nuxt# 停止容器
docker stop ci-demo-vue
docker stop ci-demo-nuxt

生产环境最佳实践

在生产环境中部署 Node.js 应用容器时,建议遵循以下最佳实践:

  1. 资源限制:使用 --memory 和 --cpus 设置容器资源上限,防止单个应用占用过多资源
  2. 健康检查:配置健康检查端点和容器健康检查,及时发现问题
  3. 日志管理:采用集中式日志收集系统,如 ELK 或 Loki,便于问题排查
  4. 环境变量:通过环境变量注入配置,实现同一镜像在不同环境运行
  5. 网络设置:仅暴露必要端口,使用内部网络进行服务间通信
  6. 容器编排:在生产环境中使用 Kubernetes 或 Docker Swarm 进行容器编排和管理

总结

通过本实践篇的学习,我们成功为两种典型的 Node.js 应用场景构建了优化、安全且高效的 Docker 镜像:

  1. 前端应用 (CSR):使用 Nginx 托管静态文件,具有高性能和优化的缓存策略

  2. 后端应用 (SSR/API):使用 PM2 管理 Node.js 进程,提供稳定可靠的服务
    我们的解决方案具有以下优势:

  3. 分层设计:工具环境和运行环境分离,职责明确

  4. 多阶段构建:大幅减小最终镜像体积,提高部署效率

  5. 安全性:使用非 root 用户运行应用,减少安全风险

  6. 缓存优化:合理利用 BuildKit 缓存加速重复构建

  7. 标准化:统一的构建流程和镜像结构,便于团队协作和自动化部署

这种方法不仅适用于示例中的 Vue 和 Nuxt 应用,也可以轻松扩展到其他 Node.js 框架和应用类型,为现代 Web 应用的容器化部署提供了可靠的参考方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913264.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913264.shtml
英文地址,请注明出处:http://en.pswp.cn/news/913264.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud 微服务(链路追踪与日志聚合)

📌 摘要 在微服务架构中,随着服务数量的增加和调用关系的复杂化,传统的日志记录方式已经无法满足对系统运行状态的全面掌控。如何快速定位异常请求、分析服务调用耗时、追踪完整链路成为运维和开发人员面临的核心挑战。 为此,Sp…

PADS交互式布局

PADS的交互式布局通过原理图与PCB的双向联动大幅提升设计效率。在原理图中框选电路模块时,PCB视图将自动高亮对应元件组并生成可移动簇,拖动时保持模块内部相对位置不变。布局过程中启用实时推挤功能(Placement Shoving)&#xff…

类图+案例+代码详解:软件设计模式----原型模式

5、原型模式 通过复制现有对象来创建新对象,避免从零开始构建,就像 “复印文件” 一样。 克隆的核心是复用现有对象状态 用 克隆熊猫 举例,秒懂原理 假设你有一只熊猫对象(属性:名字、年龄、毛色)&#…

Python-FAQ-__name__、__main__

1 需求 2 接口 3 示例 4 参考资料 在 Python 中,像 __name__ 这样的双下划线属性(也称为 "dunder" 属性,即 "double underscore" 的缩写)是 Python 的特殊属性或方法,它们为类、对象或模块提供了…

Adobe高阶技巧与设计师创意思维的进阶指南

作为一名在全球设计圈摸爬滚打了十年的职业设计师,我深知创意与技术的结合是点燃灵感的火花。凭借英国Parvis School of Economics and Music大学提供的Adobe正版教育订阅,我得以在设计之路上不断探索与突破。今天,我想以轻松实用的口吻&…

音视频会议服务搭建(设计方案-Go服务端API业务逻辑流程图)-04

前言 这一篇是 关于 Go服务端相关的音视频会议的接口API业务逻辑流程图肯定是不能完全复用到你的项目中去的,但是希望对你有一些参考性的帮助嗯,我也是在不断的进行完善和优化,并不是最终的结构,先定好大方向,然后不断…

C++ Qt Widget绘图画布缩放与平移:实现CAD级交互体验

在图形应用程序开发中,实现流畅的缩放和平移功能是创建专业级绘图工具的基础。本文将深入探讨如何在Qt Widget中实现CAD级别的交互体验,包括视图变换、坐标系统管理以及交互功能实现。核心概念:视图变换与坐标系统 在图形应用中,我…

Paimon 位图索引解析:高效等值查询的秘密( Bit-Sliced Index)

BitmapFileIndexBitmapFileIndex 这个类 是 Paimon 中一个非常重要的索引类型,它使用位图(Bitmap)来精确定位数据,尤其擅长处理低基数(low-cardinality)列的等值查询。BitmapFileIndex 实现了 FileIndexer …

S7-1200 CPU 与 S7-200 CPU S7通信(S7-1200 作为服务器

7-1200 CPU 与 S7-200 CPU S7通信(S7-1200 作为服务器) S7-1200 CPU 与 S7-200 CPU 之间的通信只能通过 S7 通信来实现,因为 S7-200 的以太网模块只支持S7 通信。当S7-200作为客户端,S7-1200作为服务器,需在客户端单边…

pyspark大规模数据加解密优化实践

假如有1亿行数据 方法1 spark udf解密 from pyspark.sql import SparkSession import pyspark.sql.functions as F from pyDes import * import binasciisparkSparkSession.builder.getOrCreate()def dec_fun(text):key triple_des(b"HHHHHHHHHHHHHHHHHHHHHHHH", CB…

华为云Flexus+DeepSeek征文|华为云ECS与CCE:从介绍到架构部署·仅需要此文足矣

前引:当今的企业面临着前所未有的技术挑战:如何构建既安全又高效、既灵活又可靠的云服务架构?如何有效整合人工智能技术,打造智能化的运维和服务体系?这些问题的答案,正在悄然改变着企业级IT基础设施的生态…

DAY 50 预训练模型+CBAM模块

浙大疏锦行https://blog.csdn.net/weixin_45655710 知识点回顾: resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 作业: 好好理解下resnet18的模型结构尝试对vgg16cbam进行微调策略 ResNet-18 结构核心思想 可以将R…

docker连接mysql

查看在运行的容器:docker ps -s 进入容器:docker exec -it 容器号或名 /bin/bash,如:docker exec -it c04c438ff177 /bin/bash 或docker exec -it mysql /bin/bash。 3. 登录mysql:mysql -uroot -p123456

javaweb第182节Linux概述~ 虚拟机连接不上FinalShell

问题描述 虚拟机无法连接到finalshell 报错 session.connect:java.net.socketexception:connection reset 或者 connection is closed by foreign host 解决 我经过一系列的排查,花费了一天的时间后,发现,只是因为,我将连接…

高压电缆护层安全的智能防线:TLKS-PLGD 监控设备深度解析

在现代电力系统庞大复杂的网络中,高压电缆护层是守护电力传输的 "隐形铠甲",其安全直接影响电网稳定。传统监测手段响应慢、精度低,难以满足安全运维需求。TLKS-PLGD 高压电缆护层环流监控设备应运而生,提供智能化解决方…

Element-Plus Cascader 级联选择器获取节点名称和value值方法

html 部分 <template><el-cascaderref"selectAeraRef":options"areas":disabled"disabled":props"optionProps"v-model"selectedOptions"filterablechange"handleChange"><template #default"…

STM32中实现shell控制台(命令解析实现)

文章目录一、核心设计思想二、命令系统实现详解&#xff08;含完整注释&#xff09;1. 示例命令函数实现2. 初始化命令系统3. 命令注册函数4. 命令查找函数5. 命令执行函数三、命令结构体&#xff08;cmd\_t&#xff09;四、运行效果示例五、小结在嵌入式系统的命令行控制台&am…

基于matlab的二连杆机械臂PD控制的仿真

基于matlab的二连杆机械臂PD控制的仿真。。。 chap3_5input.m , 1206 d2plant1.m , 1364 hs_err_pid2808.log , 15398 hs_err_pid4008.log , 15494 lx_plot.m , 885 PD_Control.mdl , 35066 tiaojie.m , 737 chap2_1ctrl.asv , 988 chap2_1ctrl.m , 905

TCP、HTTP/1.1 和HTTP/2 协议

TCP、HTTP/1.1 和 HTTP/2 是互联网通信中的核心协议&#xff0c;它们在网络分层中处于不同层级&#xff0c;各有特点且逐步演进。以下是它们的详细对比和关键特性&#xff1a;1. TCP&#xff08;传输控制协议&#xff09; 层级&#xff1a;传输层&#xff08;OSI第4层&#xff…

Java+Vue开发的进销存ERP系统,集采购、销售、库存管理,助力企业数字化运营

前言&#xff1a;在当今竞争激烈的商业环境中&#xff0c;企业对于高效管理商品流通、采购、销售、库存以及财务结算等核心业务流程的需求日益迫切。进销存ERP系统作为一种集成化的企业管理解决方案&#xff0c;能够整合企业资源&#xff0c;实现信息的实时共享与协同运作&…