387 lines
10 KiB
Bash
Executable File
387 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
# scripts/ci/build-production.sh - Сборка продакшен образов
|
|
|
|
set -e
|
|
|
|
echo "🚀 Building production images..."
|
|
|
|
# Переменные
|
|
REGISTRY=${DOCKER_REGISTRY:-"registry.hub.docker.com"}
|
|
PROJECT_NAME="catlink"
|
|
VERSION=${DRONE_TAG:-${DRONE_COMMIT_SHA:0:8}}
|
|
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
VCS_REF=${DRONE_COMMIT_SHA:-$(git rev-parse HEAD)}
|
|
|
|
echo "📋 Build information:"
|
|
echo " • Registry: $REGISTRY"
|
|
echo " • Project: $PROJECT_NAME"
|
|
echo " • Version: $VERSION"
|
|
echo " • Build Date: $BUILD_DATE"
|
|
echo " • VCS Ref: $VCS_REF"
|
|
|
|
# Создание production .env
|
|
echo "⚙️ Creating production environment configuration..."
|
|
cat > .env.production << EOF
|
|
# Production Environment Configuration
|
|
NODE_ENV=production
|
|
DJANGO_ENV=production
|
|
DEBUG=False
|
|
|
|
# Security
|
|
SECRET_KEY=\${SECRET_KEY}
|
|
ALLOWED_HOSTS=\${ALLOWED_HOSTS}
|
|
CORS_ALLOWED_ORIGINS=\${CORS_ALLOWED_ORIGINS}
|
|
|
|
# Database
|
|
DATABASE_URL=\${DATABASE_URL}
|
|
|
|
# Media and Static
|
|
STATIC_URL=/static/
|
|
MEDIA_URL=/media/
|
|
STATIC_ROOT=/app/staticfiles
|
|
MEDIA_ROOT=/app/media
|
|
|
|
# Build info
|
|
BUILD_VERSION=$VERSION
|
|
BUILD_DATE=$BUILD_DATE
|
|
VCS_REF=$VCS_REF
|
|
EOF
|
|
|
|
# Создание production docker-compose файла
|
|
echo "🐳 Creating production Docker Compose configuration..."
|
|
cat > docker-compose.production.yml << EOF
|
|
version: '3.8'
|
|
|
|
services:
|
|
web:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
args:
|
|
BUILD_VERSION: $VERSION
|
|
BUILD_DATE: $BUILD_DATE
|
|
VCS_REF: $VCS_REF
|
|
image: $REGISTRY/$PROJECT_NAME-backend:$VERSION
|
|
environment:
|
|
- DJANGO_ENV=production
|
|
- DEBUG=False
|
|
restart: unless-stopped
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.catlink-api.rule=Host(\`api.catlink.dev\`)"
|
|
- "traefik.http.services.catlink-api.loadbalancer.server.port=8000"
|
|
|
|
frontend:
|
|
build:
|
|
context: ./frontend/linktree-frontend
|
|
dockerfile: Dockerfile
|
|
args:
|
|
BUILD_VERSION: $VERSION
|
|
BUILD_DATE: $BUILD_DATE
|
|
VCS_REF: $VCS_REF
|
|
NEXT_PUBLIC_API_URL: \${NEXT_PUBLIC_API_URL}
|
|
image: $REGISTRY/$PROJECT_NAME-frontend:$VERSION
|
|
environment:
|
|
- NODE_ENV=production
|
|
restart: unless-stopped
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.catlink.rule=Host(\`catlink.dev\`)"
|
|
- "traefik.http.services.catlink.loadbalancer.server.port=3000"
|
|
|
|
networks:
|
|
default:
|
|
external:
|
|
name: traefik_default
|
|
EOF
|
|
|
|
# Обновление Dockerfile для production
|
|
echo "📝 Updating Dockerfiles for production..."
|
|
|
|
# Backend Dockerfile
|
|
cat > backend/Dockerfile.production << EOF
|
|
FROM python:3.11-slim as builder
|
|
|
|
# Build arguments
|
|
ARG BUILD_VERSION=latest
|
|
ARG BUILD_DATE
|
|
ARG VCS_REF
|
|
|
|
# Metadata
|
|
LABEL org.opencontainers.image.title="CatLink Backend"
|
|
LABEL org.opencontainers.image.description="CatLink Django API"
|
|
LABEL org.opencontainers.image.version="\$BUILD_VERSION"
|
|
LABEL org.opencontainers.image.created="\$BUILD_DATE"
|
|
LABEL org.opencontainers.image.revision="\$VCS_REF"
|
|
LABEL org.opencontainers.image.source="https://github.com/smartsoltech/links"
|
|
|
|
# Install system dependencies
|
|
RUN apt-get update && apt-get install -y \\
|
|
gcc \\
|
|
postgresql-client \\
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Set work directory
|
|
WORKDIR /app
|
|
|
|
# Install Python dependencies
|
|
COPY requirements.txt .
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
# Copy project
|
|
COPY . .
|
|
|
|
# Create directories
|
|
RUN mkdir -p staticfiles media
|
|
|
|
# Collect static files
|
|
RUN python manage.py collectstatic --noinput
|
|
|
|
# Create non-root user
|
|
RUN useradd --create-home --shell /bin/bash app \\
|
|
&& chown -R app:app /app
|
|
USER app
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \\
|
|
CMD curl -f http://localhost:8000/api/ || exit 1
|
|
|
|
EXPOSE 8000
|
|
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "backend.wsgi:application"]
|
|
EOF
|
|
|
|
# Frontend Dockerfile
|
|
cat > frontend/linktree-frontend/Dockerfile.production << EOF
|
|
FROM node:20-alpine as builder
|
|
|
|
# Build arguments
|
|
ARG BUILD_VERSION=latest
|
|
ARG BUILD_DATE
|
|
ARG VCS_REF
|
|
ARG NEXT_PUBLIC_API_URL
|
|
|
|
# Metadata
|
|
LABEL org.opencontainers.image.title="CatLink Frontend"
|
|
LABEL org.opencontainers.image.description="CatLink Next.js Application"
|
|
LABEL org.opencontainers.image.version="\$BUILD_VERSION"
|
|
LABEL org.opencontainers.image.created="\$BUILD_DATE"
|
|
LABEL org.opencontainers.image.revision="\$VCS_REF"
|
|
LABEL org.opencontainers.image.source="https://github.com/smartsoltech/links"
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package*.json ./
|
|
|
|
# Install dependencies
|
|
RUN npm ci --only=production
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Set build environment
|
|
ENV NODE_ENV=production
|
|
ENV NEXT_PUBLIC_API_URL=\$NEXT_PUBLIC_API_URL
|
|
ENV BUILD_VERSION=\$BUILD_VERSION
|
|
|
|
# Build application
|
|
RUN npm run build
|
|
|
|
# Production stage
|
|
FROM node:20-alpine as runner
|
|
|
|
WORKDIR /app
|
|
|
|
# Create non-root user
|
|
RUN addgroup --system --gid 1001 nodejs
|
|
RUN adduser --system --uid 1001 nextjs
|
|
|
|
# Copy built application
|
|
COPY --from=builder /app/public ./public
|
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
|
|
USER nextjs
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \\
|
|
CMD curl -f http://localhost:3000 || exit 1
|
|
|
|
EXPOSE 3000
|
|
|
|
ENV PORT 3000
|
|
ENV HOSTNAME "0.0.0.0"
|
|
|
|
CMD ["node", "server.js"]
|
|
EOF
|
|
|
|
# Сборка продакшен образов
|
|
echo "🔨 Building production Docker images..."
|
|
|
|
# Backend
|
|
echo " • Building backend production image..."
|
|
docker build -f backend/Dockerfile.production \\
|
|
--build-arg BUILD_VERSION="$VERSION" \\
|
|
--build-arg BUILD_DATE="$BUILD_DATE" \\
|
|
--build-arg VCS_REF="$VCS_REF" \\
|
|
-t "$REGISTRY/$PROJECT_NAME-backend:$VERSION" \\
|
|
-t "$REGISTRY/$PROJECT_NAME-backend:latest" \\
|
|
backend/
|
|
|
|
# Frontend
|
|
echo " • Building frontend production image..."
|
|
docker build -f frontend/linktree-frontend/Dockerfile.production \\
|
|
--build-arg BUILD_VERSION="$VERSION" \\
|
|
--build-arg BUILD_DATE="$BUILD_DATE" \\
|
|
--build-arg VCS_REF="$VCS_REF" \\
|
|
--build-arg NEXT_PUBLIC_API_URL="$NEXT_PUBLIC_API_URL" \\
|
|
-t "$REGISTRY/$PROJECT_NAME-frontend:$VERSION" \\
|
|
-t "$REGISTRY/$PROJECT_NAME-frontend:latest" \\
|
|
frontend/linktree-frontend/
|
|
|
|
# Проверка размеров образов
|
|
echo "📊 Production image sizes:"
|
|
docker images | grep "$PROJECT_NAME" | grep -E "($VERSION|latest)"
|
|
|
|
# Сканирование образов на уязвимости (если доступно)
|
|
echo "🔍 Scanning production images..."
|
|
for image in "$PROJECT_NAME-backend:$VERSION" "$PROJECT_NAME-frontend:$VERSION"; do
|
|
echo " • Scanning $image..."
|
|
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \\
|
|
aquasec/trivy image --exit-code 0 --severity HIGH,CRITICAL "$REGISTRY/$image" || \\
|
|
echo " ⚠️ Vulnerability scan completed with findings"
|
|
done
|
|
|
|
# Тестирование продакшен образов
|
|
echo "🧪 Testing production images..."
|
|
|
|
# Создание тестового docker-compose для продакшен образов
|
|
cat > docker-compose.test-prod.yml << EOF
|
|
version: '3.8'
|
|
services:
|
|
web-prod:
|
|
image: $REGISTRY/$PROJECT_NAME-backend:$VERSION
|
|
environment:
|
|
- DJANGO_ENV=production
|
|
- DEBUG=False
|
|
- SECRET_KEY=test-secret-key
|
|
- DATABASE_URL=sqlite:///db.sqlite3
|
|
- ALLOWED_HOSTS=localhost,127.0.0.1
|
|
ports:
|
|
- "8001:8000"
|
|
|
|
frontend-prod:
|
|
image: $REGISTRY/$PROJECT_NAME-frontend:$VERSION
|
|
environment:
|
|
- NODE_ENV=production
|
|
- NEXT_PUBLIC_API_URL=http://localhost:8001
|
|
ports:
|
|
- "3001:3000"
|
|
depends_on:
|
|
- web-prod
|
|
EOF
|
|
|
|
# Запуск тестов продакшен образов
|
|
echo " • Starting production containers for testing..."
|
|
docker-compose -f docker-compose.test-prod.yml up -d
|
|
|
|
sleep 30
|
|
|
|
# Проверка здоровья
|
|
backend_health=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8001/api/ || echo "000")
|
|
frontend_health=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3001 || echo "000")
|
|
|
|
echo " • Backend health: $backend_health"
|
|
echo " • Frontend health: $frontend_health"
|
|
|
|
# Очистка тестовых контейнеров
|
|
docker-compose -f docker-compose.test-prod.yml down
|
|
|
|
if [ "$backend_health" = "200" ] && [ "$frontend_health" = "200" ]; then
|
|
echo "✅ Production images tested successfully!"
|
|
else
|
|
echo "❌ Production image testing failed"
|
|
exit 1
|
|
fi
|
|
|
|
# Создание манифестов для деплоя
|
|
echo "📄 Creating deployment manifests..."
|
|
mkdir -p /tmp/deploy-manifests
|
|
|
|
# Kubernetes манифесты
|
|
cat > /tmp/deploy-manifests/catlink-k8s.yml << EOF
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: catlink-backend
|
|
labels:
|
|
app: catlink-backend
|
|
version: $VERSION
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: catlink-backend
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: catlink-backend
|
|
version: $VERSION
|
|
spec:
|
|
containers:
|
|
- name: backend
|
|
image: $REGISTRY/$PROJECT_NAME-backend:$VERSION
|
|
ports:
|
|
- containerPort: 8000
|
|
env:
|
|
- name: DJANGO_ENV
|
|
value: "production"
|
|
resources:
|
|
requests:
|
|
memory: "256Mi"
|
|
cpu: "250m"
|
|
limits:
|
|
memory: "512Mi"
|
|
cpu: "500m"
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: catlink-frontend
|
|
labels:
|
|
app: catlink-frontend
|
|
version: $VERSION
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: catlink-frontend
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: catlink-frontend
|
|
version: $VERSION
|
|
spec:
|
|
containers:
|
|
- name: frontend
|
|
image: $REGISTRY/$PROJECT_NAME-frontend:$VERSION
|
|
ports:
|
|
- containerPort: 3000
|
|
env:
|
|
- name: NODE_ENV
|
|
value: "production"
|
|
resources:
|
|
requests:
|
|
memory: "128Mi"
|
|
cpu: "100m"
|
|
limits:
|
|
memory: "256Mi"
|
|
cpu: "200m"
|
|
EOF
|
|
|
|
echo "✅ Production build completed successfully!"
|
|
echo "📦 Images built:"
|
|
echo " • $REGISTRY/$PROJECT_NAME-backend:$VERSION"
|
|
echo " • $REGISTRY/$PROJECT_NAME-frontend:$VERSION"
|
|
echo "📁 Deployment manifests: /tmp/deploy-manifests/" |