Victor: generate a docker compose yaml file containing nginx reverse-proxy, php-fpm symfony app, and mercure hub. create an example nginx.conf
Raycast AI: Of course. Here is a complete setup for a Symfony application using Docker Compose with Nginx, PHP-FPM, and a Mercure hub.
This setup assumes you have a directory structure like this:
.
├── app/ <-- Your Symfony project code goes here
├── docker/
│ ├── nginx/
│ │ └── nginx.conf <-- Nginx configuration
│ └── php/
│ └── Dockerfile <-- Custom PHP-FPM Dockerfile
└── docker-compose.yml <-- The main Docker Compose file
docker-compose.yml
FileThis file orchestrates the building and linking of your services.
docker-compose.yml
version: '3.8'
services:
#--------------------------------------------------------------------------
# PHP-FPM Service (Your Symfony App)
#--------------------------------------------------------------------------
app:
build:
context: ./docker/php
dockerfile: Dockerfile
container_name: symfony_app
restart: unless-stopped
volumes:
- ./app:/var/www/html
networks:
- app-network
environment:
# Symfony environment variables
APP_ENV: dev
APP_SECRET: ${APP_SECRET:-!ChangeMe!} # Change this in a .env file
DATABASE_URL: "postgresql://user:password@db:5432/app?serverVersion=16&charset=utf8"
# Mercure configuration for Symfony Notifier/Web-Push
# This URL is for server-to-server communication (app -> mercure)
MERCURE_URL: <http://mercure/.well-known/mercure>
# This URL is for the client-side browser to connect to Mercure
MERCURE_PUBLIC_URL: <http://localhost/.well-known/mercure>
# This secret MUST match MERCURE_JWT_KEY in the mercure service
MERCURE_JWT_SECRET: ${MERCURE_JWT_KEY:-!ChangeThisSuperSecretKey!}
#--------------------------------------------------------------------------
# Nginx Service (Reverse Proxy)
#--------------------------------------------------------------------------
nginx:
image: nginx:1.27-alpine
container_name: symfony_nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443" # Optional: For HTTPS
volumes:
- ./app:/var/www/html:ro # Mount app code as read-only
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
- mercure
networks:
- app-network
#--------------------------------------------------------------------------
# Mercure Hub Service
#--------------------------------------------------------------------------
mercure:
image: dunglas/mercure:v0.14
container_name: symfony_mercure
restart: unless-stopped
environment:
# The secret key to sign and verify JWTs.
# MUST match MERCURE_JWT_SECRET in the app service.
MERCURE_JWT_KEY: ${MERCURE_JWT_KEY:-!ChangeThisSuperSecretKey!}
MERCURE_ADDR: ':80' # Listen on port 80 inside the container
SERVER_NAME: ':80'
MERCURE_ALLOW_ANONYMOUS: '1' # Allow anonymous subscribers for development
MERCURE_CORS_ALLOWED_ORIGINS: '*' # Allow all origins for development
MERCURE_PUBLISH_ALLOWED_ORIGINS: '<http://nginx>, http://symfony_nginx' # Allow Nginx to publish updates
networks:
- app-network
#--------------------------------------------------------------------------
# Networks
#--------------------------------------------------------------------------
networks:
app-network:
driver: bridge
Dockerfile
This Dockerfile
for PHP installs necessary extensions for a typical Symfony application.
docker/php/Dockerfile
# Use an official PHP-FPM image as a base
FROM php:8.3-fpm-alpine
# Set working directory
WORKDIR /var/www/html
# Install system dependencies needed for PHP extensions
RUN apk add --no-cache \\\\
$PHPIZE_DEPS \\\\
icu-dev \\\\
libzip-dev \\\\
postgresql-dev # Use 'mysql-dev' for MySQL/MariaDB
# Install PHP extensions required by Symfony
RUN docker-php-ext-install \\\\
intl \\\\
pdo pdo_pgsql \\\\ # Use 'pdo_mysql' for MySQL/MariaDB
zip \\\\
opcache
# Install Composer globally
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Clear cache
RUN apk del .phpize-deps && rm -rf /var/cache/apk/*
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
This configuration file acts as a reverse proxy. It serves static files directly and forwards PHP requests to the app
(PHP-FPM) service and Mercure requests to the mercure
service.
docker/nginx/nginx.conf
server {
listen 80;
server_name localhost;
root /var/www/html/public;
# Log files
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Set a higher client body size
client_max_body_size 25M;
# Main location block for the Symfony application
location / {
# Try to serve the file directly, otherwise fall back to index.php
try_files $uri /index.php$is_args$args;
}
# Location block for PHP files
# This is the entry point for all dynamic requests
location ~ ^/index\\\\.php(/|$) {
# Forward requests to the PHP-FPM service
# 'app' is the service name from docker-compose.yml
fastcgi_pass app:9000;
fastcgi_split_path_info ^(.+\\\\.php)(/.*)$;
include fastcgi_params;
# When you are using symlinks to link the document root to the
# real one, you must ensure that essences like SCRIPT_FILENAME
# and DOCUMENT_ROOT are set correctly.
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents Nginx from sending the "Content-Type" header to the client
# when the FastCGI server returns a "Status" header.
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
# Location block for the Mercure Hub
# All requests to /.well-known/mercure will be proxied to the Mercure service
location /.well-known/mercure {
# 'mercure' is the service name from docker-compose.yml
proxy_pass <http://mercure>;
# These headers are required for Server-Sent Events (SSE) to work
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection '';
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 10m; # A long timeout is important for long-lived connections
}
# Deny access to .php files in the /bundles directory
location ~ /bundles/.*\\\\.php$ {
deny all;
}
# Block access to dotfiles (.git, .htaccess)
location ~ /\\\\. {
deny all;
}
}
docker/nginx
and docker/php
directories.docker-compose.yml
, docker/php/Dockerfile
, and docker/nginx/nginx.conf
).