Experimental set of Docker images for deploying PHP projects
This repo contains an experimental set of Docker images for deploying PHP projects using Docker.
It was inspired by Demin Yin’s PHP UK 2019 talk Massively Scaled High Performance Web Services with PHP.
The image set includes:
All images are based on Alpine GNU/Linux in order to be as small as possible, and have MySQL and MongoDB PHP extensions enabled.
$ cd base/web && docker build . -t php-server:8.2-alpine; cd ../..
$ cd base/worker && docker build . -t php-worker:8.2-alpine; cd ../..
$ docker compose up --build [-d]
The worker script should emit a log line every few seconds.
The web app listen by default on http://localhost:8000
, it exposes this endpoints:
/
: simple hello world/info.php
: shows PHP configuration/mysql
: connects to MySQL and fetches some sample data/postgres
: connects to Postgres and fetches some sample dataPlease note: I did my best to configure the images with a proper security level, but I haven’t yet tested them with an actual production environment, so if you want to use it in production take your time to test and tweak the system!
The scripts build/web
and build/worker
will package your web and console apps into Docker images adding a versioning tag based on the current commit hash. The latest version tag is saved into build/web.version
and build/worker.version
.
REPOSITORY TAG IMAGE ID CREATED SIZE
app-worker <CommitHash> 3f3f297562a6 About a minute ago 120MB
app-web <CommitHash> d451986e42f5 2 minutes ago 170MB
The images can then deployed to either your private Docker registry (i.e. docker push app-web:<hash>
) or directly to your production server using Docker save
command:
$ docker save app-web:<hash> | gzip > build/app-web-<hash>.tar.gz
$ scp build/app-web-<hash>.tar.gz you@yourserver:/some/path/app-web-<hash>.tar.gz
On your production server you can then load
the new image into Docker:
$ ssh you@yourserver 'docker load -i /some/path/app-web-<hash>.tar.gz'
$ scp build/web.version you@yourserver:/some/path/web.version
And start the new version using a script similar to the provided prod
example, which reads the image tags from the .version
files and set the needed environment variables.
$ ssh you@yourserver 'cd /some/path && ./prod stop && ./prod start'
All this can be done manually or by a CI/CD solution like Bitbucket Pipelines or Github Actions.
Although it may be tempting to embed SSL configuration and certificates within web images, it does make more sense to let them serve HTTP on a custom port (i.e. 8000) and have a frontend proxy as SSL endpoint on the deployment server. This technique also will allow to show a maintenance page during the short stop/start
cycle on update.