PHP Workspace Container Part 1

Published: Dec 30 2019 | Last Updated: Dec 31 2019

Create a docker container to provide PHP's CLI, Composer, Git, Node & Yarn that is not project specific and without the need to have any of the aforementioned tools installed on the host.

I'll be demonstrating how to accomplish this using Debian Buster as the host with docker and docker-compose already installed. 

The source code for this project is available on GitHub

I use a directory structure on my host that allows me to store all of my PHP, Javascript, Python, etc. in separate folders organized by the project language. This allows me to have one workspace container per language. I.e.

- ~/develop/php
    - /symfony-app-1
    - /symfony-app-2
- ~/develop/python
    - /python-app

Creating our container

First we can go ahead and create our directory structure as follows:

cd ~/develop/php
mkdir workspace
touch .bash_aliases Dockerfile Makefile

- ~/php
    - .bash_aliases
    - Dockerfile
    - Makefile

Next, we'll define our docker image in the Dockerfile as follow's:

// Dockerfile

FROM php:7.4-cli-buster

RUN apt-get update && apt-get install -yqq \
    libzip-dev \
    zip \
    gnupg \

# Install node and Yarn in workspace container
RUN curl -sL | bash && \
    curl -sS | apt-key add && \
    echo "deb stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update && apt-get install -yqq \
    nodejs \

# Install composer & make compose global
RUN curl -s | php && \
    mv composer.phar /usr/local/bin/composer

# Create a regular user account to work from
RUN set -xe; \
    groupadd -g 1000 developer && \
    useradd -u 1000 -g developer -m developer && \
    usermod -p "*" developer -s /bin/bash

# Copy bash aliases defined on host to container
COPY .bash_aliases /home/developer/.bash_aliases

# Cleanup
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Set which account to use
USER developer

# Set working dir for container
WORKDIR /var/develop

Next, add any bash aliases that you want present within the workspace to .bash_aliases such as:

// .bash_aliases
alias la="ls -lah"

The above can be omitted if you prefer not to use any aliases, just remember to remove the COPY .bash_aliases /home/developer/.bash_aliases from the Dockerfile.

Create make targets

We could go ahead and fire up our container now without any issues using:

$> cd php/workspace
php/workspace:$> docker build . -t workspace:latest

Successfully built f6f89d2035c7
Successfully tagged workspace:latest

php/workspace:$> docker run -ti --rm --mount type=bind,src=/php,dst=/var/develop workspace:latest /bin/bash


But that's a lot of typing every time we need to enter the workspace container. We could use bash aliases to make this easier, but that can get unwieldy if you manage a lot of docker containers. I have chosen to use make to simplify my docker life. 

Edit your Makefile as follows:

// Makefile

.PHONY: build
build: ## Build docker workspace image
   docker build . -t workspace:latest

.PHONY: workspace
workspace: ## Launch workspace container bash shell
   docker run -ti --rm --mount type=bind,src=/path/to/develop/php,dst=/var/develop workspace:latest /bin/bash

Now all I have to do is call the make target's to build and launch the container like so:

php/workspace:$> make build
docker build . -t workspace:latest
Successfully built f6f89d2035c7
Successfully tagged workspace:latest

php/workspace:$> make workspace
docker run -ti --rm --mount type=bind,src=/path/to/develop/php,dst=/var/develop workspace:latest /bin/bash

developer@f6f89d2035c7:/var/develop$> WOOHOOO!

The best part about using make targets is portability. If you are managing several project's that each have their own docker images / containers, you can reuse the same makefile, with a little tweaking, across all of your projects. And best of all, it can be committed to your Git repo for others