Fix prod scripts
This commit is contained in:
parent
9d6e20b4f1
commit
1e70525f73
5 changed files with 89 additions and 111 deletions
|
|
@ -3,17 +3,14 @@ FROM node:22-alpine AS frontend-builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files
|
# Copy frontend package files
|
||||||
COPY package*.json ./
|
COPY frontend/package*.json ./
|
||||||
|
|
||||||
# Install Node dependencies
|
# Install Node dependencies
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
# Copy frontend source
|
# Copy frontend source
|
||||||
COPY resources/ resources/
|
COPY frontend/ ./
|
||||||
COPY public/ public/
|
|
||||||
COPY vite.config.js ./
|
|
||||||
COPY tsconfig.json ./
|
|
||||||
|
|
||||||
# Build frontend assets
|
# Build frontend assets
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
@ -55,14 +52,18 @@ COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
# Copy application code first
|
# Copy application code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Install PHP dependencies after copying all files
|
# Install PHP dependencies in backend directory
|
||||||
|
WORKDIR /var/www/html/backend
|
||||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||||
|
|
||||||
# Copy built frontend assets from builder stage
|
# Copy built frontend assets from builder stage to frontend dist
|
||||||
COPY --from=frontend-builder /app/public/build/ ./public/build/
|
COPY --from=frontend-builder /app/dist/ /var/www/html/frontend/dist/
|
||||||
|
|
||||||
|
# Back to main directory
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
# Copy nginx and supervisor configurations
|
# Copy nginx and supervisor configurations
|
||||||
COPY docker/production/nginx.conf /etc/nginx/http.d/default.conf
|
COPY docker/production/nginx.conf /etc/nginx/http.d/default.conf
|
||||||
|
|
@ -70,8 +71,9 @@ COPY docker/production/supervisord.conf /etc/supervisord.conf
|
||||||
COPY docker/production/start-app.sh /usr/local/bin/start-app
|
COPY docker/production/start-app.sh /usr/local/bin/start-app
|
||||||
|
|
||||||
# Set proper permissions
|
# Set proper permissions
|
||||||
RUN chown -R www-data:www-data storage bootstrap/cache public/build \
|
RUN chown -R www-data:www-data /var/www/html \
|
||||||
&& chmod -R 755 storage bootstrap/cache \
|
&& chmod -R 755 /var/www/html/backend/storage \
|
||||||
|
&& chmod -R 755 /var/www/html/backend/bootstrap/cache \
|
||||||
&& chmod +x /usr/local/bin/start-app
|
&& chmod +x /usr/local/bin/start-app
|
||||||
|
|
||||||
# Expose port 80 for nginx
|
# Expose port 80 for nginx
|
||||||
|
|
@ -79,7 +81,7 @@ EXPOSE 80
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
CMD php artisan --version || exit 1
|
CMD cd /var/www/html/backend && php artisan --version || exit 1
|
||||||
|
|
||||||
# Start the application
|
# Start the application
|
||||||
CMD ["/usr/local/bin/start-app"]
|
CMD ["/usr/local/bin/start-app"]
|
||||||
|
|
@ -1,27 +1,26 @@
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: codeberg.org/lvl0/ffr:latest
|
image: codeberg.org/lvl0/ffr:v1.0.0-rc1
|
||||||
# build:
|
|
||||||
# context: ../..
|
|
||||||
# dockerfile: docker/production/Dockerfile
|
|
||||||
container_name: ffr-app
|
container_name: ffr-app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
working_dir: /var/www/html
|
|
||||||
environment:
|
environment:
|
||||||
- APP_ENV=production
|
- APP_ENV=production
|
||||||
- APP_DEBUG=false
|
- APP_DEBUG=false
|
||||||
|
- APP_KEY=${APP_KEY}
|
||||||
|
- APP_URL=${APP_URL}
|
||||||
- DB_CONNECTION=mysql
|
- DB_CONNECTION=mysql
|
||||||
- DB_HOST=db
|
- DB_HOST=db
|
||||||
- DB_PORT=3306
|
- DB_PORT=3306
|
||||||
- DB_DATABASE=ffr
|
- DB_DATABASE=ffr
|
||||||
- DB_USERNAME=ffr_user
|
- DB_USERNAME=ffr_user
|
||||||
- DB_PASSWORD=ffr_password
|
- DB_PASSWORD=${DB_PASSWORD}
|
||||||
- REDIS_HOST=redis
|
- REDIS_HOST=redis
|
||||||
- REDIS_PORT=6379
|
- REDIS_PORT=6379
|
||||||
- CACHE_DRIVER=redis
|
- CACHE_DRIVER=redis
|
||||||
- SESSION_DRIVER=redis
|
- SESSION_DRIVER=redis
|
||||||
- QUEUE_CONNECTION=redis
|
- QUEUE_CONNECTION=redis
|
||||||
volumes: []
|
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
||||||
|
- TELEGRAM_CHANNEL_ID=${TELEGRAM_CHANNEL_ID}
|
||||||
ports:
|
ports:
|
||||||
- "8000:80"
|
- "8000:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -32,62 +31,6 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- ffr-network
|
- ffr-network
|
||||||
|
|
||||||
queue:
|
|
||||||
image: codeberg.org/lvl0/ffr:latest
|
|
||||||
container_name: ffr-queue
|
|
||||||
restart: unless-stopped
|
|
||||||
working_dir: /var/www/html
|
|
||||||
environment:
|
|
||||||
- APP_ENV=production
|
|
||||||
- APP_DEBUG=false
|
|
||||||
- DB_CONNECTION=mysql
|
|
||||||
- DB_HOST=db
|
|
||||||
- DB_PORT=3306
|
|
||||||
- DB_DATABASE=ffr
|
|
||||||
- DB_USERNAME=ffr_user
|
|
||||||
- DB_PASSWORD=ffr_password
|
|
||||||
- REDIS_HOST=redis
|
|
||||||
- REDIS_PORT=6379
|
|
||||||
- CACHE_DRIVER=redis
|
|
||||||
- SESSION_DRIVER=redis
|
|
||||||
- QUEUE_CONNECTION=redis
|
|
||||||
command: ["php", "artisan", "horizon"]
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
networks:
|
|
||||||
- ffr-network
|
|
||||||
|
|
||||||
scheduler:
|
|
||||||
image: codeberg.org/lvl0/ffr:latest
|
|
||||||
container_name: ffr-scheduler
|
|
||||||
restart: unless-stopped
|
|
||||||
working_dir: /var/www/html
|
|
||||||
environment:
|
|
||||||
- APP_ENV=production
|
|
||||||
- APP_DEBUG=false
|
|
||||||
- DB_CONNECTION=mysql
|
|
||||||
- DB_HOST=db
|
|
||||||
- DB_PORT=3306
|
|
||||||
- DB_DATABASE=ffr
|
|
||||||
- DB_USERNAME=ffr_user
|
|
||||||
- DB_PASSWORD=ffr_password
|
|
||||||
- REDIS_HOST=redis
|
|
||||||
- REDIS_PORT=6379
|
|
||||||
- CACHE_DRIVER=redis
|
|
||||||
- SESSION_DRIVER=redis
|
|
||||||
- QUEUE_CONNECTION=redis
|
|
||||||
command: ["sh", "-c", "while true; do php artisan schedule:run --verbose --no-interaction; sleep 60; done"]
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
networks:
|
|
||||||
- ffr-network
|
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/mysql:8.4
|
image: docker.io/library/mysql:8.4
|
||||||
container_name: ffr-db
|
container_name: ffr-db
|
||||||
|
|
@ -95,14 +38,12 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_DATABASE=ffr
|
- MYSQL_DATABASE=ffr
|
||||||
- MYSQL_USER=ffr_user
|
- MYSQL_USER=ffr_user
|
||||||
- MYSQL_PASSWORD=ffr_password
|
- MYSQL_PASSWORD=${DB_PASSWORD}
|
||||||
- MYSQL_ROOT_PASSWORD=root_password
|
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
ports:
|
|
||||||
- "3306:3306"
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "ffr_user", "-pffr_password"]
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "ffr_user", "-p${DB_PASSWORD}"]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
interval: 3s
|
interval: 3s
|
||||||
|
|
@ -127,4 +68,4 @@ volumes:
|
||||||
db_data:
|
db_data:
|
||||||
driver: local
|
driver: local
|
||||||
redis_data:
|
redis_data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,19 @@
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
root /var/www/html/public;
|
|
||||||
index index.php index.html;
|
# Serve static React build files
|
||||||
|
root /var/www/html/frontend/dist;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
# Security headers
|
# API requests to Laravel backend
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
location /api/ {
|
||||||
add_header X-Content-Type-Options "nosniff";
|
root /var/www/html/backend/public;
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
try_files /index.php =404;
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
fastcgi_pass 127.0.0.1:9000;
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME /var/www/html/backend/public/index.php;
|
||||||
include fastcgi_params;
|
include fastcgi_params;
|
||||||
|
|
||||||
# Increase timeouts for long-running requests
|
# Increase timeouts for long-running requests
|
||||||
|
|
@ -24,6 +21,30 @@ server {
|
||||||
fastcgi_send_timeout 300;
|
fastcgi_send_timeout 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Serve Laravel public assets (images, etc.)
|
||||||
|
location /images/ {
|
||||||
|
alias /var/www/html/backend/public/images/;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# React app - catch all routes
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets with far-future expiry
|
||||||
|
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
|
add_header X-Content-Type-Options "nosniff";
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
|
||||||
# Deny access to hidden files
|
# Deny access to hidden files
|
||||||
location ~ /\.ht {
|
location ~ /\.ht {
|
||||||
deny all;
|
deny all;
|
||||||
|
|
@ -34,14 +55,6 @@ server {
|
||||||
deny all;
|
deny all;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Static assets with far-future expiry
|
|
||||||
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Laravel specific optimizations
|
|
||||||
location = /favicon.ico {
|
location = /favicon.ico {
|
||||||
access_log off;
|
access_log off;
|
||||||
log_not_found off;
|
log_not_found off;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Create .env file if it doesn't exist
|
# Create .env file if it doesn't exist
|
||||||
if [ ! -f /var/www/html/.env ]; then
|
if [ ! -f /var/www/html/backend/.env ]; then
|
||||||
cp /var/www/html/.env.example /var/www/html/.env 2>/dev/null || touch /var/www/html/.env
|
cp /var/www/html/backend/.env.example /var/www/html/backend/.env 2>/dev/null || touch /var/www/html/backend/.env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Wait for database to be ready
|
# Wait for database to be ready
|
||||||
|
|
@ -14,21 +14,23 @@ done
|
||||||
echo "Database connection established!"
|
echo "Database connection established!"
|
||||||
|
|
||||||
# Generate app key if not set
|
# Generate app key if not set
|
||||||
if ! grep -q "APP_KEY=base64:" /var/www/html/.env; then
|
if ! grep -q "APP_KEY=base64:" /var/www/html/backend/.env; then
|
||||||
php artisan key:generate --force
|
cd /var/www/html/backend && php artisan key:generate --force
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Laravel optimizations for production
|
# Laravel optimizations for production
|
||||||
|
cd /var/www/html/backend
|
||||||
php artisan config:cache
|
php artisan config:cache
|
||||||
php artisan route:cache
|
php artisan route:cache
|
||||||
php artisan view:cache
|
php artisan view:cache
|
||||||
|
|
||||||
# Run migrations
|
# Run migrations
|
||||||
|
cd /var/www/html/backend
|
||||||
php artisan migrate --force
|
php artisan migrate --force
|
||||||
|
|
||||||
# Run seeders (only if needed for production data)
|
# Run all seeders (same as dev)
|
||||||
php artisan db:seed --force --class=PlatformInstanceSeeder
|
cd /var/www/html/backend
|
||||||
php artisan db:seed --force --class=SettingsSeeder
|
php artisan db:seed --force
|
||||||
|
|
||||||
# Start supervisor to manage nginx and php-fpm
|
# Start supervisor to manage nginx and php-fpm
|
||||||
supervisord -c /etc/supervisord.conf
|
supervisord -c /etc/supervisord.conf
|
||||||
|
|
@ -22,4 +22,24 @@ stdout_logfile=/dev/stdout
|
||||||
stdout_logfile_maxbytes=0
|
stdout_logfile_maxbytes=0
|
||||||
stderr_logfile=/dev/stderr
|
stderr_logfile=/dev/stderr
|
||||||
stderr_logfile_maxbytes=0
|
stderr_logfile_maxbytes=0
|
||||||
priority=10
|
priority=10
|
||||||
|
|
||||||
|
[program:horizon]
|
||||||
|
command=php /var/www/html/backend/artisan horizon
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
priority=20
|
||||||
|
|
||||||
|
[program:scheduler]
|
||||||
|
command=sh -c "while true; do php /var/www/html/backend/artisan schedule:run --verbose --no-interaction; sleep 60; done"
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
priority=20
|
||||||
Loading…
Reference in a new issue