From ba2a2988782d187b53ef3cc2d03a506985db4b16 Mon Sep 17 00:00:00 2001 From: DungTT Date: Thu, 28 May 2026 16:42:34 +0700 Subject: [PATCH] nhatrai . don't merge --- .dockerignore | 7 ++++++ .env | 9 +++++++ Dockerfile | 17 +++++++++++++ docker-build-site.mjs | 56 +++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 8 +++++++ nginx.conf | 38 +++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+) create mode 100644 .dockerignore create mode 100644 .env create mode 100644 Dockerfile create mode 100644 docker-build-site.mjs create mode 100644 docker-compose.yml create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..af5bee0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +* +!nginx.conf +!docker-build-site.mjs +!www.mewedding.vn/ +!www.mewedding.vn/** +!w.ladicdn.com/ +!w.ladicdn.com/** diff --git a/.env b/.env new file mode 100644 index 0000000..81d2036 --- /dev/null +++ b/.env @@ -0,0 +1,9 @@ +COMPOSE_PROJECT_NAME=wd-hn-nhatrai + +IMAGE_NAME=toiiiiday/minhhiep-thanhnhan +IMAGE_TAG=1.0.0 +CONTAINER_NAME=minhhiep-thanhnhan + +HOST_PORT=7060 +PUBLIC_DOMAIN=minhhiep-thanhnhan.weddinghappy.asia +SERVER_IP=172.20.235.176 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..de52e35 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM node:alpine AS site + +WORKDIR /src +COPY docker-build-site.mjs . +COPY www.mewedding.vn ./www.mewedding.vn +COPY w.ladicdn.com ./w.ladicdn.com +RUN node docker-build-site.mjs + +FROM nginx:alpine + +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=site /site/ /usr/share/nginx/html/ + +EXPOSE 7060 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget -qO- http://127.0.0.1:7060/ >/dev/null || exit 1 diff --git a/docker-build-site.mjs b/docker-build-site.mjs new file mode 100644 index 0000000..29d823c --- /dev/null +++ b/docker-build-site.mjs @@ -0,0 +1,56 @@ +import fs from "node:fs/promises"; +import path from "node:path"; + +const outDir = "/site"; +const indexPath = "www.mewedding.vn/index.html"; +const sourceDir = "www.mewedding.vn/source"; + +function decodeLocalAsset(rawUrl) { + let url = rawUrl.split("?")[0]; + url = url.replaceAll("\\ ", " "); + url = url.replace(/^\.\.\//, ""); + url = url.replace(/^\/+/, ""); + try { + return decodeURIComponent(url); + } catch { + return url; + } +} + +async function copyFilePreservingPath(relativePath) { + const source = path.resolve(relativePath); + const target = path.join(outDir, relativePath); + await fs.mkdir(path.dirname(target), { recursive: true }); + await fs.copyFile(source, target); +} + +const html = await fs.readFile(indexPath, "utf8"); +await fs.rm(outDir, { recursive: true, force: true }); +await copyFilePreservingPath(indexPath); +await fs.cp(sourceDir, path.join(outDir, sourceDir), { recursive: true }); + +const assetPattern = + /(?:url\(["']?|src=["']|href=["']|"(?:dC|dw)"\s*:\s*")((?:\.\.\/|\/)w\.ladicdn\.com\/[^"')]+)/g; +const assets = new Set(); + +for (const match of html.matchAll(assetPattern)) { + assets.add(decodeLocalAsset(match[1])); +} + +const missing = []; +for (const asset of assets) { + try { + await fs.access(asset); + await copyFilePreservingPath(asset); + } catch { + missing.push(asset); + } +} + +if (missing.length > 0) { + console.error("Missing local assets:"); + for (const asset of missing) console.error(`- ${asset}`); + process.exit(1); +} + +console.log(`Prepared static site with ${assets.size} local assets.`); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..447d59a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +services: + wedding-web: + build: . + image: ${IMAGE_NAME}:${IMAGE_TAG} + container_name: ${CONTAINER_NAME} + restart: unless-stopped + ports: + - "${HOST_PORT}:7060" diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..b593e6c --- /dev/null +++ b/nginx.conf @@ -0,0 +1,38 @@ +server { + listen 7060; + server_name _; + + root /usr/share/nginx/html; + index index.html; + charset utf-8; + + add_header X-Content-Type-Options "nosniff" always; + + location = / { + try_files /www.mewedding.vn/index.html =404; + } + + location = /index.html { + try_files /www.mewedding.vn/index.html =404; + } + + location /w.ladicdn.com/ { + try_files $uri =404; + expires 30d; + add_header Cache-Control "public, max-age=2592000, immutable"; + } + + location /www.mewedding.vn/source/ { + try_files $uri =404; + expires 30d; + add_header Cache-Control "public, max-age=2592000, immutable"; + } + + location /www.mewedding.vn/ { + try_files $uri $uri/ /www.mewedding.vn/index.html; + } + + location / { + try_files $uri $uri/ /www.mewedding.vn/index.html; + } +}