Skip to content
/ symfony-docker Public template

Symfony 6 setup with Docker and Traefik

License

Notifications You must be signed in to change notification settings

ToshY/symfony-docker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

78 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎼 Symfony Docker πŸ‹

Code style Mess detector Static analysis Unit tests Security

A webapp starting template for Symfony 6 with Docker Compose.

πŸ“œ Introduction

This repository acts as a template to set up basic Symfony webapp with docker compose and Traefik.

🧰 Prerequisites

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.

🎬 Get Started

Update hosts file

Add webapp.local to your hosts files, e.g. /etc/hosts (Unix).

Initialise dotenv

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.

Start application services

task up

Visit the application

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.

πŸ“š Additional services

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.

Mail

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 ###

Usage

You can now access Mailcrab at localhost:1080.

Redis

Want to cache in-memory? Use Redis.

Compose configuration

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

Environment variables

.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 ###

Usage

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.

Messenger & RabbitMQ

Want to handle data asynchronously? Use RabbitMQ.

Dependencies

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 configuration

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

Environment variables

.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 ###

Usage

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

πŸ› οΈ Contribute

Install dependencies

task app:install:dev

Enable GrumPHP

task grum:init

Manual test run

task contribute

🧰 DIY

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).

❕ Licence

This repository comes with a MIT license.