Refactor Dockerfiles and enhance Next.js configuration for improved build and security
- Updated Dockerfiles for BFF and Portal to optimize dependency installation and build processes, focusing on specific package filters. - Enhanced Next.js configuration to improve security headers and Content Security Policy for development environments. - Adjusted Docker Compose files to support dynamic image tagging for better version control. - Cleaned up deployment scripts to include environment variable management for image tagging.
This commit is contained in:
parent
bc5c7c9bd4
commit
ce7c7773cd
@ -24,15 +24,16 @@ RUN apk add --no-cache python3 make g++ openssl libc6-compat \
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy manifests first for dependency caching
|
# Copy manifests first for dependency caching (all workspace packages)
|
||||||
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||||
COPY packages/domain/package.json ./packages/domain/
|
COPY packages/domain/package.json ./packages/domain/package.json
|
||||||
COPY apps/bff/package.json ./apps/bff/
|
COPY apps/bff/package.json ./apps/bff/package.json
|
||||||
|
COPY apps/portal/package.json ./apps/portal/package.json
|
||||||
|
|
||||||
# Install all dependencies with cache mount (separate layer for better caching)
|
# Install only the packages needed for the BFF (domain + bff)
|
||||||
ENV HUSKY=0
|
ENV HUSKY=0
|
||||||
RUN --mount=type=cache,id=pnpm-bff,target=/root/.local/share/pnpm/store \
|
RUN --mount=type=cache,id=pnpm-bff,target=/root/.local/share/pnpm/store \
|
||||||
pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile --filter @customer-portal/domain... --filter @customer-portal/bff...
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Stage 2: Builder
|
# Stage 2: Builder
|
||||||
@ -47,7 +48,9 @@ COPY packages/domain/ ./packages/domain/
|
|||||||
COPY apps/bff/ ./apps/bff/
|
COPY apps/bff/ ./apps/bff/
|
||||||
|
|
||||||
# Build: domain → Prisma generate → BFF (single RUN for better layer efficiency)
|
# Build: domain → Prisma generate → BFF (single RUN for better layer efficiency)
|
||||||
RUN pnpm --filter @customer-portal/domain build \
|
# Clean tsbuildinfo to force fresh emit; checked-in files can skip output otherwise
|
||||||
|
RUN rm -f apps/bff/tsconfig*.tsbuildinfo \
|
||||||
|
&& pnpm --filter @customer-portal/domain build \
|
||||||
&& pnpm --filter @customer-portal/bff exec prisma generate \
|
&& pnpm --filter @customer-portal/bff exec prisma generate \
|
||||||
&& pnpm --filter @customer-portal/bff build
|
&& pnpm --filter @customer-portal/bff build
|
||||||
|
|
||||||
@ -84,8 +87,10 @@ ENV PRISMA_SCHEMA_PATH=/app/prisma/schema.prisma
|
|||||||
COPY --from=builder --chown=nestjs:nodejs /app/deploy ./
|
COPY --from=builder --chown=nestjs:nodejs /app/deploy ./
|
||||||
|
|
||||||
# Regenerate Prisma client for production paths and cleanup
|
# Regenerate Prisma client for production paths and cleanup
|
||||||
RUN rm -rf node_modules/.prisma \
|
RUN npm install -g prisma@${PRISMA_VERSION} \
|
||||||
&& npx --yes prisma@${PRISMA_VERSION} generate --schema=${PRISMA_SCHEMA_PATH} \
|
&& rm -rf node_modules/.prisma \
|
||||||
|
&& prisma generate --schema=${PRISMA_SCHEMA_PATH} \
|
||||||
|
&& mkdir -p /app/node_modules/.prisma \
|
||||||
# Create symlink for backward compatibility with any hardcoded paths
|
# Create symlink for backward compatibility with any hardcoded paths
|
||||||
&& mkdir -p /app/apps/bff/prisma \
|
&& mkdir -p /app/apps/bff/prisma \
|
||||||
&& ln -sf /app/prisma/schema.prisma /app/apps/bff/prisma/schema.prisma \
|
&& ln -sf /app/prisma/schema.prisma /app/apps/bff/prisma/schema.prisma \
|
||||||
|
|||||||
@ -23,15 +23,16 @@ RUN apk add --no-cache libc6-compat \
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy manifests first for dependency caching
|
# Copy manifests first for dependency caching (all workspace packages)
|
||||||
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||||
COPY packages/domain/package.json ./packages/domain/
|
COPY packages/domain/package.json ./packages/domain/package.json
|
||||||
COPY apps/portal/package.json ./apps/portal/
|
COPY apps/portal/package.json ./apps/portal/package.json
|
||||||
|
COPY apps/bff/package.json ./apps/bff/package.json
|
||||||
|
|
||||||
# Install dependencies with cache mount (unique id per app for better caching)
|
# Install only the packages needed for the portal (domain + portal)
|
||||||
ENV HUSKY=0
|
ENV HUSKY=0
|
||||||
RUN --mount=type=cache,id=pnpm-portal,target=/root/.local/share/pnpm/store \
|
RUN --mount=type=cache,id=pnpm-portal,target=/root/.local/share/pnpm/store \
|
||||||
pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile --filter @customer-portal/domain... --filter @customer-portal/portal...
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Stage 2: Builder
|
# Stage 2: Builder
|
||||||
|
|||||||
@ -47,11 +47,37 @@ const nextConfig = {
|
|||||||
|
|
||||||
async headers() {
|
async headers() {
|
||||||
const isDev = process.env.NODE_ENV === "development";
|
const isDev = process.env.NODE_ENV === "development";
|
||||||
const connectSources = ["'self'", "https:"];
|
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
connectSources.push("http://localhost:*");
|
const devConnectSources = ["'self'", "https:", "http://localhost:*", "ws://localhost:*"];
|
||||||
|
const devScriptSrc = ["'self'", "'unsafe-inline'", "'unsafe-eval'", "blob:"].join(" ");
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: "/(.*)",
|
||||||
|
headers: [
|
||||||
|
{ key: "X-Frame-Options", value: "DENY" },
|
||||||
|
{ key: "X-Content-Type-Options", value: "nosniff" },
|
||||||
|
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
|
||||||
|
{ key: "X-XSS-Protection", value: "1; mode=block" },
|
||||||
|
{
|
||||||
|
key: "Content-Security-Policy",
|
||||||
|
value: [
|
||||||
|
"default-src 'self'",
|
||||||
|
`script-src ${devScriptSrc}`,
|
||||||
|
"style-src 'self' 'unsafe-inline'",
|
||||||
|
"img-src 'self' data: https:",
|
||||||
|
"font-src 'self' data:",
|
||||||
|
`connect-src ${devConnectSources.join(" ")}`,
|
||||||
|
"frame-ancestors 'none'",
|
||||||
|
].join("; "),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const connectSources = ["'self'", "https:"];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: "/(.*)",
|
source: "/(.*)",
|
||||||
|
|||||||
@ -10,7 +10,7 @@ services:
|
|||||||
# Frontend (Next.js)
|
# Frontend (Next.js)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
frontend:
|
frontend:
|
||||||
image: ${FRONTEND_IMAGE:-portal-frontend:latest}
|
image: ${FRONTEND_IMAGE:-portal-frontend}:${IMAGE_TAG:-latest}
|
||||||
container_name: portal-frontend
|
container_name: portal-frontend
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:${FRONTEND_PORT:-3000}:3000"
|
- "127.0.0.1:${FRONTEND_PORT:-3000}:3000"
|
||||||
@ -35,7 +35,7 @@ services:
|
|||||||
# Backend (NestJS BFF)
|
# Backend (NestJS BFF)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
backend:
|
backend:
|
||||||
image: ${BACKEND_IMAGE:-portal-backend:latest}
|
image: ${BACKEND_IMAGE:-portal-backend}:${IMAGE_TAG:-latest}
|
||||||
container_name: portal-backend
|
container_name: portal-backend
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:${BACKEND_PORT:-4000}:4000"
|
- "127.0.0.1:${BACKEND_PORT:-4000}:4000"
|
||||||
|
|||||||
1
portal-backend.latest.tar.gz.sha256
Normal file
1
portal-backend.latest.tar.gz.sha256
Normal file
@ -0,0 +1 @@
|
|||||||
|
8c26832b5a788235f2fb461eeeb10a33f34f40830d04fb1235aed449b67ebe1c /home/barsa/projects/customer_portal/customer-portal/portal-backend.latest.tar.gz
|
||||||
1
portal-frontend.latest.tar.gz.sha256
Normal file
1
portal-frontend.latest.tar.gz.sha256
Normal file
@ -0,0 +1 @@
|
|||||||
|
8b0b76418ba09fc6cb3134db6ac87d350463f88fae6ffae4fd536111d15fa0cf /home/barsa/projects/customer_portal/customer-portal/portal-frontend.latest.tar.gz
|
||||||
@ -292,6 +292,8 @@ while [[ $# -gt 0 ]]; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
export IMAGE_TAG
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Main
|
# Main
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user