實踐篇:14-構建 Node.js 應用程序鏡像

背景介紹
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;實現信息的實時共享與協同運作&…