mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
Add GHCR container image support with multi-arch builds and security scanning
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
99
.dockerignore
Normal file
99
.dockerignore
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
coverage
|
||||||
|
.nyc_output
|
||||||
|
*.test.ts
|
||||||
|
*.test.tsx
|
||||||
|
*.spec.ts
|
||||||
|
*.spec.tsx
|
||||||
|
__tests__
|
||||||
|
__mocks__
|
||||||
|
.vitest
|
||||||
|
|
||||||
|
# Next.js
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
|
||||||
|
# Production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
.env.development
|
||||||
|
.env.test
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# Vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# TypeScript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
docs
|
||||||
|
README*
|
||||||
|
CHANGELOG*
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
# CI/CD
|
||||||
|
.github
|
||||||
|
.gitlab-ci.yml
|
||||||
|
azure-pipelines.yml
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
Dockerfile*
|
||||||
|
docker-compose*
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Development
|
||||||
|
.editorconfig
|
||||||
|
.prettierrc*
|
||||||
|
.eslintrc*
|
||||||
|
.eslintignore
|
||||||
|
|
||||||
|
# Storybook
|
||||||
|
.storybook
|
||||||
|
storybook-static
|
||||||
|
|
||||||
|
# E2E
|
||||||
|
e2e
|
||||||
|
playwright-report
|
||||||
|
test-results
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp
|
||||||
|
temp
|
||||||
|
.tmp
|
||||||
|
.cache
|
||||||
138
.github/workflows/container-build.yml
vendored
Normal file
138
.github/workflows/container-build.yml
vendored
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
name: Build and Push GHCR Images
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
name: Build and Push Docker Images
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- image: nextjs-app
|
||||||
|
context: .
|
||||||
|
dockerfile: ./frontends/nextjs/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
- image: dbal-daemon
|
||||||
|
context: ./dbal/production
|
||||||
|
dockerfile: ./dbal/production/build-config/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels)
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=sha,prefix={{branch}}-
|
||||||
|
type=raw,value=latest,enable={{is_default_branch}}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ${{ matrix.context }}
|
||||||
|
file: ${{ matrix.dockerfile }}
|
||||||
|
platforms: ${{ matrix.platforms }}
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
||||||
|
VCS_REF=${{ github.sha }}
|
||||||
|
VERSION=${{ steps.meta.outputs.version }}
|
||||||
|
|
||||||
|
- name: Generate artifact attestation
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
|
||||||
|
subject-digest: ${{ steps.build.outputs.digest }}
|
||||||
|
push-to-registry: true
|
||||||
|
|
||||||
|
security-scan:
|
||||||
|
name: Security Scan Images
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-and-push
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
image: [nextjs-app, dbal-daemon]
|
||||||
|
steps:
|
||||||
|
- name: Run Trivy vulnerability scanner
|
||||||
|
uses: aquasecurity/trivy-action@master
|
||||||
|
with:
|
||||||
|
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}:${{ github.ref_name }}
|
||||||
|
format: 'sarif'
|
||||||
|
output: 'trivy-results-${{ matrix.image }}.sarif'
|
||||||
|
|
||||||
|
- name: Upload Trivy results to GitHub Security tab
|
||||||
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
|
with:
|
||||||
|
sarif_file: 'trivy-results-${{ matrix.image }}.sarif'
|
||||||
|
category: container-${{ matrix.image }}
|
||||||
|
|
||||||
|
publish-manifest:
|
||||||
|
name: Create Multi-Arch Manifest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-and-push
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
steps:
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create and push manifest for all images
|
||||||
|
run: |
|
||||||
|
for image in nextjs-app dbal-daemon; do
|
||||||
|
docker manifest create \
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$image:${{ github.ref_name }} \
|
||||||
|
--amend ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$image:${{ github.ref_name }}-amd64 \
|
||||||
|
--amend ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$image:${{ github.ref_name }}-arm64
|
||||||
|
docker manifest push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$image:${{ github.ref_name }}
|
||||||
|
done
|
||||||
110
docker-compose.ghcr.yml
Normal file
110
docker-compose.ghcr.yml
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
version: '3.9'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# MetaBuilder Next.js App
|
||||||
|
nextjs-app:
|
||||||
|
image: ghcr.io/${GITHUB_REPOSITORY:-johndoe6345789/metabuilder}/nextjs-app:${IMAGE_TAG:-latest}
|
||||||
|
container_name: metabuilder-nextjs
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DATABASE_URL=file:/app/data/metabuilder.db
|
||||||
|
- DBAL_API_URL=http://dbal-daemon:8080
|
||||||
|
- DBAL_WS_URL=ws://dbal-daemon:50051
|
||||||
|
- NEXTAUTH_URL=http://localhost:3000
|
||||||
|
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-change-me-in-production}
|
||||||
|
volumes:
|
||||||
|
- metabuilder-data:/app/data
|
||||||
|
depends_on:
|
||||||
|
- dbal-daemon
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
networks:
|
||||||
|
- metabuilder-network
|
||||||
|
|
||||||
|
# DBAL Daemon (Production)
|
||||||
|
dbal-daemon:
|
||||||
|
image: ghcr.io/${GITHUB_REPOSITORY:-johndoe6345789/metabuilder}/dbal-daemon:${IMAGE_TAG:-latest}
|
||||||
|
container_name: metabuilder-dbal
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
- "50051:50051"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DATABASE_URL=file:/app/data/metabuilder.db
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- ENABLE_METRICS=true
|
||||||
|
volumes:
|
||||||
|
- metabuilder-data:/app/data
|
||||||
|
- dbal-logs:/app/logs
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
|
networks:
|
||||||
|
- metabuilder-network
|
||||||
|
|
||||||
|
# Prometheus for metrics (optional)
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus:latest
|
||||||
|
container_name: metabuilder-prometheus
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
volumes:
|
||||||
|
- ./deployment/docker/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||||
|
- prometheus-data:/prometheus
|
||||||
|
command:
|
||||||
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||||
|
- '--storage.tsdb.path=/prometheus'
|
||||||
|
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
|
||||||
|
- '--web.console.templates=/usr/share/prometheus/consoles'
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- metabuilder-network
|
||||||
|
profiles:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
# Grafana for visualization (optional)
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:latest
|
||||||
|
container_name: metabuilder-grafana
|
||||||
|
ports:
|
||||||
|
- "3001:3000"
|
||||||
|
environment:
|
||||||
|
- GF_SECURITY_ADMIN_USER=admin
|
||||||
|
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
|
||||||
|
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
|
||||||
|
volumes:
|
||||||
|
- grafana-data:/var/lib/grafana
|
||||||
|
- ./deployment/docker/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
|
||||||
|
- ./deployment/docker/grafana/datasources:/etc/grafana/provisioning/datasources:ro
|
||||||
|
depends_on:
|
||||||
|
- prometheus
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- metabuilder-network
|
||||||
|
profiles:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
metabuilder-data:
|
||||||
|
driver: local
|
||||||
|
dbal-logs:
|
||||||
|
driver: local
|
||||||
|
prometheus-data:
|
||||||
|
driver: local
|
||||||
|
grafana-data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
metabuilder-network:
|
||||||
|
driver: bridge
|
||||||
189
docs/CONTAINER_IMAGES.md
Normal file
189
docs/CONTAINER_IMAGES.md
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
# MetaBuilder Container Images
|
||||||
|
|
||||||
|
MetaBuilder provides official container images hosted on GitHub Container Registry (GHCR) for easy deployment.
|
||||||
|
|
||||||
|
## Available Images
|
||||||
|
|
||||||
|
### 1. Next.js App (`ghcr.io/johndoe6345789/metabuilder/nextjs-app`)
|
||||||
|
The main MetaBuilder web application built with Next.js.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Multi-architecture support (amd64, arm64)
|
||||||
|
- Standalone output for minimal image size
|
||||||
|
- Built-in health checks
|
||||||
|
- Non-root user for security
|
||||||
|
- DBAL types pre-generated
|
||||||
|
|
||||||
|
**Tags:**
|
||||||
|
- `latest` - Latest stable build from main branch
|
||||||
|
- `develop` - Latest development build
|
||||||
|
- `v*.*.*` - Semantic version tags
|
||||||
|
- `main-<sha>` - Specific commit from main branch
|
||||||
|
|
||||||
|
### 2. DBAL Daemon (`ghcr.io/johndoe6345789/metabuilder/dbal-daemon`)
|
||||||
|
The secure C++ DBAL daemon for production deployments.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Multi-architecture support (amd64, arm64)
|
||||||
|
- Process isolation for security
|
||||||
|
- Connection pooling
|
||||||
|
- Row-level security enforcement
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Using Docker Compose with GHCR Images
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull and start all services
|
||||||
|
docker compose -f docker-compose.ghcr.yml up -d
|
||||||
|
|
||||||
|
# With monitoring stack
|
||||||
|
docker compose -f docker-compose.ghcr.yml --profile monitoring up -d
|
||||||
|
|
||||||
|
# Stop services
|
||||||
|
docker compose -f docker-compose.ghcr.yml down
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose -f docker-compose.ghcr.yml logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Individual Containers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run Next.js app
|
||||||
|
docker run -d \
|
||||||
|
--name metabuilder-nextjs \
|
||||||
|
-p 3000:3000 \
|
||||||
|
-e DATABASE_URL=file:/app/data/metabuilder.db \
|
||||||
|
-v metabuilder-data:/app/data \
|
||||||
|
ghcr.io/johndoe6345789/metabuilder/nextjs-app:latest
|
||||||
|
|
||||||
|
# Run DBAL daemon
|
||||||
|
docker run -d \
|
||||||
|
--name metabuilder-dbal \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-p 50051:50051 \
|
||||||
|
-e DATABASE_URL=file:/app/data/metabuilder.db \
|
||||||
|
-v metabuilder-data:/app/data \
|
||||||
|
ghcr.io/johndoe6345789/metabuilder/dbal-daemon:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
To pull images from GHCR, you need a GitHub Personal Access Token with `read:packages` scope:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Login to GHCR
|
||||||
|
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
|
||||||
|
|
||||||
|
# Pull an image
|
||||||
|
docker pull ghcr.io/johndoe6345789/metabuilder/nextjs-app:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building Images Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build Next.js app
|
||||||
|
docker build -f frontends/nextjs/Dockerfile -t metabuilder/nextjs-app:local .
|
||||||
|
|
||||||
|
# Build with specific platform
|
||||||
|
docker buildx build \
|
||||||
|
--platform linux/amd64,linux/arm64 \
|
||||||
|
-f frontends/nextjs/Dockerfile \
|
||||||
|
-t metabuilder/nextjs-app:local .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
### Next.js App
|
||||||
|
- `DATABASE_URL` - Database connection string
|
||||||
|
- `DBAL_API_URL` - DBAL daemon API URL (default: `http://localhost:8080`)
|
||||||
|
- `DBAL_WS_URL` - DBAL daemon WebSocket URL (default: `ws://localhost:50051`)
|
||||||
|
- `NEXTAUTH_SECRET` - NextAuth secret for session encryption
|
||||||
|
- `NODE_ENV` - Environment mode (production/development)
|
||||||
|
|
||||||
|
### DBAL Daemon
|
||||||
|
- `DATABASE_URL` - Database connection string
|
||||||
|
- `LOG_LEVEL` - Logging level (debug/info/warn/error)
|
||||||
|
- `ENABLE_METRICS` - Enable Prometheus metrics (true/false)
|
||||||
|
- `MAX_CONNECTIONS` - Maximum database connections
|
||||||
|
|
||||||
|
## Health Checks
|
||||||
|
|
||||||
|
Both images include health checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Next.js app health
|
||||||
|
curl http://localhost:3000/api/health
|
||||||
|
|
||||||
|
# Check DBAL daemon health
|
||||||
|
curl http://localhost:8080/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Image Scanning
|
||||||
|
All images are automatically scanned for vulnerabilities using Trivy during the CI/CD pipeline. Results are available in the GitHub Security tab.
|
||||||
|
|
||||||
|
### Attestations
|
||||||
|
Build provenance attestations are generated for all images pushed to GHCR, ensuring supply chain security.
|
||||||
|
|
||||||
|
### Non-Root Users
|
||||||
|
All containers run as non-root users:
|
||||||
|
- Next.js app runs as user `nextjs` (UID 1001)
|
||||||
|
- DBAL daemon runs as user `dbal` (UID 1000)
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
When using the monitoring profile:
|
||||||
|
- **Prometheus**: http://localhost:9090
|
||||||
|
- **Grafana**: http://localhost:3001 (admin/admin)
|
||||||
|
|
||||||
|
## Volumes
|
||||||
|
|
||||||
|
- `metabuilder-data` - Persistent database and application data
|
||||||
|
- `dbal-logs` - DBAL daemon logs
|
||||||
|
- `prometheus-data` - Prometheus metrics storage
|
||||||
|
- `grafana-data` - Grafana dashboards and settings
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container won't start
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
docker logs metabuilder-nextjs
|
||||||
|
docker logs metabuilder-dbal
|
||||||
|
|
||||||
|
# Check health status
|
||||||
|
docker inspect --format='{{json .State.Health}}' metabuilder-nextjs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Permission issues
|
||||||
|
```bash
|
||||||
|
# Ensure volumes have correct permissions
|
||||||
|
docker volume inspect metabuilder-data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network connectivity
|
||||||
|
```bash
|
||||||
|
# Test network connectivity between containers
|
||||||
|
docker compose -f docker-compose.ghcr.yml exec nextjs-app curl http://dbal-daemon:8080/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
Images are automatically built and pushed on:
|
||||||
|
- Push to `main` or `develop` branches
|
||||||
|
- New version tags (`v*.*.*`)
|
||||||
|
- Manual workflow dispatch
|
||||||
|
|
||||||
|
See `.github/workflows/container-build.yml` for the complete workflow.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues related to container images, please open an issue in the MetaBuilder repository with:
|
||||||
|
- Image tag being used
|
||||||
|
- Docker/Podman version
|
||||||
|
- Platform (amd64/arm64)
|
||||||
|
- Container logs
|
||||||
|
- docker-compose.yml configuration (if applicable)
|
||||||
89
frontends/nextjs/Dockerfile
Normal file
89
frontends/nextjs/Dockerfile
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# Multi-stage Dockerfile for MetaBuilder Next.js App
|
||||||
|
# Optimized for production deployment with GHCR
|
||||||
|
|
||||||
|
# Stage 1: Dependencies
|
||||||
|
FROM node:20-alpine AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
|
||||||
|
# Copy package files for all workspaces
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY frontends/nextjs/package*.json ./frontends/nextjs/
|
||||||
|
COPY dbal/development/package*.json ./dbal/development/
|
||||||
|
COPY config/package*.json ./config/ 2>/dev/null || true
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Stage 2: Builder
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy dependencies from deps stage
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY --from=deps /app/frontends/nextjs/node_modules ./frontends/nextjs/node_modules
|
||||||
|
COPY --from=deps /app/dbal/development/node_modules ./dbal/development/node_modules
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Generate DBAL types from YAML schemas
|
||||||
|
WORKDIR /app/dbal/development
|
||||||
|
RUN npx tsx ../shared/tools/codegen/generate-types.ts
|
||||||
|
|
||||||
|
# Generate Prisma Client
|
||||||
|
WORKDIR /app/frontends/nextjs
|
||||||
|
RUN npm run db:generate
|
||||||
|
|
||||||
|
# Build Next.js app
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 3: Production runner
|
||||||
|
FROM node:20-alpine AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
tini \
|
||||||
|
curl \
|
||||||
|
dumb-init
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup --system --gid 1001 nodejs && \
|
||||||
|
adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
# Copy necessary files from builder
|
||||||
|
COPY --from=builder /app/frontends/nextjs/public ./public
|
||||||
|
COPY --from=builder /app/frontends/nextjs/.next/standalone ./
|
||||||
|
COPY --from=builder /app/frontends/nextjs/.next/static ./.next/static
|
||||||
|
|
||||||
|
# Copy Prisma schema and generated client
|
||||||
|
COPY --from=builder /app/prisma ./prisma
|
||||||
|
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
|
||||||
|
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
RUN chown -R nextjs:nodejs /app
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:3000/api/health || exit 1
|
||||||
|
|
||||||
|
# Use dumb-init to handle signals
|
||||||
|
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
Reference in New Issue
Block a user