This is one of those posts that is more of a reference for me rather than general information. If you use PHP, Docker, MySQL, Windows, WSL2 and PHPStorm this post about my typical Laravel project setup may be of interest to you.
Docker and WSL2
I use Docker, specifically docker compose. Typically, I define two services in the docker-compose.yml
file, [project_name].app
and [project_name].mysql
. If the project is part of a service I will define a network, this is to make it easier for containers to communicate. All the Costs to Expect Apps rely on the Costs to Expect API so they all share the same network.
Below is an example of a docker-compose.yml
file for Budget, our free budgeting tool.
version: '3'
services:
costs.budget.app:
build:
context: .
dockerfile: .docker/app/Dockerfile
image: costs.budget.app
container_name: costs.budget.app
ports:
- "80:80"
volumes:
- .:/var/www/html
env_file: .env
environment:
TZ: UTC
DB_HOST: ${DB_HOST}
DB_DATABASE: ${DB_DATABASE}
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
costs.budget.mysql:
build:
context: .
dockerfile: .docker/mysql/Dockerfile
image: costs.budget.mysql
container_name: costs.budget.mysql
ports:
- "3306:3306"
env_file: .env
environment:
TZ: UTC
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- ./.docker/mysql/data:/var/lib/mysql
networks:
default:
name: costs.network
external: true
I leave the ports at their default values. The exception is when I know I will need to run more than Docker container at a which need to communicate. I always need to run the Costs to Expect API at the same time as another Costs to Expect App so will typically map the ports on the API to 8080 and 3308.
The dockerfiles for each of the services exist in a .docker
folder. I typically end up with .docker/app/Dockerfile
and .docker/mysql/Dockerfile
. The .docker/mysql
folder will also contain a data folder, this is the volume for the MySQL data.
The MySQL Dockerfile doesn’t include any configuration, just FROM mysql:8
, the example below shows a Dockerfile for a typically Laravel application.
I used to include Composer and PHPUnit but have moved away from the additional complexity as it didn’t really offer any benefits and just made configuration in PPHStorm more complicated.
FROM php:8.1-apache
COPY . /var/www/html
COPY .docker/app/vhost.conf /etc/apache2/sites-available/000-default.conf
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd
RUN apt-get update && apt-get install -y \
zip libzip-dev \
&& docker-php-ext-configure zip \
&& docker-php-ext-install zip
RUN docker-php-ext-install pdo_mysql bcmath
RUN chown -R www-data:www-data /var/www/html \
&& a2enmod rewrite
WORKDIR /var/www/html
PHPStorm, Composer and PHPUnit
PHPStorm works relatively flawlessly with WSL2, well it did and will again without a tweak after the 16th of January.
I store all my project files in WSL2, specifically Ubuntu, the project root for PHPStorm will normally be something like \\wsl$\Ubuntu\home\[user]\Projects\[project_name]
. I have a Projects folder inside my home directory and a folder for each project. The Projects folder includes any phar files I might need so as not to duplicate them across projects.
The CLI Interpreter is set to my distro of choice, so in my case Ubuntu.
Composer settings are as defined as below.
- Path to composer.json
//wsl$/Ubuntu/home/[user]/Projects/[project_name]/composer.js
on
- Execution, composer.phar
- Composer.phar location
\wsl$\Ubuntu\home\[user]\Projects\composer.phar
PHPUnit settings are defined as below
- Remote Interpreter
- Use composer autoloader
- Path to script
/home/[user]/Projects/[project_name]/vendor/autoload.php
- Test runner default configuration file
/home/[user]/Projects/[project_name]/phpunit.xml.dist
This Laravel project setup works well for all my projects as if I ever need to use a different version of PHP or MySQL I can update the dockerfiles for each service and rebuild. I recently needed to upgrade an App form PHP5.6 to 8.0, this setup made it easy to upgrade to each version of PHP and MySQL along the way and test at each step.
If I need to use Tailwind, SASS or other tools, I try to use them via WSL2 before going the Windows route.
After reading this you may wonder why I use Windows for development, there are three main reasons, one, I’m comfortable with Windows, two, I play games, three, I build my own PCs. The setup above will work regardless of your operating system of choice.
This post is part of a series on my development process. Please check out some of my other posts in this series, my git workflow and action class usage in my Laravel apps.