Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.

Boilerplate for Symfony applications, to quickly configure development and production environments, with lifecycle workflows.

Notifications You must be signed in to change notification settings

FrancoisPog/Symfony-Boilerplate

Repository files navigation

Symfony 5 Boilerplate

This repository is a boilerplate for Symfony applications, to quickly configure development and production environments, with lifecycle workflows.

We use Docker & Docker-compose, to easily develop, test and deploy our application.

For databases, we are using MySQL here, but it can be easily adapted for MariaDB or Postgres.

To improve frontend development, we use Webpack-encore, configured to use SCSS and PReact. A ViteJS is configured to automatically reload the page, whenever a twig template is updated.

To automate testing and deployment, we use Github Actions workflows. Tests will be run in each pull request, and the application will be deployed each time the main branch is updated.

For the production environment, we use Nginx to serve the application.

⚠️ The purpose of boilerplate is to speed up the configuration of this type of project, it does not guarantee the absence of bugs, nor any type of optimization. It doesn't aim to be perfect (yet), and will need more use to improve it. Feel free to suggest improvements, anyone who can improve it is welcome.

Table of contents

Requirements

  • A Github repository
  • A Docker registry (DockerHub could help)
  • A private server, with Nginx and a webhooks handler
  • Docker and Docker-compose installed locally and on your production server

In this repository, we use my personal registry docker.francois.poguet.com, adapt it to use yours.

Configuration before use

Override environment files

The .env and docker-compose.yml files are for the local development environment, so you can replace them to suit your local needs, with the .env.local and docker-compose.override files .yml.

Build Docker images

For MySql and Node we use the official images, but for PHP and Nginx we use custom ones (in the ./docker/ directory). We add Composer and Symfony in the official PHP image and we add a default configuration for nginx (which you shouldn't need to change).

To be able to run the project, you need to create and push docker development images to your registry, they shouldn't change in the future. Production images will be built in the CI. Here we only have one development image, that of php.

To do this, you just need to run this command :

docker build -t docker.francois.poguet.com/symfony5-php-dev -f ./docker/php/Dockerfile.dev .

Configure the development database

To configure databases, we use an init script (./Docker/MySQL/initdb.sql), which creates both databases for development and testing, and the associated user. The script is executed when the MySQL data volume is first mounted (see the section about starting the server).

Remember to change the names of the databases, and the user credentials. You can add databases or users as you like.

Install development dependencies

The last step to run the server is to install the dependencies of Node and Symfony, in the associated containers. The commands are as follows:

docker-compose run php composer install
docker-compose run node npm install

Run the development environment

Start the server

We can now start the server, simply by starting the different containers, orchestrated by the docker-compose.yml file, with this command :

You can use the -d option to run in detached mode, to keep control of your terminal (but you won't be able to see the logs and potential errors).

docker-compose up

The Symfony application will run on localhost:8000 and PhpMyAdmin on localhost:8081.

You can change these ports as you want, you can also change the directory where MySQL data is stored ($HOME/docker-MySQL/sf5/ by default) but this one must be empty before initialization to avoid a lot of problems (in particular, the directory should not be the /var/lib/MySQL used by the MySQL service).

Remember to change the MYSQL_ROOT_PASSWORD to something more secure than root.

Stop the server

To stop the server you just have to down the containers with the command :

docker-compose down

Testing

To run tests with phpunit in a running PHP container, just run this command :

docker-compose exec php php ./bin/phpunit

If you just want to run tests without starting the server, use this one :

docker-compose run php php ./bin/phpunit

We use a .env.test file to override the .env for testing, for example to use a specific database (see here).

Continuous integration

A workflow is configured to automatically run the tests in Github Actions, in each pull request (.github/workflows/test.yml). It use a specific docker-compose and .env file, without development tools.

The PHP development image is pulled from your registry into the Github Actions server for testing, so be sure you pushed them.

The workflow uses Github Secrets to keep private your credentials for your docker registry, don't forget to populate them in your github repository.

Taskfile

To simplify commands through containers, I personally use Taskfile. You can install it here, and type task --list to see the list of available tasks.

Deploy in production

Production environment

To deploy to production, you must build and push the PHP production image, which contains the built front-end assets and server code. On your production server, you need the docker-compose.prod.yml file, rename it to docker-compose.yml to be detected automatically.

You also need your .env file for the Symfony project.

As we only need a single database in production, we just need to set the environment variables directly in the docker-compose and the database and user will be created on initialization. Again, use an empty directory for MySQL data.

If necessary, you can initialize the database(s) with a script, with the same method as above

The last file to have is the deploy.sh script, which (re)starts the server with the latest version of the PHP production image. If you want to manually stop the containers in production, you must use the -v option (docker-compose down -v) to stop the shared volume between the Nginx and PHP containers, otherwise the containers will not use the updated images.

To easily monitor the deployment of your project, this script uses webhooks to send logs to your Discord server, so you just need to adjust the variables at the top of the script for your project and your Discord server's webhook URL. See here how to set up a webhook in your discord server.

Success Failure
image image

Continous deployment

A workflow is configured to automatically build and push production image in Github Actions, each time the main branch is updated (.github/workflows/build.yml).

Once the image is pushed, the action sends a webhook to your server telling it that it can run the deploy.sh script to update the project.

Here too the workflow uses some Github secrets, don't forget them !

I personally use this tool to manage webhooks on my private server, with this configuration :

{
  "id": "symfony-redeploy",
  "execute-command": "/var/www/symfony5/deploy.sh",
  "command-working-directory": "/var/www/symfony5/",
  "trigger-rule": {
    "and": [
      {
        "match": {
          "type": "payload-hash-sha1",
          "secret": "Your webhook secret",
          "parameter": {
            "source": "header",
            "name": "X-Hub-Signature"
          }
        }
      },
      {
        "match": {
          "type": "value",
          "value": "refs/heads/main",
          "parameter": {
            "source": "payload",
            "name": "ref"
          }
        }
      }
    ]
  }
}

Serve your application under a domain name with Nginx

Currently, the production application is available on port 3001 on your server, but if you want to make it accessible from internet under a domain name, you need to serve it with Nginx, outside of the container. The only thing to do is to create a virtual host, proxying port 3001, as below.

You can find some documentation about Nginx installation and use here. Find out here how to install and configure SSL certificates with Certbot.

server {
  server_name   myproject.francois.poguet.com;

  location / {
    proxy_pass  http://localhost:3001;
  }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/myproject.francois.poguet.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/myproject.francois.poguet.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = myproject.francois.poguet.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  listen        80;
  server_name   myproject.francois.poguet.com;
    return 404; # managed by Certbot


}

About

Boilerplate for Symfony applications, to quickly configure development and production environments, with lifecycle workflows.

Topics

Resources

Stars

Watchers

Forks