Skip to content

Instantly share code, notes, and snippets.

@devhammed
Last active November 14, 2025 12:40
Show Gist options
  • Select an option

  • Save devhammed/bfe64d563176396955f60190bf795044 to your computer and use it in GitHub Desktop.

Select an option

Save devhammed/bfe64d563176396955f60190bf795044 to your computer and use it in GitHub Desktop.
Laravel Docker Setup (NGINX, PHP-FPM, Queue Worker, Scheduler, Reverb)
# Stage 1: Build
FROM php:8.4-cli AS build
# Setup build root
WORKDIR /app
# Install dependencies
RUN apt-get update && apt-get install -y \
git \
unzip \
zip \
curl \
&& curl -fsSL https://deb.nodesource.com/setup_23.x | bash - \
&& apt-get install -y nodejs \
&& npm install -g npm \
&& rm -rf /var/lib/apt/lists/*
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Copy Composer files
COPY composer.json composer.lock ./
# Install Composer dependencies
RUN composer install --prefer-dist --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --optimize-autoloader --ignore-platform-reqs \
&& composer clear-cache
# Copy app source
COPY . .
# Dump autoload
RUN composer dump-autoload --optimize
# Set Vite environment variables
ARG VITE_APP_NAME
ENV VITE_APP_NAME=$VITE_APP_NAME
ARG VITE_APP_URL
ENV VITE_APP_URL=$VITE_APP_URL
ARG VITE_BROADCAST_CONNECTION
ENV VITE_BROADCAST_CONNECTION=$VITE_BROADCAST_CONNECTION
ARG VITE_REVERB_APP_KEY
ENV VITE_REVERB_APP_KEY=$VITE_REVERB_APP_KEY
ARG VITE_REVERB_HOST
ENV VITE_REVERB_HOST=$VITE_REVERB_HOST
ARG VITE_REVERB_PORT
ENV VITE_REVERB_PORT=$VITE_REVERB_PORT
ARG VITE_REVERB_SCHEME
ENV VITE_REVERB_SCHEME=$VITE_REVERB_SCHEME
# Build frontend assets
RUN npm ci \
&& npm run build \
&& rm -rf node_modules
# Stage 2: Runtime
FROM php:8.4-fpm
# Install dependencies
RUN apt-get update && apt-get install -y \
git unzip libpq-dev libpng-dev libonig-dev libxml2-dev libicu-dev libuv1-dev \
curl supervisor nginx \
&& docker-php-ext-install pdo_pgsql mbstring bcmath pcntl gd exif intl \
&& pecl install redis \
&& pecl install uv-beta \
&& docker-php-ext-enable redis uv \
&& rm -rf /var/lib/apt/lists/*
# Setup application root
WORKDIR /var/www/html
# Copy application
COPY --from=build /app ./
# Copy configs
COPY .docker/nginx.conf /etc/nginx/nginx.conf
COPY .docker/php.ini /usr/local/etc/php/conf.d/user-php.ini
COPY .docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY .docker/run.sh /usr/local/bin/run.sh
# Setup storage and permissions
RUN php artisan storage:link \
&& chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache \
&& chmod +x /usr/local/bin/run.sh
# Expose NGINX
EXPOSE 80
# Start container
ENTRYPOINT ["/usr/local/bin/run.sh"]
user www-data;
worker_processes auto;
pid /run/nginx.pid;
worker_rlimit_nofile 50000;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 50000;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
access_log /dev/stdout;
error_log /dev/stderr;
server {
listen 80;
index index.php;
root /var/www/html/public;
charset utf-8;
client_max_body_size 200M;
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# START REVERB
location /app/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /apps/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
# END REVERB
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
}
upload_max_filesize = 30M
post_max_size = 60M
memory_limit = 512M
max_execution_time = 60
#!/bin/bash
# Exit on error
set -eux
# Run database migrations
php artisan migrate --force
# Clear Laravel caches
php artisan optimize:clear
# Rebuild Laravel caches
php artisan optimize
# Start supervisor
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
[supervisord]
nodaemon=true
minfds=50000
user=root
[program:php-fpm]
command=php-fpm -F
autostart=true
autorestart=true
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:nginx]
command=nginx -g "daemon off;"
autostart=true
autorestart=true
priority=10
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:queue-worker]
command=php artisan queue:work --sleep=3 --tries=3 --max-time=3600
directory=/var/www/html
user=www-data
autostart=true
autorestart=true
priority=15
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:scheduler]
command=php artisan schedule:work --run-output-file=/dev/stdout
directory=/var/www/html
user=www-data
autostart=true
autorestart=true
priority=15
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:reverb]
command=php artisan reverb:start --host=127.0.0.1 --port=8080
directory=/var/www/html
user=www-data
autostart=true
autorestart=true
priority=15
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment