π³ An extendable multistage PHP Symfony 4.3+ Docker Image for Production and Development
A Base Template Image to be added to your Symfony Application.
Introduction
Docker Image for Symfony 4.3+ Application running on Apache 2.4 based on PHP Official Image. This image should be used as a base image for your Symfony Project, and you shall extend and edit it according to your app needs. The Image utilizes docker's multistage builds to create multiple targets optimized for production and development.
You should copy this repositoryDockerfile
, .docker
Directory, Makefile
, and .dockerignore
to your Symfony application repository and configure it to your needs.
Main Points π
-
Production Image is a fully contained Image with source code and dependencies inside, Development image is set up for mounting source code on runtime to allow development and debugging using the container.
-
Image configuration is transparent, you can view and modify any of Apache's
*.conf
files, PHP*.ini
files or Entrypoint*.sh
scripts in the.docker
directory. -
Apache SSL is enabled, and hence run HTTP and HTTPS endpoints, with HTTPS it uses self-signed certificate generated at runtime. however, for production you'll need to mount your own signed certificates to
/etc/apache2/certs
amd overwrite defaults. -
Image tries to fail at build time as much as possible by running all sort of Checks.
-
Dockerfile is arranged for optimize builds, so that changed won't invalidate cache as much as possible.
-
As Symfony 4+ Uses Environment Variables for parameters, and only passing environment variables to the container is enough to be read by symfony. (no need to pass them through Apache2 conf too).
Requirements
- Docker 17.05 or higher
- Docker-Compose 3.4 or higher (optional)
- Symfony 4+ Application
Setup
Get Template
1. Generate Repo from this Template
- Download This Repository
- Copy
Dockerfile
,.docker
Directory,Makefile
, and.dockerignore
Into your Symfony Application Repository. - Modify
Dockerfile
to your app needs, and add your app needed PHP Extensions and Required Packages. - Situational:
- If you will use
Makefile
andDocker-Compose
: go to.docker/.composer/.env
and modifySERVER_NAME
to your app's name. - If you will expose SSL port to Production: Mount your signed certificates
server.crt
&server.key
to/etc/apache2/certs
. Also make sureSERVER_NAME
build ARG matches Certificate's Common Name.
- If you will use
- run
make up
for development ormake deploy
for production.
OR
And start from step 3..
Building Image
-
The image is to be used as a base for your Symfony application image, you should modify its Dockerfile to your needs.
-
The image come with a handy Makefile to build the image using Docker-Compose files, it's handy when manually building the image for development or in a not-orchestrated docker hosts. However in an environment where CI/CD pipelines will build the image, they will need to supply some build-time arguments for the image. (tho defaults exist.)
Build Time Arguments
ARG | Description | Default |
---|---|---|
PHP_VERSION |
PHP Version used in the Image | 7.3.9 |
COMPOSER_VERSION |
Composer Version used in Image | 1.9.0 |
SERVER_NAME |
Server Name (In production, and using SSL, this must match certificate's common name) | php-app |
COMPOSER_AUTH |
A Json Object with Bitbucket or Github token to clone private Repos with composer. Reference | {} |
Runtime Environment Variables
ENV | Description | Default |
---|---|---|
APP_ENV |
App Environment | - prod for Production image |
- dev for Development image |
||
APP_DEBUG |
Enable Debug | - 0 for Production image |
- 1 for Development image |
Tips for building Image in different environments
Production
- For SSL: Mount your signed certificates as secrets to
/etc/apache2/certs/server.key
&/etc/apache2/certs/server.crt
- Make sure build argument
SERVER_NAME
matches certificate's common name. - Expose container port
80
and443
.
You can disable SSL by modifying
site.conf
in.docker/conf/apache2
config if you don't need HTTPS or is having it using a front loadbalancer/proxy.
By default, Image has a generated self-signed certificate for SSL connections added at run time.
Development
- Mount source code root to
/var/www/app
- Expose container port
8080
and443
. (or whatever you need actually)
Configuration
1. PHP Extensions, Dependencies, and Configuration
Modify PHP Configuration
- PHP
prod
Configuration.docker/conf/php/php-prod.ini
π - PHP
dev
Configuration.docker/conf/php/php-dev.ini
π - PHP additional Symfony recommended configuration at
.docker/conf/php/symfony.ini
π
Add Packages needed for PHP runtime
Add Packages needed for PHP runtime in this section of the Dockerfile
.
...
# ---------------- Install Packages Needed Inside Base Image ------------------
RUN apt-get -yqq update && apt-get -yqq --no-install-recommends install \
# ----- Needed for PHP -----------------
# - Please define package version too ---
curl=7.52\* \
# ---------------------------------------
&& apt-get -qq autoremove --purge -y \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
...
Add & Enable PHP Extensions
Add PHP Extensions using docker-php-ext-install <extensions...>
or pecl install <extensions...>
and Enable them by docker-php-ext-enable <extensions...>
in this section of the Dockerfile
.
...
# --------------------- Install / Enable PHP Extensions ------------------------
RUN docker-php-ext-install opcache && pecl install memcached && docker-php-ext-enable memcached
...
Note
At build time, Image will run
composer check-platform-reqs
to check that PHP and extensions versions match the platform requirements of the installed packages.
2. Apache Configuration
- Apache defaults are all defined in
.docker/conf/apache2/apache2.conf
π - Site configurations are defined in
.docker/conf/apache2/main.conf
π and default using optimized recommended config by Symfony. - Virtualhost configurations are defined in
.docker/conf/apache2/site.conf
π that configure both HTTP and HTTPS hosts and Includemain.conf
π to keep things DRY.
Note
At build time, Image will run
apachectl configtest
to check Apache config file syntax is OK.
3. Post Deployment Custom Scripts
Post Installation scripts should be configured in composer.json
in the post-install-cmd
part.
However, Sometimes, some packages has commands that need to be run on startup, that are not compatible with composer, provided in the image a shell script post-deployment.sh
π that will be executed after deployment.
Special about this file that it comes loaded with all OS Environment variables as well as defaults from .env
and .env.${APP_ENV}
files. so it won't need a special treatment handling parameters.
It is still discouraged to be used if it's possible to run these commands using composer scripts.
Misc Notes
- Apache will output logs on container's stdout, and your application shall do this too. Read about 12factor/logs
- As Symfony 4+ Uses Environment Variables for parameters, and only passing environment variables to the container is enough to be read by symfony. (no need to pass them through Apache2 conf too).
- During Build, Image will run
composer dump-autoload
andcomposer dump-env
to optimize for performance.
License
MIT License Copyright (c) 2019 Sherif Abdel-Naby
Contribution
PR(s) are Open and welcomed.
This image has so little to do with Symfony itself and more with Setting up a PHP Website with Apache, hence it can be extended for other PHP Frameworks (e.g Laravel, etc). maybe if you're interested to build a similar image for another framework we can collaborate.
Possible Ideas
- Add a slim image with supervisor(and no apache) for running consumers.
- Add a slim image with cron tab(and no apache) for cron job instances.
- Add node build stage that compiles javascript.
- Recreate the image for Symfony 3^
- Recreate the image for Laravel