feature - 6 - fix production compose issues

This commit is contained in:
myrmidex 2025-12-27 20:55:04 +01:00
parent 630a8cc73f
commit 71212ef9da
5 changed files with 123 additions and 54 deletions

View file

@ -36,25 +36,24 @@ ENV APP_ENV=production \
MAIL_MAILER=smtp \ MAIL_MAILER=smtp \
MAIL_ENCRYPTION=tls MAIL_ENCRYPTION=tls
# Copy composer files and install PHP dependencies # Copy application code first
COPY composer.json composer.lock ./ COPY . .
# Install PHP dependencies (production only)
RUN composer install --no-dev --no-interaction --optimize-autoloader RUN composer install --no-dev --no-interaction --optimize-autoloader
# Copy package files and install Node dependencies # Install ALL Node dependencies (including dev for building)
COPY package*.json ./ RUN npm ci
RUN npm ci --omit=dev
# Copy application code
COPY . .
# Build frontend assets # Build frontend assets
RUN npm run build RUN npm run build
# Remove node_modules after build to save space
RUN rm -rf node_modules
# Laravel optimizations # Laravel optimizations
RUN php artisan config:cache \ RUN php artisan config:cache \
&& php artisan route:cache \ && php artisan route:cache \
&& php artisan view:cache \
&& php artisan livewire:discover \
&& composer dump-autoload --optimize && composer dump-autoload --optimize
# Set permissions # Set permissions
@ -93,5 +92,31 @@ EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/up || exit 1 CMD curl -f http://localhost:8000/up || exit 1
# Create startup script for production
RUN cat > /start-prod.sh <<'EOF'
#!/bin/sh
set -e
# Wait for database to be ready
echo "Waiting for database..."
for i in $(seq 1 30); do
if php artisan db:monitor --database=mysql 2>/dev/null | grep -q "OK"; then
echo "Database is ready!"
break
fi
echo "Waiting for database... ($i/30)"
sleep 2
done
# Run migrations
echo "Running migrations..."
php artisan migrate --force || echo "Migrations failed or already up-to-date"
# Start FrankenPHP # Start FrankenPHP
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"] exec frankenphp run --config /etc/caddy/Caddyfile
EOF
RUN chmod +x /start-prod.sh
# Start with our script
CMD ["/start-prod.sh"]

View file

@ -38,21 +38,17 @@ logs-db: ## Show database logs
docker compose logs -f db docker compose logs -f db
# Production Commands # Production Commands
.PHONY: prod
prod: ## Start production environment
docker compose -f docker-compose.prod.yml up -d
.PHONY: prod-build .PHONY: prod-build
prod-build: ## Build production image prod-build: ## Build production image for Codeberg
docker compose -f docker-compose.prod.yml build ./bin/build-push.sh
.PHONY: prod-stop .PHONY: prod-build-tag
prod-stop: ## Stop production environment prod-build-tag: ## Build with specific tag (usage: make prod-build-tag TAG=v1.0.0)
docker compose -f docker-compose.prod.yml down ./bin/build-push.sh $(TAG)
.PHONY: prod-logs .PHONY: prod-login
prod-logs: ## Show production logs prod-login: ## Login to Codeberg registry
docker compose -f docker-compose.prod.yml logs -f podman login codeberg.org
# Laravel Commands # Laravel Commands
.PHONY: artisan .PHONY: artisan

29
bin/build-push.sh Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
# Build and push production image to Codeberg
set -e
# Configuration
REGISTRY="codeberg.org"
NAMESPACE="lvl0"
IMAGE_NAME="dish-planner"
TAG="${1:-latest}"
echo "🔨 Building production image..."
podman build -f Dockerfile -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG} .
echo "📤 Pushing to Codeberg registry..."
echo "Please ensure you're logged in to Codeberg:"
echo " podman login codeberg.org"
podman push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}
echo "✅ Done! Image pushed to ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}"
echo ""
echo "To deploy in production:"
echo "1. Copy docker-compose.prod.yml to your server"
echo "2. Set required environment variables:"
echo " - APP_KEY (generate with: openssl rand -base64 32)"
echo " - APP_URL"
echo " - DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_ROOT_PASSWORD"
echo "3. Run: docker-compose -f docker-compose.prod.yml up -d"

View file

