Parallel Docker builds for the wp-browser project – 02

This post is the second in a series, and you can find the first one here.

In my previous post I’ve written code that would work on my machine, a Mac OS machine.
To make this of any value, to myself and others, I want to spend some time trying to make the simple setup I have work with Windows and Linux too.
Since PHPStorm and similar IDEs are widely available on all platforms, the part I need to tweak and update is the one dealing with the stack setup.

Making it work on Linux

Looking at the current version of the docker-compose.yml file, making the current set up work on Linux requires the XDEBUG_REMOTE_HOST environment variable to be correctly set:

version: '3.2'

services:

  wpbrowser:
    # Instead of using a pre-built image, let's build it from the file.
    build:
      context: ./docker/wpbrowser
      dockerfile: Dockerfile
      args:
        # By default use PHP 7.3 but allow overriding the version.
        - BUILD_PHP_VERSION=${TEST_PHP_VERSION:-7.3}
    volumes:
      # Bind the project files into the /project directory.
      - ./:/project
    environment:
      # As XDebug remote host use the host hostname on Docker for Mac or Windows, but allow overriding it.
      # Build systems are usually Linux-based.
      # Use default port, 9000, by default.
      XDEBUG_CONFIG: "remote_host=${XDEBUG_REMOTE_HOST:-host.docker.internal} remote_port=${XDEBUG_REMOTE_PORT:-9000}"
      # I use PHPStorm as IDE and this makes the handshake easier.
      PHP_IDE_CONFIG: "serverName=wp.test"

From a terminal emulator, I can get the docker host IP address with this command:

ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+'

It’s not my finding or invention: I’ve found it around the web, precisely here.

Putting the pieces together, this one-line command will allow me to run unit tests, with XDebug support, on Linux:

XDEBUG_REMOTE_HOST="$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')" \
    docker-compose run --rm -e XDEBUG_REMOTE_HOST="${XDEBUG_REMOTE_HOST}" wpbrowser run unit

It works, as shown in the screenshots below; it’s not the most “accessible” and most effortless command to remember, but it works.

Making it work on Windows

According to the Docker for Windows documentation Docker on Windows, I’m excluding WSL at this stage, should expose the container host at the host.docker.internal hostname.
After I’ve installed Docker on Windows, I launch cmder and make sure all works as expected with the following commands:

docker --version
docker run --rm -it alpine ping host.docker.internal

I’ve already installed PHP, the extensions required by wp-browser , and Composer on the Windows machine using chocolatey.
Time to install Composer dependencies using composer install and wait for the dependencies installation to finish.

I configure PHPStorm the same way I’ve configured it on Mac:

Running the same docker-compose (with some differences) command I’ve used to run the tests on Mac should yield the same results.

docker-compose.exe build
docker-compose.exe run --rm wpbrowser run unit

So it does.

Windows is not my daily driver, but I have to admit the experience, so far, is a pleasing one.

Making it work on Windows Subsystem for Linux (WSL)

The round would not be complete without trying out WSL.
I’ve installed Bash on Windows, the required PHP packages and made sure I can connect to the Docker daemon from the bash session.
I’ve followed this guide and it worked… flawlessly.

Due to the number of layers involved, I’m taking baby steps to ensure all the moving parts are there are working as expected.

The first step is making sure I can get the IP address of the host machine (Windows) from WSL. I use the same command I would use on a Linux host:

ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+'

This command, though, does not have the desired effect: the docker0 network does not exist in the context of a WSL session.

This result is not surprising: the docker client is connecting to the Docker host, see the blog post I’ve linked above, via the tco://localhost:2375 address.
On a real Linux machine, the Docker server would be available on a socket; it’s not the case in WSL.

If I’m still using the Windows implementation of Docker when using WSL, then this means I should be able to ping the Docker host from the containers using host.docker.internal.
I’m using the alpine container to make sure of that:

docker run --rm -it alpine ping host.docker.internal

As expected, it works.

Since the Docker host is still the Windows machine, the PHPStorm configuration is not changed and the XDebug connection just works:

As the last step I want, in the context of Windows and WSL, know what the PHP_OS_FAMILY constant value is.
I run the same command on a cmder and and WSL (Ubuntu 18.04) session:

From PHP point of view, then, WSL is a Linux system.
For the sake of completeness running the same command on Mac and Linux yields the following results:

Next

The next logical step is hiding the complexity involved in “looking around” and running the correct commands in a script.
Codeception is using the Symfony Console component to manage its own CLI, and wp-browser is doing the same with its custom commands; adding another command, maybe more, dedicated to running the tests in containers seems a reasonable choice.

I appreciate your input