This repository acts as a template to set up basic Symfony webapp with docker compose and Traefik.
- Docker Compose (v2.21.0+)
- Task
- Reverse proxy | Traefik (Optional)
- It is assumed that the user has a working development setup for Traefik.
Tip
You can switch out Traefik for any other reverse proxy of your choice (or not use a reverse proxy at all), although this requires additional tweaking of labels (or exposing ports) in the docker compose configuration.
Add webapp.local
to your hosts files, e.g. /etc/hosts
(Unix).
For first time setup, initialise the .env.local
from the .env
.
task init
You can now tweak the values in the .env.local
if needed.
task up
If the reverse proxy is configured correctly, you should be able to visit webapp.local
in your browser and be
greeted by Symfony's default landing page.
Note
You can disregard the SSL certificate warnings for development usages.
You can add additional services to either compose.yaml
or compose.override.yaml
(specifically for your current
environment).
The following services are commonly used in a Symfony web application and serve as examples on how you can use additional docker containers in your stack.
Important
Make sure you run task docker:up
(or task docker:recreate
) after adding new services.
Want to test if your mails are send and displayed correctly in development? Use Mailcrab.
compose.override.yaml
services:
mailcrab:
image: marlonb/mailcrab:${MAILCRAB_IMAGE_VERSION}
ports:
- "1080:1080"
expose:
- 1025
networks:
- webapp
- proxy
networks:
webapp:
driver: bridge
proxy:
external: true
.env.local
###> IMAGE VERSIONS ###
MAILCRAB_IMAGE_VERSION="v1.4.0"
###< IMAGE VERSIONS ###
###> symfony/mailjet-mailer ###
MAILER_DSN="smtp://mailcrab:1025"
###< symfony/mailjet-mailer ###
You can now access Mailcrab at localhost:1080.
Want to cache in-memory? Use Redis.
compose.yaml
x-restart-always: &restart-always
restart: always
services:
redis:
image: redis:${REDIS_IMAGE_VERSION}
command: redis-server --include /usr/local/etc/redis/redis.conf --requirepass ${REDIS_PASSWORD}
<<: [*restart-always]
environment:
REDISCLI_AUTH: ${REDIS_PASSWORD}
expose:
- 6379
volumes:
- redis_data:/data
- ./.docker/redis/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- webapp
volumes:
redis_data:
driver: local
networks:
webapp:
driver: bridge
.env
###> IMAGE VERSIONS ###
REDIS_IMAGE_VERSION="7.0-alpine"
###< IMAGE VERSIONS ###
###> redis ###
REDIS_USER="default"
REDIS_PASSWORD="password"
REDIS_DSN="redis:${REDIS_USER}:${REDIS_PASSWORD}@?host[redis:6379]&dbindex=1"
###< redis ###
You can either run task
commands to run redis-cli
commands inside the Redis container (see .tasks/redis/Taskfile.yml
), or you can
expose the port to the host and use external tools to access the Redis container through localhost
.
For the latter case, this would require additional entry to the compose.override.yaml
(create if not exists).
compose.override.yaml
services:
redis:
ports:
- "6379:6379"
You can now access Redis at localhost:6379.
Tip
Use Redis Insight (v2) to view the data in your Redis container.
Want to handle data asynchronously? Use RabbitMQ.
Install the following PHP dependencies to use AMQP messenger with Symfony:
task composer:require -- symfony/messenger:^6.4.*
task composer:require -- symfony/amqp-messenger:^6.4.*
compose.yaml
x-restart-always: &restart-always
restart: always
x-restart-unless-stopped: &restart-unless-stopped
restart: unless-stopped
services:
messenger:
extends:
file: compose.common.yaml
service: php
depends_on:
phpfpm:
condition: service_started
rabbitmq:
condition: service_healthy
<<: [*restart-unless-stopped]
command: bin/console messenger:consume --time-limit=300 --quiet async
logging:
options:
max-size: "25mb"
max-file: "10"
rabbitmq:
image: rabbitmq:${RABBITMQ_IMAGE_VERSION}
hostname: rabbitmq
security_opt:
- no-new-privileges:true
<<: [*restart-always]
environment:
RABBITMQ_DEFAULT_USER: ${MESSENGER_TRANSPORT_USER}
RABBITMQ_DEFAULT_PASS: ${MESSENGER_TRANSPORT_SECRET}
healthcheck:
test: ["CMD-SHELL", "if rabbitmqctl status; then \nexit 0 \nfi \nexit 1"]
interval: 5s
timeout: 5s
retries: 5
expose:
- 5672
- 15672
volumes:
- ./.docker/rabbitmq/enabled_plugins:/etc/rabbitmq/enabled_plugins
- ./.docker/rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
- rabbitmq_data:/var/lib/rabbitmq
labels:
traefik.enable: true
traefik.docker.network: proxy
traefik.http.routers.webapp-rabbitmq.tls: true
traefik.http.routers.webapp-rabbitmq.entrypoints: websecure
traefik.http.routers.webapp-rabbitmq.rule: Host(`rabbitmq.${APP_DOMAIN}`)
traefik.http.routers.webapp-rabbitmq.service: webapp-rabbitmq
traefik.http.services.webapp-rabbitmq.loadbalancer.server.port: 15672
networks:
- webapp
- proxy
volumes:
rabbitmq_data:
driver: local
networks:
webapp:
driver: bridge
proxy:
external: true
.env
###> IMAGE VERSIONS ###
RABBITMQ_IMAGE_VERSION="3-management"
###< IMAGE VERSIONS ###
###> symfony/messenger ###
MESSENGER_TRANSPORT_USER="default"
MESSENGER_TRANSPORT_SECRET="password"
MESSENGER_TRANSPORT_DSN="amqp://${MESSENGER_TRANSPORT_USER}:${MESSENGER_TRANSPORT_SECRET}@rabbitmq:5672/%2f/messages"
###< symfony/messenger ###
You can now access the RabbitMQ panel at rabbitmq.webapp.local.
Tip
You can scale the messenger
service to use multiple containers to handle messages even faster!
Scale messenger
service with 5
containers:
docker compose up -d messenger --scale messenger=5
task app:install:dev
task grum:init
task contribute
If you want to create a Symfony project from scratch yourself, with the essential dependencies, you can do the following:
# Substitute "dev.example.com" with desired project directory name
docker run --rm -it -v $(pwd):/app composer:2 create-project symfony/skeleton:6.4.* dev.example.com
docker run --rm -it -v $(pwd)/dev.example.com:/app composer:2 require webapp -n
sudo chown -R $(id -u):$(id -g) $(pwd)/dev.example.com
This will give you a basic Symfony webapp environment (without Docker).
This repository comes with a MIT license.