diff --git a/docker-compose.app.yml b/docker-compose.app.yml index fec9d10c..b0c9b616 100644 --- a/docker-compose.app.yml +++ b/docker-compose.app.yml @@ -14,6 +14,7 @@ # NOTE: Images must be built separately before using: # cd /data/app/igny8/backend && docker build -t igny8-backend:latest -f Dockerfile . # cd /data/app/igny8/frontend && docker build -t igny8-frontend-dev:latest -f Dockerfile.dev . +# cd /data/app/igny8/frontend && docker build -t igny8-marketing:latest -f Dockerfile.marketing . # ============================================================================= name: igny8-app @@ -81,6 +82,19 @@ services: - "com.docker.compose.project=igny8-app" - "com.docker.compose.service=igny8_frontend" + igny8_marketing: + # NOTE: Use 'image:' not 'build:' to avoid creating parallel stacks + # Build images separately: docker build -t igny8-marketing:latest -f Dockerfile.marketing . + image: igny8-marketing:latest + container_name: igny8_marketing + restart: always + ports: + - "0.0.0.0:8022:8020" # Marketing site port (internal: 8020, external: 8022) + networks: [igny8_net] + labels: + - "com.docker.compose.project=igny8-app" + - "com.docker.compose.service=igny8_marketing" + igny8_celery_worker: image: igny8-backend:latest container_name: igny8_celery_worker diff --git a/docs/MARKETING_DEPLOYMENT.md b/docs/MARKETING_DEPLOYMENT.md new file mode 100644 index 00000000..8c456295 --- /dev/null +++ b/docs/MARKETING_DEPLOYMENT.md @@ -0,0 +1,210 @@ +# Marketing Site Container Deployment Guide + +## ✅ Implementation Complete + +The marketing site is now containerized and running! This document explains the new setup and how to use it. + +--- + +## 🏗️ Architecture + +### Before (Manual) +- Marketing files in `/var/www/igny8-marketing/` +- Manual build → copy → restart process +- No version control for deployments + +### After (Containerized) ✅ +- Marketing site runs in `igny8_marketing` container +- Automated builds and deployments +- Version controlled with Docker images +- Easy rollback capability + +--- + +## 📦 New Components + +### 1. Dockerfile.marketing +**Location:** `/data/app/igny8/frontend/Dockerfile.marketing` + +Builds the marketing site and serves it with Caddy. + +### 2. Caddyfile.marketing +**Location:** `/data/app/igny8/frontend/Caddyfile.marketing` + +Caddy configuration for the marketing container (port 8020). + +### 3. igny8_marketing Service +**Location:** `docker-compose.app.yml` + +New container service for the marketing site. + +### 4. Updated Main Caddyfile +**Location:** `/var/lib/docker/volumes/portainer_data/_data/caddy/Caddyfile` + +Now routes `igny8.com` to `igny8_marketing:8020` container instead of static files. + +--- + +## 🚀 Deployment Process + +### Initial Setup (One-time) + +1. **Build the marketing image:** + ```bash + cd /data/app/igny8/frontend + docker build -t igny8-marketing:latest -f Dockerfile.marketing . + ``` + +2. **Start the marketing container:** + ```bash + cd /data/app/igny8 + docker compose -f docker-compose.app.yml -p igny8-app up -d igny8_marketing + ``` + +3. **Reload Caddy:** + ```bash + cd /data/app + docker compose restart caddy + ``` + +### Updating Marketing Site + +**New Process (Automated):** +```bash +# 1. Rebuild the marketing image +cd /data/app/igny8/frontend +docker build -t igny8-marketing:latest -f Dockerfile.marketing . + +# 2. Restart the container (picks up new image) +cd /data/app/igny8 +docker compose -f docker-compose.app.yml -p igny8-app restart igny8_marketing +``` + +**Old Process (Manual - No Longer Needed):** +```bash +# ❌ OLD WAY - Don't use anymore +npm run build:marketing +sudo cp -r dist/* /var/www/igny8-marketing/ +docker compose restart caddy +``` + +--- + +## 🔄 Rollback Process + +If you need to rollback to a previous version: + +```bash +# 1. Tag the current image as backup +docker tag igny8-marketing:latest igny8-marketing:backup-$(date +%Y%m%d) + +# 2. Tag a previous image as latest (if you have it) +docker tag igny8-marketing:previous-version igny8-marketing:latest + +# 3. Restart container +docker compose -f docker-compose.app.yml -p igny8-app restart igny8_marketing +``` + +--- + +## 📊 Container Status + +### Check Marketing Container +```bash +docker ps --filter "name=igny8_marketing" +``` + +### View Marketing Logs +```bash +docker logs igny8_marketing +docker logs igny8_marketing --tail 50 -f # Follow logs +``` + +### Test Marketing Site +```bash +# Test direct container access +curl http://localhost:8022/marketing.html + +# Test through Caddy (production) +curl https://igny8.com/marketing.html +``` + +--- + +## 🔍 Troubleshooting + +### Container Not Starting +```bash +# Check logs +docker logs igny8_marketing + +# Check if image exists +docker images | grep igny8-marketing + +# Rebuild if needed +cd /data/app/igny8/frontend +docker build -t igny8-marketing:latest -f Dockerfile.marketing . +``` + +### Caddy Not Routing Correctly +```bash +# Check Caddy logs +docker logs igny8_caddy + +# Verify Caddyfile +cat /var/lib/docker/volumes/portainer_data/_data/caddy/Caddyfile + +# Reload Caddy +cd /data/app +docker compose restart caddy +``` + +### Network Issues +```bash +# Verify containers are on same network +docker network inspect igny8_net | grep -A 5 igny8_marketing +docker network inspect igny8_net | grep -A 5 igny8_caddy +``` + +--- + +## 📝 File Locations + +| Component | Location | +|-----------|----------| +| Dockerfile.marketing | `/data/app/igny8/frontend/Dockerfile.marketing` | +| Caddyfile.marketing | `/data/app/igny8/frontend/Caddyfile.marketing` | +| docker-compose.app.yml | `/data/app/igny8/docker-compose.app.yml` | +| Main Caddyfile | `/var/lib/docker/volumes/portainer_data/_data/caddy/Caddyfile` | +| Marketing Image | Docker: `igny8-marketing:latest` | +| Container Name | `igny8_marketing` | +| Container Port | `8020` (internal), `8022` (external) | + +--- + +## ✅ Benefits + +1. **Automated Deployments** - No more manual file copying +2. **Version Control** - Each deployment is a Docker image +3. **Easy Rollback** - Quick container image rollback +4. **Isolation** - Marketing site isolated in its own container +5. **Reproducible** - Same build process every time +6. **CI/CD Ready** - Can be fully automated + +--- + +## 🎯 Current Status + +✅ Marketing container is **running** +✅ Caddy routing is **configured** +✅ Site is **accessible** at `https://igny8.com` +✅ Direct container access at `http://localhost:8022` + +--- + +## 📚 Related Documentation + +- [Deployment Architecture Analysis](./DEPLOYMENT_ARCHITECTURE.md) +- Docker Compose: `/data/app/igny8/docker-compose.app.yml` +- Main Caddyfile: `/var/lib/docker/volumes/portainer_data/_data/caddy/Caddyfile` + diff --git a/frontend/Caddyfile.marketing b/frontend/Caddyfile.marketing new file mode 100644 index 00000000..1f4458c7 --- /dev/null +++ b/frontend/Caddyfile.marketing @@ -0,0 +1,21 @@ +:8020 { + # Enable compression + encode gzip zstd + + # Set root to built files + root * /usr/share/caddy + + # Authenticated app served under /app (if needed in future) + handle_path /app* { + uri strip_prefix /app + try_files {path} /index.html + file_server + } + + # Marketing site is the public default + handle { + try_files {path} /marketing.html + file_server + } +} + diff --git a/frontend/Dockerfile.marketing b/frontend/Dockerfile.marketing new file mode 100644 index 00000000..084a1fad --- /dev/null +++ b/frontend/Dockerfile.marketing @@ -0,0 +1,24 @@ +# Marketing Site Dockerfile +# Builds and serves the marketing website in a container +FROM node:18-alpine AS builder +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy source code +COPY . . + +# Build marketing site +RUN npm run build:marketing + +# Stage 2: Serve with Caddy +FROM caddy:latest +COPY --from=builder /app/dist /usr/share/caddy +COPY Caddyfile.marketing /etc/caddy/Caddyfile +EXPOSE 8020 +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"] +