As PHP grows, more versions show up with better stability & performance, obviously we test our code against production environment, but what if we could test it against new versions with little effort and ensure soft migration in future ?

Here we will use Docker & Gitlab to ensure that our PHP code runs on these versions: 5.5, 5.6 and 7.0.

We’ll use our own Docker images with configured additional extensions not provided by PHP official images, also with installed GIT and newest composer out of the box.

What is Gitlab

Gitlab is git projects hosting platform staying that it will be free forever. How does it differ from Github or Bitbucket ?

  • no limits on public / private repos and users, more info here
  • no PRs (pull requests), but MR (merge requests) - more details here
  • Gitlab runners - tool to run builds on external machines, using host itself or docker - in this series we will speak only about docker runners. Runner can be either public (provided by Gitlab) or private - setup on external machine. In this example we will use Gitlab’s public runners.


If you want to see how it works / looks like then make some change in source and build will be automatically ran against your changes.

.gitlab-ci.yml config

First we need a config for our Gitlab runner. It is a configuration file written in YAML format, for full specification see docs

Let’s go trough the config for details:

Variables, section where we specify env variables which will be available for all running scripts

  • COMPOSER_CACHE_DIR - we want to cache composer libraries across builds, we don’t want to pull all the dependencies for each build,
  • COMPOSER_DISABLE_XDEBUG_WARN - disabling composer’s xdebug warn so it doesn’t mess with our tests output,
  • COMPOSER_VENDOR_DIR - here we setup custom directory for composer’s vendor dir,
  • CI_PROJECT_ID and CI_BUILD_REF_NAME are provided by Gitlab, you can read more about available variables here
    • CI_PROJECT_ID - this is ID of our project,
    • CI_BUILD_REF_NAME - The branch or tag name for which project is built.

Stages, section when we specify groups of tasks to be executed, you can think about it as a pipeline, for example: test, build, deploy.

We only specify test as this is our only stage in this scenario.


  • test55 - job name
  • image - docker image pulled from Docker Hub
  • stage - to which stage task belongs to
  • script - list of commands to execute

mkdir -p /storage/vendor/${CI_PROJECT_ID}/${CI_BUILD_REF_NAME} - Here we prepare storage for composer’s dependencies

ln -s /storage/vendor/${CI_PROJECT_ID}/${CI_BUILD_REF_NAME} vendor - link the storage to vendor in our app directory

make - run our make script to install dependencies and run tests.

PHP Testing

Makefile - quickly adds console for repetitive tasks done with our application from command line, like:

  • installing dependencies
  • testing
  • building
  • releasing
  • and many more.

Example Makefile:

structure is:

if you run make without params it will run first command.

Now we can call $ make and test will execute after composer, example output:

You can see example build & output here

Wrap up

As you can see it is easy to test your code against many PHP versions. All you need is Gitlab and Docker image supporting your stack. Of course you don’t need to use Gitlab, you can configure your Jenkins or any other build tool to test your code on different Docker images. We like Gitlab as this offers many features out of the box with little effort. So if you start a new project, or want to automate testing with current one - try Gitlab as it might be the right tool for you.