feat(CUB-64): Docker runtime setup for development & deployment
Some checks failed
Dev Build / build-test (pull_request) Failing after 47s
Dev Build / deploy-dev (pull_request) Has been skipped
Dev Build / notify-success (pull_request) Has been skipped
Dev Build / notify-failure (pull_request) Successful in 3s

- Backend Dockerfile: added curl install for health check (not in aspnet base image)
- Frontend Dockerfile: multi-stage Angular build with nginx serving
- Frontend nginx.conf: SPA routing, API proxy, SignalR WebSocket support, health endpoint
- Frontend .dockerignore: excludes node_modules, dist, .angular, etc.
- docker-compose.dev.yml: added PostgreSQL service, fixed frontend context path,
  renamed web service from control-center-web to extrudex-web, added DB env vars,
  proper service dependencies with health checks
- deploy.sh: updated service list to include PostgreSQL port
This commit is contained in:
2026-04-27 08:33:18 +00:00
parent 8168d25bdf
commit 61178ebb7b
6 changed files with 135 additions and 7 deletions

View File

@@ -17,6 +17,9 @@ RUN dotnet publish Extrudex.csproj \
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
WORKDIR /app
# Install curl for health check (not included in aspnet base image)
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
# Non-root user for security
RUN adduser --disabled-password --gecos "" appuser
USER appuser

View File

@@ -18,13 +18,14 @@ echo "📦 Building and starting services..."
$COMPOSE_CMD -f docker-compose.dev.yml up -d --build
echo "⏳ Waiting for services to become healthy..."
sleep 10
sleep 15
echo "✅ Deployment complete!"
echo ""
echo "Services running:"
echo " • PostgreSQL: localhost:5433"
echo " • Extrudex API: http://localhost:5080"
echo " • Control Center Web: http://localhost:5081"
echo " • Extrudex Web: http://localhost:5081"
echo ""
echo "To view logs:"
echo " $COMPOSE_CMD -f docker-compose.dev.yml logs -f"

View File

@@ -1,6 +1,25 @@
version: '3.8'
services:
extrudex-db:
image: postgres:16-alpine
container_name: extrudex-db
environment:
POSTGRES_USER: extrudex
POSTGRES_PASSWORD: changeme
POSTGRES_DB: extrudex
ports:
- "5433:5432"
volumes:
- extrudex-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U extrudex"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
networks:
- extrudex-network
extrudex-api:
build:
context: ./backend
@@ -11,6 +30,14 @@ services:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8080
- EXTRUDEX_DB_HOST=extrudex-db
- EXTRUDEX_DB_PORT=5432
- EXTRUDEX_DB_NAME=extrudex
- EXTRUDEX_DB_USER=extrudex
- EXTRUDEX_DB_PASSWORD=changeme
depends_on:
extrudex-db:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
@@ -21,11 +48,11 @@ services:
networks:
- extrudex-network
control-center-web:
extrudex-web:
build:
context: ../Control-Center/frontend
context: ./frontend
dockerfile: Dockerfile
container_name: control-center-web
container_name: extrudex-web
ports:
- "5081:80"
depends_on:
@@ -35,6 +62,9 @@ services:
networks:
- extrudex-network
volumes:
extrudex-db-data:
networks:
extrudex-network:
driver: bridge

10
frontend/.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
node_modules
dist
.git
.angular
.vscode
*.md
.editorconfig
.prettierrc
src/test.ts
**/*.spec.ts

30
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,30 @@
# ── Stage 1: Build the Angular application ───────────────────
FROM node:22-alpine AS build
WORKDIR /app
# Copy package files first for better layer caching
COPY package.json package-lock.json ./
RUN npm ci
# Copy source and build
COPY . .
RUN npx ng build --configuration production
# ── Stage 2: Serve static files with nginx ───────────────────
FROM nginx:alpine
# Remove default nginx config
RUN rm /etc/nginx/conf.d/default.conf
# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy built Angular artifacts from build stage
COPY --from=build /app/dist/frontend/browser /usr/share/nginx/html
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -qO- http://localhost:80/health || exit 1
CMD ["nginx", "-g", "daemon off;"]

54
frontend/nginx.conf Normal file
View File

@@ -0,0 +1,54 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
gzip_min_length 256;
# Angular SPA — fallback to index.html for client-side routing
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets aggressively
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Proxy API requests to backend
# Uses resolver so nginx doesn't crash if backend isn't available at startup
resolver 127.0.0.11 valid=30s ipv6=off;
set $backend "extrudex-api:8080";
location /api/ {
proxy_pass http://$backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# SignalR WebSocket support
location /hubs/ {
proxy_pass http://$backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Health check endpoint
location /health {
access_log off;
return 200 "ok";
add_header Content-Type text/plain;
}
}