Bundles like XAMPP and WAMP have always been the straightforward choice for developing PHP applications. One-click installation and almost zero configuration makes it easy to bootstrap a development environment across different operating systems. However, like almost every magic, it has own trade-offs.
Using bundles or local installation of php and web server were okay at first. Things could go relatively painless with small number of non-complex dependencies and a handful of developers. A single page installation guide could cut it. As the dependencies grows, it becomes harder and sometimes imposible to replicate same environment across the operating systems. Real show begins when the number of developers starts to increase in the project. Just multiply the burden with the number of developers and you can see the picture. J
There are several ways available to overcome this operational cost. One of the most popular ways is utilizing linux containers and it’s defacto orchestrator docker. At Digitalact, we don’t install any server specific tools in our workstations. Everything is dockerized. In this post, we will talk about what we do and why when dockerizing a php application.
When you consider dockerize an application the very first thing you must decide is base image. We are using debian-slim flavour as our base image. There is one big reason behind this decision: Debian isn’t a derivative distribution. It is the root. This is the where the journey begins. Rock solid packages with professional maintainers. Plus, debian-slim is one of the most “clean” base image out there.
What is inside our Dockerfile?
Just after putting base image definition right at the top, we do a package upgrade immediately. This is pretty straightforward. Start with up to date image!
We install most basic packages like unzip, git, curl, cron etc. Just because we have choosen a bare-minimal image to build with, these most basic tools don’t exist in the image.
Official debian repositories don’t have up to date PHP versions due to their strict package maintain procedures. However, there is a guy named Ondrej Sury. As being a debian developer since 2000, he is doing the heavy lifting for us to bring up to date php versions to debian and derivatives. (which he points out importance of his work in deb.sury.org “Who am I?” section).
So, we are relying on Ondrej’s work and adding his repository to our sources.list file. Then we install PHP as usual. (we prefer php-fpm) Offcourse, starting from most basic packages like pdo, zip, gd. We don’t want to bloat our beloved docker image!
Yes, instead of using sepereate image, we do install nginx alongside with PHP inside our image. Number one reason to do this, there are some huge performance penalties in OSX with docker bind-mounts. Things can get crazy pretty quick if you run different bind-mounted images with frameworks that needs high number of i/o operations to disk in development mode. (like symfony/magento). We don’t want to fry eggs with our macbooks. So we allow one high i/o image in our docker setups. No more.
We don’t really need Apache. Plus, nginx is lighter and faster.
Create Custom User & Configure
We like to put everything under one non-admin unprivileged standart system user. PHP, Nginx and other services will utilize this user to run. There are two main reasons:
- Utilize base security: From now on, we acknowledge that every action in this docker image will be triggered by user X. So we set the scope from start.
- Eliminate permission problems from beginning. If there is a permission issue, we know where to look at. The user X.
Users home directroy is also created to hosts everything, including logs for php and nginx. This alone eliminates most of the permission issues in our docker image.
We do a cleanup before finishing a docker image. Examples below:
- Remove default configuration files: Nginx default site, PHP-FPM default pool. Because we simply don’t need them.
- Logs and apt cache: We don’t want to see logs (if any) created during the image build process. Because they are unnecessary. And can lead to confusion if debug process takes place afterwards. We are removing apt cache to make overall image smaller in final build. We don’t need them too.
In this article we talked about Digitialact way of dockerization of php applications. We explained main concepts and why we choose to do that way. There is no code examples in this article, because this is the first article regarding dockerization in our blog and we didn’t want to overwhelm you with details. However you can find a link below to your github repo which contains concrete implementation of what we talked about in abstract.
Check out: https://github.com/digital-act/dockerized-php-fpm-nginx
by Tuncay Üner