Over the years, Docker has become the de facto standard for building, shipping and running server applications. Docker allows you to store all the instructions needed to build the environment that will host your software next to the code, in the repository of the project.
I'm very excited to announce that after 6 years of teamwork, Symfony and API Platform now include an industry-first set of tools designed to automatically create, manage and run the Docker containers needed for your applications.
Docker Compose and Dockerfile Flex Configurators
As you probably know, Symfony comes with a handy tool called Flex. Flex is a Composer plugin that makes it easy to add new features to your projects. When you install a new PHP library, Flex automatically generates the code and configuration necessary to get that library set up.
And Flex has new superpowers! It is now able to generate and update a
docker-compose.yml
file to add the services needed by the packages you just
installed!
For instance, to use the Doctrine ORM,
you need a DBMS. Well, guess what? When installing Doctrine (e.g. composer require orm
),
Flex will now ask if you want it to update your docker-compose.yml
file.
If you answer "yes", it automatically adds a Postgres server that's ready to be used!
Another example: let's say you are using Symfony UX Turbo
and you want to take advantage of its great real-time capabilities.
Then, you need a Mercure.rocks hub.
Symfony Flex has you covered: it can automatically add one to your docker-compose.yml
file!
Run docker-compose up
and everything is ready!
In addition to the Docker Compose configurator, a Dockerfile
configurator
has also been added. It's able to add the PHP extensions required by the PHP
packages you install (e.g. pdo_pgsql
) to a compatible Dockerfile. More on that later!
Currently, the following Flex recipes leverage these new configurators:
PHP package | Docker Compose addition | Dockerfile addition |
---|---|---|
symfony/orm-pack |
postgres |
pdo_pgsql |
symfony/mercure-bundle |
dunglas/mercure |
|
symfony/panther |
chromedriver
geckodriver |
|
symfony/mailer |
schickling/mailcatcher |
|
blackfireio/blackfire-symfony-meta |
blackfire/blackfire |
The Docker Compose configurator also generates two override files:
docker-compose.override.yml
contains the specific configuration needed in development,
and docker-compose.prod.yml
the configuration needed in production. We'll come back to this.
Symfony CLI and Docker Compose
The Symfony CLI, which Fabien open-sourced during the opening keynote of the SymfonyWorld conference, is able to automatically detect Docker Compose services and to automatically configure your apps to use them.
To do so, Symfony CLI queries the Docker Engine API to find the ports used by
the Docker containers and populates the environment variables used by the app
to connect to them. Thanks to the generated docker-compose.override.yml
,
the services added by Symfony Flex are compatible with this feature.
And that's not all: you can start several projects at the same time without any
conflict (with, for example, a different Postgres server per project). To achieve
this, the Docker Compose services in docker-compose.override.yml
are mapped
to random ports on the host! Run docker-compose ps
in your project directory
to see the assigned ports.
Docker Skeleton and Installer
The Symfony CLI is the easiest way to get started with Symfony. But it needs a local PHP installation, a local Composer installation, and is designed to be used only in development.
What if you want to be sure that all the developers in your team use the exact same PHP version? What if you want to facilitate the onboarding and don't want your devs to install PHP or Composer locally? What if you want to want to use the same configuration also in your continuous integration system or even in production?
Here comes Symfony Docker!
Symfony Docker is a skeleton containing everything needed to install and run a Symfony project. With Symfony Docker, as long as you have a working installation of Docker Compose, you can create new Symfony projects without having to install anything locally.
Symfony Docker comes with two simple images:
- PHP FPM (and CLI)
- the Caddy webserver
It contains a Dockerfile
and docker-compose.yml
files compatible with
the Symfony Flex configurators. It is designed to be simple, readable and non-bloated,
but still allows running your project locally, in your CI, and in production!
Like Symfony CLI, Symfony Docker also sets the environment variables used by your project to ensure that it connects to the Docker Compose services installed by the Flex configurator.
Because Symfony Docker uses the shiny Caddy web server, TLS certificates are
generated and renewed automatically (both for localhost
and for your real
domain names in prod), HTTP/2 and HTTP/3 are natively supported, and you can
install all the Caddy modules that you
want (my own Mercure and
Vulcain modules,
an OAuth/OpenID Connect module, an
HTTP cache module...)!
Getting Started with Symfony Docker is straightforward:
1 2 3
$ git clone https://github.com/dunglas/symfony-docker
$ docker-compose build --pull --no-cache
$ docker-compose up
That's all, Symfony has been installed and your project is up and running. Install Doctrine, or Blackfire, or any other package supported by the Docker configurators and the required services and PHP extensions will be installed automatically!
Symfony Docker contains more goodies such as the ability to select the version of Symfony to install. It can also be added to existing projects. Read its documentation to learn more about that.
Symfony Docker is also a GitHub template that you can use to bootstrap your project. It contains a GitHub Actions workflow that automatically runs your tests using the provided Docker containers!
Symfony Docker isn't the only skeleton compatible with the new Flex configurators! The API Platform distribution (from which Symfony Docker has been extracted) also supports them!
Kubernetes
While Symfony Docker (and the API Platform distribution) can be used in production using Docker Compose, only single-host deployments are supported.
This may be sufficient for small to medium-sized projects, but when things get serious, you'll probably want to use the king of container orchestrators: Kubernetes.
The Docker images provided by Symfony Docker have been designed to be compatible with Kubernetes. But there is more! The API Platform project provides a Helm chart (the package manager of Kubernetes) to deploy your project on any Kubernetes cluster in a single command!
This chart is entirely compatible with Symfony Docker (and you don't need to use API Platform). Copy and paste the chart in your project, and voilà!
Learn how to deploy your apps in Kubernetes
For more details about this brand new Docker integration, visit the SymfonyWorld Online 2021 Winter Edition replay and watch the talk I gave about this. You can also check below the slides of my talk:
If you like these new features, and if you want new ones like this, sponsor me and sponsor the Symfony project!
That is just pure awesome - Thanks! :)
This has been long overdue, thank you.
May I ask why Caddy was chosen and not something a bit more traditional (I have nothing against it, just curious)?
One more reason to upgrade! Thank you very much!
@andrej because author of this package (dunglas/symfony-docker) like go any go-related stack. and use it on his projects (mercure and others). see https://github.com/dunglas/symfony-docker/pull/75
Thank you Kévin for this awesome news! In the Getting started code section, I guess it missing the
cd symfony-docker
instruction before thedocker-compose build --pull --no-cache
Hello, I am testing Docker support with symfony (flex) but I failed to install mailcatcher via symfony/mailer. I have the impression that the recipe has not been updated yet. It works like a charm using symfony/orm ! Thanks for this very handy contribution !
This is really a cool features.
Thanks for your hard work and providing us with these new features!
I am currently playing around with Symfony-Docker, but from what I can see, it works as a single application. This may be just a me-problem, but is Caddy capable of wildcard subdomains (*.localhost) that reverse_proxy to localhost?
Thanks again!