docker: minimal runtime image — UI in devDeps, distroless final, slim bundle
Docker / build (push) Failing after 16s
Docker / build (push) Failing after 16s
Made-with: Cursor
This commit is contained in:
+7
-7
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Сборка фронта (devDependencies только здесь)
|
||||
# Сборка фронта (все devDependencies + UI)
|
||||
FROM node:22-alpine AS build
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
@@ -11,7 +11,7 @@ COPY public ./public
|
||||
COPY src ./src
|
||||
RUN npm run build
|
||||
|
||||
# Production node_modules + server + dist
|
||||
# Только runtime-deps: express, cors, sql.js (+ транзитивные)
|
||||
FROM node:22-alpine AS prod
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
@@ -20,17 +20,17 @@ RUN --mount=type=cache,target=/root/.npm \
|
||||
COPY server ./server
|
||||
COPY --from=build /app/dist ./dist
|
||||
|
||||
# Слой приложения одним COPY в финальный образ (меньше слоёв в image)
|
||||
# Артефакты без package.json / lock — не нужны для node server/index.js
|
||||
FROM node:22-alpine AS bundle
|
||||
WORKDIR /out
|
||||
COPY --from=prod /app/node_modules ./node_modules
|
||||
COPY --from=prod /app/server ./server
|
||||
COPY --from=prod /app/dist ./dist
|
||||
COPY --from=prod /app/package.json ./package.json
|
||||
|
||||
FROM node:22-alpine
|
||||
# Минимальный runtime (см. https://github.com/GoogleContainerTools/distroless/blob/main/nodejs/README.md)
|
||||
FROM gcr.io/distroless/nodejs22-debian13:nonroot
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
COPY --from=bundle /out/ .
|
||||
COPY --from=bundle --chown=nonroot:nonroot /out/ .
|
||||
EXPOSE 3001
|
||||
CMD ["node", "server/index.js"]
|
||||
CMD ["server/index.js"]
|
||||
|
||||
Generated
+20
-6
@@ -8,26 +8,26 @@
|
||||
"name": "vps-tracker",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tabler/core": "^1.4.0",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"chart.js": "^4.5.1",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"sql.js": "^1.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@tabler/core": "^1.4.0",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"chart.js": "^4.5.1",
|
||||
"concurrently": "^9.1.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"vite": "^7.3.1"
|
||||
}
|
||||
},
|
||||
@@ -1018,12 +1018,14 @@
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
||||
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -1391,6 +1393,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.4.0.tgz",
|
||||
"integrity": "sha512-5BigzOlbOH9N0Is4u0rYNRCiwtnUXWO57K9zwuscygcicAa8UV9MGaS4zTgQsZEtZ9tsNANhN/YD8gCBGKYCiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
@@ -1408,6 +1411,7 @@
|
||||
"version": "3.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.40.0.tgz",
|
||||
"integrity": "sha512-V/Q4VgNPKubRTiLdmWjV/zscYcj5IIk+euicUtaVVqF6luSC9rDngYWgST5/yh3Mrg/mYUwRv1YVTk71Jp0twQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"version": "3.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.40.0.tgz",
|
||||
"integrity": "sha512-oO5+6QCnna4a//mYubx4euZfECtzQZFDGsDMIdzZUhbdyBCT+3bRVFBPueGIcemWld4Vb/0UQ39C/cmGfGylAg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tabler/icons": "3.40.0"
|
||||
@@ -1685,6 +1690,7 @@
|
||||
"version": "5.3.7",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz",
|
||||
"integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1835,6 +1841,7 @@
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz",
|
||||
"integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kurkle/color": "^0.3.0"
|
||||
@@ -1958,6 +1965,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
|
||||
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -3408,6 +3416,7 @@
|
||||
"version": "19.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -3417,6 +3426,7 @@
|
||||
"version": "19.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
||||
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
@@ -3439,6 +3449,7 @@
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz",
|
||||
"integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
@@ -3461,6 +3472,7 @@
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz",
|
||||
"integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-router": "7.13.1"
|
||||
@@ -3578,6 +3590,7 @@
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
@@ -3648,6 +3661,7 @@
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
|
||||
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
|
||||
+9
-9
@@ -11,26 +11,26 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tabler/core": "^1.4.0",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"chart.js": "^4.5.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"sql.js": "^1.14.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.1"
|
||||
"express": "^4.21.1",
|
||||
"sql.js": "^1.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@tabler/core": "^1.4.0",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"chart.js": "^4.5.1",
|
||||
"concurrently": "^9.1.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"concurrently": "^9.1.0",
|
||||
"globals": "^16.5.0",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"vite": "^7.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user