PatoLab ships with a production-readyDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/lerichardv/patolab-platform/llms.txt
Use this file to discover all available pages before exploring further.
dockerfile that packages the Laravel application, Nginx, PHP-FPM, and Chromium into a single self-contained image. The container runs Nginx and PHP-FPM concurrently under Supervisor, exposes the application on port 8080, and includes the Node.js toolchain and Chromium binary needed for PDF invoice generation via Spatie Browsershot. Frontend assets are compiled during the image build so the final container has no runtime dependency on Node or npm.
Dockerfile Overview
The build uses a single-stage image based onphp:8.3-fpm:
System packages installed
The following system packages are installed at build time:- nginx — reverse proxy / web server
- supervisor — process manager that keeps Nginx and PHP-FPM alive
- chromium — headless browser for Browsershot PDF generation
- nodejs / npm — required to compile React/TypeScript frontend assets during the build
- git, unzip, curl, zip — general-purpose utilities used during dependency installation
- PHP extension dependencies:
libzip-dev,libpng-dev,libjpeg62-turbo-dev,libfreetype6-dev,libonig-dev
PHP extensions installed
Build steps summary
| Stage | What happens |
|---|---|
| System install | apt-get installs Nginx, Supervisor, Chromium, Node.js, and PHP extension libs |
| PHP extensions | docker-php-ext-install compiles pdo pdo_mysql mbstring bcmath gd zip opcache |
| Composer install | composer install --no-dev --optimize-autoloader with a dependency-cache layer |
| npm install | npm ci with a dependency-cache layer |
| Application copy | Full source is copied into /app |
| Storage setup | storage/ and bootstrap/cache/ directories are created and chowned to www-data |
| Autoload dump | composer dump-autoload --no-dev --optimize re-generates the classmap after the full source copy |
| Asset build | php artisan storage:link, php artisan wayfinder:generate --with-form, then npm run build compile the React bundle |
| Nginx config | Inline RUN echo writes the virtual-host config to /etc/nginx/sites-available/default |
| Supervisor config | Inline RUN echo writes the php-fpm + nginx process definitions |
Working directory and exposed port
Process manager (CMD)
The container entrypoint fixes runtime permissions, then hands off to Supervisor:| Program | Command |
|---|---|
php-fpm | php-fpm |
nginx | nginx -g "daemon off;" |
autorestart=true and write their logs to stdout/stderr so they appear in docker logs.
Required Environment Variables
Pass these variables to the container via--env flags or a --env-file:
Application
| Variable | Required | Example value |
|---|---|---|
APP_KEY | ✅ | base64:... (generate with php artisan key:generate --show) |
APP_URL | ✅ | https://patolab.example.com |
APP_ENV | ✅ | production |
APP_DEBUG | ✅ | false |
Database
| Variable | Required | Example value |
|---|---|---|
DB_CONNECTION | ✅ | mysql or pgsql |
DB_HOST | ✅ | db (service name) or IP address |
DB_PORT | ✅ | 3306 (MySQL) / 5432 (PostgreSQL) |
DB_DATABASE | ✅ | patolab |
DB_USERNAME | ✅ | patolab_user |
DB_PASSWORD | ✅ | strongpassword |
Queue and PDF
| Variable | Required | Example value |
|---|---|---|
QUEUE_CONNECTION | ✅ | database |
BROWSERSHOT_CHROME_PATH | ✅ | /usr/bin/chromium |
PUPPETEER_EXECUTABLE_PATH | Recommended | /usr/bin/chromium |
The Dockerfile pre-sets
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium as a build-time ENV. Passing it at runtime overrides the build-time value if Chromium lives in a different path on your base image.Storage Volume Mount
The Laravelstorage/ directory holds uploaded files, generated PDFs, compiled views, and session data. Mount it as a persistent named volume so data survives container restarts and upgrades:
docker run Example
Collaboration Server
The real-time collaborative report editor runs as a separate Node.js WebSocket server (editor-collaboration-server/) on port 1234. This process is not included in the main container’s Supervisor configuration.
You have two options:
Option A — separate container (recommended)
Option A — separate container (recommended)
Run the collaboration server as its own service alongside the main app container:Below is a sample Set the env var on the main app container so the frontend knows where to connect:
docker-compose.yml snippet showing how you might define both services (there is no docker-compose.yml committed to the repository — create this file yourself and adjust values to match your environment):Option B — same container (simple setups)
Option B — same container (simple setups)
Add the collaboration server as a third Supervisor program in the same container. This is simpler to operate but couples the two processes together.
/api/collaboration webhook endpoint — make sure the two containers can reach each other over the network.
