# Building PHP Projects on AWS CodeBuild


By Ben Ramsey

Published on December 2, 2016


I've had a great time at [AWS re:Invent](https://reinvent.awsevents.com/) this week, attending sessions and hanging out with some of the [ShootProof](https://www.shootproof.com/) team. My favorite part of the week was the "mini con" on containers. I spent Thursday immersed in sessions dedicated to deploying Docker containers on AWS.

Of course, the main highlight of re:Invent is always the keynotes and the new services and features announcements they make during the keynotes. One of the new services caught my attention, and I decided to give it a try. That service is [AWS CodeBuild](https://aws.amazon.com/codebuild/).

CodeBuild is designed to be used as part of the [AWS CodePipeline](https://aws.amazon.com/codepipeline/), but it may also be used by itself. Additionally, with AWS's increased focus on their container service ([ECS](https://aws.amazon.com/ecs/)), it's designed to integrate with ECS to use images you've stored in AWS, but it may also use images available on [Docker Hub](https://hub.docker.com/).

Out of the box, CodeBuild provides some managed images that you may use to build your projects. These include environments for Android, Java, Python, Ruby, Golang, and Node.js. PHP is missing from this list, but since you're able to use other images, I decided to see how easy it is to get up and running on CodeBuild with a PHP project. I chose to try out my [ramsey/uuid library](https://github.com/ramsey/uuid) for a simple test. Feel free to follow along with me.

## Getting Started

From your Amazon console, search for "CodeBuild" from the AWS Services search box, and choose it from the drop down menu that appears.

^^^
![Search for CodeBuild from the AWS console](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/console-codebuild-search.png)
^^^ **Figure 1.** Search for "CodeBuild" from the AWS console

If you've not yet begun playing with CodeBuild, you'll see a page like the one in Figure 2. Click the "Get Started" button to begin.

^^^
![Search for CodeBuild from the AWS console](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-getting-started-2.png)
^^^ **Figure 2.** Getting started with CodeBuild

## Configuring Your Project

Figure 3 shows most of the options available when configuring a project, pre-filled for the ramsey/uuid library. I'll step through each option to explain what's going on.

First, provide a project name. Here, I've named the project "ramsey-uuid."

For _Source provider_, choose GitHub and then click the link provided to connect to GitHub. This will take you through the OAuth dance to grant AWS with access to your GitHub account. Afterwards, the _Repository_ drop-down will be populated with a list of your GitHub repositories. Here, I've selected the uuid repository.

Next, you need to tell CodeBuild how to build your project by specifying an image to use. To use an image in Docker Hub, select "Specify a Docker image" for _Environment image_ and choose "Other" for _Custom image type_. For the _Custom image ID_, I'm using `benramsey/composer-uuid:latest` to specify the repository, image name, and image tag. You may place a [_buildspec.yml_ file](http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html) in the root of your repository to specify build commands (similar to a [_.travis.yml_ file](https://docs.travis-ci.com/user/customizing-the-build)). Since ramsey/uuid doesn't have a _buildspec.yml_ file, I'm specifying the _Build commands_ directly.

> [!WARNING]
> While there is an [official Composer image on Docker Hub](https://hub.docker.com/_/composer/), it is currently based on the `php:7-alpine` image (see the [Dockerfile](https://github.com/composer/docker/blob/be6ecf58913f704399d11a352818b22951832a60/1.2/Dockerfile) for reference). The PHP image using [Alpine Linux](https://alpinelinux.org/) will not run on AWS CodeBuild. Until this is resolved, I recommend using [Rob Loach's](http://robloach.net/) [composer/composer image](https://hub.docker.com/r/composer/composer/), which is what I have used as the basis for my [benramsey/composer-uuid](https://hub.docker.com/r/benramsey/composer-uuid/) image.

The full build command I've specified for ramsey/uuid is:

```shell
$ composer install --no-interaction --prefer-dist \
    && ./vendor/bin/parallel-lint src tests \
    && ./vendor/bin/phpunit --verbose --no-coverage \
    && ./vendor/bin/phpcs src tests --standard=psr2 -sp
```

Finally, I'm not generating any artifacts for this build, so I selected "No artifacts" for the _Artifacts type_, and I chose to let it automatically create a service role in my account.

Our project is now configured, so click _Continue_, review your choices, click _Save and Build_, then click _Start build_ to run a build.

^^^
[![Configure a CodeBuild project](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png)](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png)
^^^ **Figure 3.** Configure a project *(click to enlarge)*

## Building Your Project

As your project is building, you're able to view the progress of each stage of the build, complete with the last 20 lines of the log output, or you may view the complete log in CloudWatch to see any errors or problems that were emitted during the build. If the build passes, you'll see the word _Succeeded_ in a comforting bold green.

^^^
[![View the progress of your project build](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png)](https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png)
^^^ **Figure 4.** Project build progress *(click to enlarge)*

## What Next?

My team is looking into CodeBuild as an alternative to running a dedicated Jenkins instance, and as we evaluate it, there are a few things we're considering:

* Some of our tests talk to a dev database in a VPC. How do we grant VPC access to a container running in CodeBuild?
* In Jenkins, we capture a handful of artifacts, including code coverage reports and generated docblock documentation. With CodeBuild, we might consider copying these artifacts into an S3 bucket configured for website hosting.
* What do we do about the other information we currently capture, like JUnit and Clover XML files?

Feel free to use ramsey/uuid and my directions here to play with CodeBuild, or use your own project. In the comments, let me know what you think and whether you've run into any caveats with your builds. If you come up with any solutions for the things we're considering, I'd love to hear them.