@ -1,12 +1,7 @@
# Production Docker Compose # Production Docker Compose
version: '3.8'
services: services:
app: app:
build: image: codeberg.org/lvl0/dish-planner:latest
context: .
dockerfile: Dockerfile
image: dishplanner:latest
container_name: dishplanner_app container_name: dishplanner_app
restart: always restart: always
ports: ports:
@ -30,8 +25,7 @@ services:
- app_storage:/app/storage - app_storage:/app/storage
- app_logs:/app/storage/logs - app_logs:/app/storage/logs
depends_on: depends_on:
db: - db
condition: service_healthy
networks: networks:
- dishplanner - dishplanner
healthcheck: healthcheck:
@ -50,22 +44,10 @@ services:
MYSQL_USER: "${DB_USERNAME}" MYSQL_USER: "${DB_USERNAME}"
MYSQL_PASSWORD: "${DB_PASSWORD}" MYSQL_PASSWORD: "${DB_PASSWORD}"
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}" MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
# MariaDB performance tuning
MYSQL_INITDB_SKIP_TZINFO: 1
MYSQL_CHARACTER_SET_SERVER: utf8mb4
MYSQL_COLLATION_SERVER: utf8mb4_unicode_ci
volumes: volumes:
- db_data:/var/lib/mysql - db_data:/var/lib/mysql
- ./database/backups:/backups # For backup scripts
networks: networks:
- dishplanner - dishplanner
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# No ports exposed - only accessible within network
# Optional: Redis for production caching/sessions # Optional: Redis for production caching/sessions
# redis: # redis:
@ -105,9 +87,6 @@ services:
networks: networks:
dishplanner: dishplanner:
driver: bridge driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes: volumes:
db_data: db_data:

View file

@ -52,6 +52,45 @@ pkgs.mkShell {
podman-compose exec app php artisan "$@" podman-compose exec app php artisan "$@"
} }
prod-build() {
local TAG="''${1:-latest}"
local REGISTRY="codeberg.org"
local NAMESPACE="lvl0"
local IMAGE_NAME="dish-planner"
echo "🔨 Building production image..."
podman build -f Dockerfile -t ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG} .
echo " Build complete: ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}"
echo "Run 'prod-push' to push to Codeberg"
}
prod-push() {
local TAG="''${1:-latest}"
local REGISTRY="codeberg.org"
local NAMESPACE="lvl0"
local IMAGE_NAME="dish-planner"
echo "📤 Pushing to Codeberg registry..."
if podman push ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}; then
echo " Image pushed to ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}"
else
echo " Failed to push image. Did you run 'prod-build' first?"
echo " Also make sure you're logged in with 'prod-login'"
return 1
fi
}
prod-build-push() {
local TAG="''${1:-latest}"
prod-build "$TAG" && prod-push "$TAG"
}
prod-login() {
echo "📝 Logging into Codeberg registry..."
podman login codeberg.org
}
echo "🚀 Dish Planner Development Environment" echo "🚀 Dish Planner Development Environment"
echo "=======================================" echo "======================================="
echo "PHP: $(php --version | head -n1)" echo "PHP: $(php --version | head -n1)"
@ -59,17 +98,18 @@ pkgs.mkShell {
echo "Podman: $(podman --version)" echo "Podman: $(podman --version)"
echo "Podman-compose: $(podman-compose --version 2>/dev/null || echo 'checking...')" echo "Podman-compose: $(podman-compose --version 2>/dev/null || echo 'checking...')"
echo "" echo ""
echo "Quick commands:" echo "Development commands:"
echo " rebuild - Full rebuild (removes volumes)" echo " rebuild - Full rebuild (removes volumes)"
echo " rebuild-quick - Quick rebuild (keeps volumes)" echo " rebuild-quick - Quick rebuild (keeps volumes)"
echo " logs [service] - Follow logs (default: all)" echo " logs [service] - Follow logs (default: all)"
echo " shell - Enter app container" echo " shell - Enter app container"
echo " artisan [cmd] - Run artisan commands" echo " artisan [cmd] - Run artisan commands"
echo "" echo ""
echo "Standard commands:" echo "Production commands:"
echo " podman-compose up -d - Start containers" echo " prod-login - Login to Codeberg registry"
echo " podman-compose down - Stop containers" echo " prod-build [tag] - Build production image (default: latest)"
echo " make dev - Start via Makefile" echo " prod-push [tag] - Push image to Codeberg"
echo " prod-build-push - Build and push in one command"
echo "" echo ""
# Auto-start prompt # Auto-start prompt