diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..9d46aca --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,84 @@ +# Multi-stage build for Laravel + React application +FROM node:20-alpine AS frontend-builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install Node dependencies +RUN npm ci --only=production + +# Copy frontend source +COPY resources/ resources/ +COPY public/ public/ +COPY vite.config.ts ./ +COPY tsconfig.json ./ +COPY components.json ./ +COPY eslint.config.js ./ + +# Build frontend assets +RUN npm run build + +# PHP runtime stage +FROM php:8.2-fpm-alpine + +# Install system dependencies +RUN apk add --no-cache \ + git \ + curl \ + libpng-dev \ + libxml2-dev \ + zip \ + unzip \ + oniguruma-dev \ + mysql-client + +# Install PHP extensions +RUN docker-php-ext-install \ + pdo_mysql \ + mbstring \ + exif \ + pcntl \ + bcmath \ + gd + +# Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Set working directory +WORKDIR /var/www/html + +# Copy application code first +COPY . . + +# Install PHP dependencies after copying all files +RUN composer install --no-dev --optimize-autoloader --no-interaction + +# Copy built frontend assets from builder stage +COPY --from=frontend-builder /app/public/build/ ./public/build/ + +# Set proper permissions +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html/storage \ + && chmod -R 755 /var/www/html/bootstrap/cache + +# Create a startup script +RUN echo '#!/bin/sh' > /usr/local/bin/start-app \ + && echo 'cp -r /var/www/html/public/. /var/www/html/public_shared/ 2>/dev/null || true' >> /usr/local/bin/start-app \ + && echo 'php artisan config:cache' >> /usr/local/bin/start-app \ + && echo 'php artisan route:cache' >> /usr/local/bin/start-app \ + && echo 'php artisan view:cache' >> /usr/local/bin/start-app \ + && echo 'php artisan migrate --force' >> /usr/local/bin/start-app \ + && echo 'php-fpm' >> /usr/local/bin/start-app \ + && chmod +x /usr/local/bin/start-app + +# Expose port 9000 for PHP-FPM +EXPOSE 9000 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD php artisan --version || exit 1 + +# Start the application +CMD ["/usr/local/bin/start-app"] \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..a133062 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,65 @@ +version: '3.8' + +services: + app: + image: codeberg.org/lvl0/incr:v0.1.0-alpha-1 + # build: + # context: ../ + # dockerfile: docker/Dockerfile + container_name: incr-app + 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=incr + - DB_USERNAME=incr_user + - DB_PASSWORD=incr_password + volumes: + - ../storage:/var/www/html/storage + - ../public:/var/www/html/public + depends_on: + - db + networks: + - incr-network + + db: + image: mysql:8.0 + container_name: incr-db + restart: unless-stopped + environment: + - MYSQL_DATABASE=incr + - MYSQL_USER=incr_user + - MYSQL_PASSWORD=incr_password + - MYSQL_ROOT_PASSWORD=root_password + volumes: + - db_data:/var/lib/mysql + ports: + - "3306:3306" + networks: + - incr-network + + nginx: + image: nginx:alpine + container_name: incr-nginx + restart: unless-stopped + ports: + - "80:80" + volumes: + - ../public:/var/www/html/public:ro + - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - app + networks: + - incr-network + +networks: + incr-network: + driver: bridge + +volumes: + db_data: + driver: local \ No newline at end of file diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..3877706 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,26 @@ +server { + listen 80; + server_name localhost; + root /var/www/html/public; + index index.php index.html; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass app:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } + + location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} \ No newline at end of file