From effe6bfae2810a57caf71355e64181a92a5529aa Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Sun, 18 May 2025 22:26:42 +0200 Subject: [PATCH 1/3] Laradock --- .gitmodules | 3 +++ laradock | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 laradock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..206a67b1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "laradock"] + path = laradock + url = https://github.com/Laradock/laradock.git diff --git a/laradock b/laradock new file mode 160000 index 00000000..f2b5954e --- /dev/null +++ b/laradock @@ -0,0 +1 @@ +Subproject commit f2b5954e762619cebb452cebb0f9dcb5bc859ffe From 8e3d08fd879416846de0c5963609fea532dc3a7b Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Sun, 18 May 2025 22:33:00 +0200 Subject: [PATCH 2/3] Laradock --- Dockerfile | 143 ++++++++++++++++++++++++-------------- docker-compose.render.yml | 57 +++++++++++++++ nginx.render.dockerfile | 27 +++++++ php-fpm.render.dockerfile | 34 +++++++++ supervisord.conf | 28 ++++++++ 5 files changed, 236 insertions(+), 53 deletions(-) create mode 100644 docker-compose.render.yml create mode 100644 nginx.render.dockerfile create mode 100644 php-fpm.render.dockerfile create mode 100644 supervisord.conf diff --git a/Dockerfile b/Dockerfile index 4a413379..8da14251 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,60 +1,97 @@ -# Stage 1: Compile Frontend Assets -FROM node:20-alpine AS node_builder - -WORKDIR /app/frontend - -# Copy package files and essential build configuration -COPY package.json package-lock.json* webpack.mix.js tailwind.config.js postcss.config.js* .babelrc* ./ -# Ensure postcss.config.js and .babelrc are optional by using * in case they don't exist - -# Install all dependencies (including devDependencies like laravel-mix) -RUN npm ci - -# Copy frontend source code (js, css, images, etc.) -COPY resources/js ./resources/js -COPY resources/css ./resources/css -COPY resources/img ./resources/img -# Add other relevant resource directories if needed - -# Compile assets for production -RUN npm run production - -# Stage 2: Setup PHP Application Environment using richarvey/nginx-php-fpm -FROM richarvey/nginx-php-fpm:3.1.6 AS app - -# Set Laravel Environment Variables as per the article -ENV APP_ENV production -ENV APP_DEBUG false -ENV LOG_CHANNEL stderr -ENV APP_KEY ${APP_KEY} -ENV SKIP_COMPOSER 1 -ENV WEBROOT /var/www/html/public -ENV PHP_ERRORS_STDERR 1 # Send PHP errors to stderr for Docker logging -ENV RUN_SCRIPTS 1 # Enable execution of scripts in /scripts directory -ENV REAL_IP_HEADER 1 # If behind a proxy, trust X-Forwarded-For -ENV COMPOSER_ALLOW_SUPERUSER 1 # Allow composer to run as root if needed by scripts - -# Set working directory +# Stage 1: Base with PHP, Composer, and common extensions +# We'll use an official PHP image as a base for PHP-FPM +FROM php:8.2-fpm-alpine AS php_base + +# Install system dependencies for PHP extensions and other tools +RUN apk add --no-cache \ + bash \ + curl \ + git \ + supervisor \ + nginx \ + # For common PHP extensions + libzip-dev \ + libpng-dev \ + libjpeg-turbo-dev \ + freetype-dev \ + icu-dev \ + libxml2-dev \ + # For pdo_mysql + mysql-client + +# Install PHP extensions +# You can customize this list based on Laradock's PHP-FPM Dockerfile or your app's needs +RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j$(nproc) \ + gd \ + intl \ + opcache \ + pdo_mysql \ + zip \ + xml \ + bcmath \ + pcntl \ + exif \ + sockets + +# Get latest Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Set working directory for the application WORKDIR /var/www/html -# Copy all application files +# Copy application code COPY . . -# Copy compiled assets from the node_builder stage -COPY --from=node_builder /app/frontend/public ./public +# Install Composer dependencies +RUN composer install --no-dev --no-interaction --no-progress --optimize-autoloader + +# Optimize Laravel (optional here, can also be done at runtime start, but better in image) +RUN php artisan config:cache +RUN php artisan route:cache +# RUN php artisan view:cache # view:cache can sometimes be problematic if paths change + +# Fix permissions for storage and bootstrap cache +RUN chown -R www-data:www-data storage bootstrap/cache public \ + && chmod -R 775 storage bootstrap/cache public + +# Stage 2: Final image with Nginx and Supervisor +FROM alpine:latest -# Copy our Nginx site configuration to the standard location for richarvey images -COPY nginx-site.conf /etc/nginx/sites-available/default +# Copy PHP-FPM and application from the php_base stage +COPY --from=php_base /usr/local/etc/php-fpm.d/ /usr/local/etc/php-fpm.d/ +COPY --from=php_base /usr/local/etc/php/ /usr/local/etc/php/ +COPY --from=php_base /usr/local/sbin/php-fpm /usr/local/sbin/php-fpm +COPY --from=php_base /usr/local/bin/php /usr/local/bin/php +COPY --from=php_base /usr/bin/composer /usr/bin/composer +COPY --from=php_base /var/www/html /var/www/html +COPY --from=php_base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Install Nginx and Supervisor from Alpine packages (if not already in php_base or if we want a clean stage) +RUN apk add --no-cache nginx supervisor mysql-client bash + +# Create Nginx log directory if it doesn't exist from package install +RUN mkdir -p /var/log/nginx && \ + chown -R nginx:nginx /var/log/nginx && \ + mkdir -p /var/lib/nginx && \ + chown -R nginx:nginx /var/lib/nginx && \ + # Create run directory for php-fpm and nginx pid + mkdir -p /run/php && \ + mkdir -p /run/nginx + +# Copy Nginx configuration +# We will create these files next: nginx.conf and supervisord.conf +COPY nginx-prod.conf /etc/nginx/nginx.conf +COPY laravel-site.conf /etc/nginx/http.d/default.conf + +# Copy Supervisor configuration +COPY supervisord.conf /etc/supervisord.conf + +# Application root +WORKDIR /var/www/html -# Copy our deploy script to the location where richarvey image expects to run scripts -# Ensure deploy.sh has necessary commands (composer install, migrations, cache) -RUN mkdir -p /scripts -COPY deploy.sh /scripts/00-laravel-deploy.sh -# Install dos2unix, convert line endings, and ensure the script is executable -RUN apk add --no-cache dos2unix && \ - dos2unix /scripts/00-laravel-deploy.sh && \ - chmod +x /scripts/00-laravel-deploy.sh +# Expose port 80 for Nginx +EXPOSE 80 -# The base image (richarvey/nginx-php-fpm) handles starting Nginx, PHP-FPM, -# and running scripts from /scripts. Its default CMD is /start.sh. -CMD ["/start.sh"] +# Start Supervisor +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] diff --git a/docker-compose.render.yml b/docker-compose.render.yml new file mode 100644 index 00000000..7f98e5c1 --- /dev/null +++ b/docker-compose.render.yml @@ -0,0 +1,57 @@ +version: '3.8' + +services: + php-fpm: + build: + context: . # We'll build from the project root + dockerfile: php-fpm.render.dockerfile # A dedicated Dockerfile for this service + args: + # Example: Use PHP_VERSION from Laradock's .env or set a default + # This can be overridden by Render environment variables if needed + LARADOCK_PHP_VERSION: ${PHP_VERSION:-8.2} # Defaulting to 8.2 as in previous Dockerfile + volumes: + # Mount Render's persistent disk for Laravel storage + # The name 'laravel-storage' should match the disk name in render.yaml + - laravel-storage:/var/www/html/storage + # Environment variables will be injected by Render from render.yaml + # working_dir is typically /var/www/html (set in php-fpm.render.dockerfile) + + nginx: + build: + context: ./laradock/nginx # Use Laradock's Nginx Dockerfile + args: + # Environment variables from Laradock's .env can be passed as build args if needed + # For example, if Laradock's Nginx Dockerfile uses them. + # Common ones are already handled by Laradock's Nginx entrypoint/config. + PHP_UPSTREAM_CONTAINER: php-fpm # Ensure it points to our php-fpm service + PHP_UPSTREAM_PORT: 9000 + NGINX_HOST_LOG_PATH: /var/log/nginx # Standard log path + # Ensure NGINX_SITES_PATH points where Laradock's Dockerfile expects to find site configs + # NGINX_SITES_PATH: /etc/nginx/sites-available # Default in Laradock .env + volumes: + # The application code (especially /public) needs to be accessible by Nginx. + # Our php-fpm service builds the code into /var/www/html. + # We need to share this with Nginx. + # The 'app_code' volume is defined below and should be populated by the php-fpm service. + # However, for Render, it's often better if the Nginx image also has the static assets. + # Laradock's Nginx Dockerfile usually copies from APP_CODE_PATH_HOST. + # Let's ensure our php-fpm service populates the app_code volume, + # and nginx mounts it. + # Alternatively, nginx Dockerfile could also COPY ../public /var/www/html/public + - app_code:/var/www/html + ports: + - "80:80" + depends_on: + - php-fpm + # Environment variables from render.yaml will be available. + # Laradock's Nginx often uses NGINX_APP_CODE_PATH_CONTAINER=/var/www/html + # and expects the site config to set root to $NGINX_APP_CODE_PATH_CONTAINER/public + environment: + NGINX_APP_CODE_PATH_CONTAINER: /var/www/html # To align with Laradock's Nginx config expectations + # Other NGINX_... variables from laradock/.env can be set here if needed by the entrypoint + +volumes: + laravel-storage: # This name must match the disk name in render.yaml + driver: local # For local testing; Render handles this differently + app_code: # Volume to share application code if needed, populated by php-fpm build + driver: local diff --git a/nginx.render.dockerfile b/nginx.render.dockerfile new file mode 100644 index 00000000..86e87940 --- /dev/null +++ b/nginx.render.dockerfile @@ -0,0 +1,27 @@ +# nginx.render.dockerfile +# Use Laradock's Nginx image as a base +FROM laradock/nginx:latest + +# Application code is expected to be in /var/www/html +# Nginx needs access to the public directory. +# We'll copy the application's public directory. +# Note: The php-fpm container builds the full app. For Nginx, we primarily need static assets. +# If your app has a build step for frontend assets that places them in public/, +# ensure that step is run before this Dockerfile builds or that the assets are copied. +# The php-fpm.render.dockerfile already copies the whole app, so assets should be there. + +WORKDIR /var/www/html + +# Copy only the public directory from the application source for Nginx to serve static files. +# The rest of the app (PHP files) will be handled by PHP-FPM. +# This assumes the build context for docker-compose is the project root. +COPY public ./public + +# Copy custom Nginx site configuration for the Laravel application +# We will create 'laravel.render.conf' next. +COPY laravel.render.conf /etc/nginx/sites-available/default.conf + +# Expose port 80 (already exposed by base image, but good for clarity) +EXPOSE 80 + +# CMD is inherited from laradock/nginx, which starts nginx. diff --git a/php-fpm.render.dockerfile b/php-fpm.render.dockerfile new file mode 100644 index 00000000..93c8e341 --- /dev/null +++ b/php-fpm.render.dockerfile @@ -0,0 +1,34 @@ +# php-fpm.render.dockerfile +ARG LARADOCK_PHP_VERSION=8.2 +FROM laradock/php-fpm:${LARADOCK_PHP_VERSION} + +# Set working directory +WORKDIR /var/www/html + +# Install pdo_mysql if not present by default in this specific Laradock base +# (Laradock's build process for php-fpm usually includes common extensions based on its .env) +# For a production image, ensure all necessary extensions are explicitly built or verified. +# Example: RUN docker-php-ext-install pdo_mysql zip bcmath pcntl exif sockets ... + +# Copy application code from the build context (project root) +COPY . . + +# Install Composer dependencies +# Composer should be available in the laradock/php-fpm base image. +RUN composer install --no-dev --no-interaction --no-progress --optimize-autoloader + +# Run Laravel optimizations +RUN php artisan config:cache && \ + php artisan route:cache && \ + php artisan view:cache + +# Ensure storage, bootstrap/cache, and public directories are writable by www-data +# Adjust ownership/permissions as necessary for your application's needs. +# The user for php-fpm is typically www-data. +RUN chown -R www-data:www-data storage bootstrap/cache public && \ + chmod -R 775 storage bootstrap/cache public + +# Expose port 9000 for PHP-FPM (already exposed by base image, but good for clarity) +EXPOSE 9000 + +# The CMD is inherited from laradock/php-fpm, which starts php-fpm. diff --git a/supervisord.conf b/supervisord.conf new file mode 100644 index 00000000..efb9de7a --- /dev/null +++ b/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +nodaemon=true +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid +loglevel=info + +[program:php-fpm] +command=/usr/local/sbin/php-fpm -F --pid /run/php/php-fpm.pid +autostart=true +autorestart=true +priority=5 +stdout_logfile=/var/log/supervisor/php-fpm.log +stderr_logfile=/var/log/supervisor/php-fpm.error.log +stdout_logfile_maxbytes=0 ; Set to 0 to disable rotation, or specify size like 10MB +stderr_logfile_maxbytes=0 + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +autostart=true +autorestart=true +priority=10 +stdout_logfile=/var/log/supervisor/nginx.log +stderr_logfile=/var/log/supervisor/nginx.error.log +stdout_logfile_maxbytes=0 +stderr_logfile_maxbytes=0 + +[include] +files = /etc/supervisor/conf.d/*.conf From 553a5662b13adcc2881238d91a23eec9044a39b0 Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Sun, 18 May 2025 22:35:43 +0200 Subject: [PATCH 3/3] Update render.yaml --- render.yaml | 95 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/render.yaml b/render.yaml index 76775e1b..47133d2d 100644 --- a/render.yaml +++ b/render.yaml @@ -13,57 +13,54 @@ databases: # For MySQL, version is typically tied to the plan or a default. services: - - type: web # Must be one of "web", "worker", "pserv", "cron" for serverService - name: laravel-vue-ecommerce - runtime: docker # Valid runtime for serverService - autoDeploy: false # Boolean value - healthCheckPath: /api/health # For web services - # image: # Define if image is pre-built and pushed to a registry - # url: registry.render.com/YOUR_RENDER_ORG_OR_USER/laravel-vue-ecommerce:latest + # PHP-FPM Service (Private Service) + - type: pserv + name: php-fpm # Internal service name + runtime: docker # Added runtime + dockerContext: . # Build from project root + dockerfilePath: ./php-fpm.render.dockerfile # Using the Dockerfile we created envVars: - key: APP_NAME value: "Laravel Vue Ecommerce" - key: APP_ENV value: "production" - key: APP_DEBUG - value: "false" # Env vars are strings + value: "false" - key: APP_URL - value: "${RENDER_EXTERNAL_URL}" # Render injects this + value: "${RENDER_EXTERNAL_URL}" # Will be taken from the web service - key: ASSET_URL - value: "${RENDER_EXTERNAL_URL}" # Render injects this + value: "${RENDER_EXTERNAL_URL}" # Will be taken from the web service - key: APP_KEY - generateValue: true # Valid per envVarFromKeyValue schema + fromService: + type: web + name: laravel-vue-ecommerce # Name of the Nginx web service + envVarKey: APP_KEY_GENERATED # Use a different key to avoid circular dependency if APP_KEY is also on web - key: LOG_CHANNEL value: "stderr" - # Database Connection - - key: DB_CONNECTION # Tells Laravel to use the mysql driver + - key: DB_CONNECTION value: "mysql" - - key: DATABASE_URL # Laravel will parse this if DB_CONNECTION is set - fromDatabase: # Valid per envVarFromDatabase schema - name: ecommerce-db # Must match the name in the top-level 'databases' section - property: connectionString # Provides the full database connection URL - # Cache and Session + - key: DATABASE_URL + fromDatabase: + name: ecommerce-db + property: connectionString - key: CACHE_DRIVER - value: "file" + value: "file" # Consider 'redis' if you add a Redis service - key: SESSION_DRIVER - value: "file" - # Stripe Keys (Set these as secrets in Render dashboard) + value: "file" # Consider 'redis' - key: STRIPE_KEY - sync: false # Valid per envVarFromKeyValue schema + sync: false - key: STRIPE_SECRET sync: false - key: STRIPE_WEBHOOK_SECRET sync: false - # Cashier Settings - key: CASHIER_CURRENCY value: "NOK" - key: CASHIER_CURRENCY_LOCALE value: "nb-NO" - # Mailer Configuration (example, adjust as needed) - key: MAIL_MAILER value: "smtp" - key: MAIL_HOST - value: "your_mail_host" # Set as secret or actual value + value: "your_mail_host" - key: MAIL_PORT value: "587" - key: MAIL_USERNAME @@ -76,14 +73,44 @@ services: value: "hello@example.com" - key: MAIL_FROM_NAME value: "${APP_NAME}" + # For Laradock PHP_VERSION in php-fpm.render.dockerfile build arg + - key: PHP_VERSION + value: "8.2" # Or from laradock/.env if possible, but direct is safer for Render + disk: + name: laravel-storage + mountPath: /var/www/html/storage # Mount point for Laravel's storage + sizeGB: 1 # sizeGB defined directly here - # Start command: The Docker image's CMD ["/start.sh"] will be used by default. - # The /start.sh script from richarvey/nginx-php-fpm will execute our /scripts/00-laravel-deploy.sh - # (because ENV RUN_SCRIPTS 1 is set) and then start Nginx & PHP-FPM. - # Thus, no explicit startCommand override is needed here. + # Nginx Service (Web Service) + - type: web + name: laravel-vue-ecommerce # Public-facing service name + runtime: docker # Added runtime + dockerContext: ./laradock/nginx # Build using Laradock's Nginx Dockerfile + # dockerfilePath is implicitly Dockerfile within the context + autoDeploy: false + healthCheckPath: / # Or a static file like /favicon.ico, or /api/health if Nginx proxies it + envVars: + - key: APP_NAME # For consistency, though Nginx might not use it directly + value: "Laravel Vue Ecommerce" + - key: APP_ENV + value: "production" + - key: APP_URL + value: "${RENDER_EXTERNAL_URL}" + - key: ASSET_URL + value: "${RENDER_EXTERNAL_URL}" + - key: APP_KEY_GENERATED # Nginx service generates the APP_KEY + generateValue: true + # Environment variables for Laradock's Nginx entrypoint/configuration + - key: NGINX_PHP_UPSTREAM_CONTAINER + value: "php-fpm" # Must match the name of the php-fpm service above + - key: NGINX_PHP_UPSTREAM_PORT + value: "9000" + - key: NGINX_APP_CODE_PATH_CONTAINER + value: "/var/www/html" # Used by laradock/nginx/sites/default.conf + # For Laradock PHP_VERSION in its Nginx Dockerfile build args (if it uses it) + - key: PHP_VERSION + value: "8.2" + # Nginx service does not directly write to Laravel's storage, + # but it needs the application code (public assets) which is built into its image. - # Persistent disk for Laravel storage - disk: # Valid per serverService schema, referencing "disk" definition - name: laravel-storage # Name for the persistent disk - mountPath: /var/www/html/storage # Mount path inside the container - sizeGB: 1 # Size of the disk in GB, integer +# Top-level disks: block removed as it's not allowed by schema; disk defined in php-fpm service.