PHP on Docker

In this article you will learn about setting up a PHP based project and runnning your phpunit tests. This setup will allow you to run any other PHP based tool as well.

Services and Steps

Before reading through the documentation please take a look at the Services and Steps documentation page so you have a good understanding how services and steps on Codeship work.

Dockerfile

We will start by creating a Dockerfile that lets you run your PHP based test suite in Codeship.

Please take a look at our Dockerfile Caching best practices article first to make sure you build your Dockerfile in a way that only invalidates the Docker cache when necessary.

Following is an example Dockerfile with inline comments describing each step in the file. The Dockerfile shows the different ways you can install extensions or dependencies so you can extend it to fit exactly what you need. Also take a look at the PHP container documentation on the Docker Hub.

# Start from PHP 5.6
# Take a look at the PHP container documentation on the Dockerhub for more detailed
# info on running the container: https://hub.docker.com/_/php/
FROM php:5.6

# Installing git to install dependencies later and necessary libraries for postgres
# and mysql including client tools. You can remove those if you don't need them for your build.
RUN apt-get update && \
    apt-get install -y \
      git \
      libpq-dev \
      postgresql-client \
      mysql-client

# Install tools and applications through pear. Binaries will be accessible in your PATH.
RUN pear install pear/PHP_CodeSniffer

# Install extensions through pecl and enable them through ini files
RUN pecl install hrtime
RUN echo "extension=hrtime.so" > $PHP_INI_DIR/conf.d/hrtime.ini

# Install Composer and make it available in the PATH
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer

# Install extensions through the scripts the container provides
# Here we install the pdo_pgsql and pdo_mysql extensions to access PostgreSQL and MySQL.
RUN docker-php-ext-install pdo_pgsql
RUN docker-php-ext-install pdo_mysql

# Set the WORKDIR to /app so all following commands run in /app
WORKDIR /app

# Copy composer files into the app directory.
COPY composer.json composer.lock ./

# Install dependencies with Composer.
# --prefer-source fixes issues with download limits on Github.
# --no-interaction makes sure composer can run fully automated
RUN composer install --prefer-source --no-interaction

COPY . ./

This Dockerfile will give you a good starting point to install any further packages or tools you might need. Take a look at our browser testing documentation to find and install any further tools you might need for your build.

codeship-services.yml

The following example will use the Dockerfile we created to set up a container we call project_name (please change to your specific project name) that will run your build. We’re adding a PostgreSQL container and Redis container so the tests have access to those two services.

When accessing other containers please be aware that those services do not run on localhost, but on a different hostname, e.g. “postgres” or “mysql”. If you reference localhost in any of your configuration files you have to change that to point to the hostname of the service you want to access. Setting them through environment variables and using those inside of your configuration files is the cleanest approach to setting up your build environment.

project_name:
  build:
    image: organisation_name/project_name
    dockerfile_path: Dockerfile.ci
  # Linking Redis and Postgres into the container
  links:
    - redis
    - postgres
  # Set environment variables to connect to the service you need for your build. Those environment variables can overwrite settings from your configuration files if configured. Make sure that your environment variables and configuration files work work together as expected.
  environment:
    - DATABASE_URL=postgres://postgres@postgres/YOUR_DATABASE_NAME
    - REDIS_URL=redis://redis
# Service definition that specify a version of the service through container tags
redis:
  image: redis:2.8
postgres:
  image: postgres:9.4

For more information about other services you can use with Codeship check out our services and databases documentation.

codeship-steps.yml

Now we’re going to set up our steps file that contains a parallelized build configuration.

Every step in a build gets its own clean container and linked services. Any setup commands that are necessary to setup a linked container (e.g. database migrations) need to be run for every step. While this duplicates some of the work, it also makes sure your parallelized test commands run completely independently.

Here we’re splitting up the testsuite of unit and integration tests and run them in separate containers.

- service: php
  command: phpunit tests/unit
- service: php
  command: phpunit tests/integration