Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 117 additions & 10 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ env:
IMAGE_NAME: whilesmartphp/laravel-dev

jobs:
build:
build-app:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
Expand Down Expand Up @@ -50,30 +50,88 @@ jobs:
platforms: ${{ matrix.platform }}
build-args: |
PHP_VERSION=${{ matrix.php_version }}
cache-from: type=gha,scope=${{ matrix.php_version }}-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.php_version }}-${{ matrix.platform }}
cache-from: type=gha,scope=app-${{ matrix.php_version }}-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=app-${{ matrix.php_version }}-${{ matrix.platform }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}

- name: Export digest
if: github.event_name != 'pull_request'
run: |
mkdir -p /tmp/digests/${{ matrix.php_version }}
mkdir -p /tmp/digests/app-${{ matrix.php_version }}
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${{ matrix.php_version }}/${digest#sha256:}"
touch "/tmp/digests/app-${{ matrix.php_version }}/${digest#sha256:}"

- name: Upload digest
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: digest-${{ matrix.php_version }}-${{ matrix.runner }}
path: /tmp/digests/${{ matrix.php_version }}
name: digest-app-${{ matrix.php_version }}-${{ matrix.runner }}
path: /tmp/digests/app-${{ matrix.php_version }}
if-no-files-found: error
retention-days: 1

merge:
build-package:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write

strategy:
matrix:
php_version: ['8.2', '8.4']
platform: ['linux/amd64', 'linux/arm64']
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: ./package
platforms: ${{ matrix.platform }}
build-args: |
PHP_VERSION=${{ matrix.php_version }}
cache-from: type=gha,scope=package-${{ matrix.php_version }}-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=package-${{ matrix.php_version }}-${{ matrix.platform }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}

- name: Export digest
if: github.event_name != 'pull_request'
run: |
mkdir -p /tmp/digests/package-${{ matrix.php_version }}
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/package-${{ matrix.php_version }}/${digest#sha256:}"

- name: Upload digest
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: digest-package-${{ matrix.php_version }}-${{ matrix.runner }}
path: /tmp/digests/package-${{ matrix.php_version }}
if-no-files-found: error
retention-days: 1

merge-app:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
needs: build
needs: build-app
permissions:
contents: read
packages: write
Expand All @@ -93,7 +151,7 @@ jobs:
- name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digest-${{ matrix.php_version }}-*
pattern: digest-app-${{ matrix.php_version }}-*
merge-multiple: true
path: /tmp/digests

Expand All @@ -118,3 +176,52 @@ jobs:
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.php_version }}

merge-package:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
needs: build-package
permissions:
contents: read
packages: write

strategy:
matrix:
php_version: ['8.2', '8.4']

steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digest-package-${{ matrix.php_version }}-*
merge-multiple: true
path: /tmp/digests

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=package-${{ matrix.php_version }}
type=raw,value=package-${{ matrix.php_version }}-{{sha}}

- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)

- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:package-${{ matrix.php_version }}
104 changes: 93 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
# Laravel Dev Docker Image

Centralized Laravel development Docker image with nginx, PHP-FPM, and supervisor.
Centralized Laravel development Docker images with two variants:

## Image
- **App** — Full Laravel application image with nginx, PHP-FPM, and supervisor
- **Package** — Lightweight CLI image for package development and testing

## Images

```
# App variant (nginx + PHP-FPM + supervisor)
ghcr.io/whilesmartphp/laravel-dev:8.4
ghcr.io/whilesmartphp/laravel-dev:8.2

# Package variant (PHP CLI only)
ghcr.io/whilesmartphp/laravel-dev:package-8.4
ghcr.io/whilesmartphp/laravel-dev:package-8.2
```

## What's Included
## App Variant

Full-stack Laravel development environment.

### What's Included

- **PHP-FPM** (8.2 or 8.4)
- **Nginx** with Laravel-optimized config
Expand All @@ -18,8 +30,6 @@ ghcr.io/whilesmartphp/laravel-dev:8.2
- **PHP Extensions:** pdo_mysql, pdo_pgsql, mbstring, exif, pcntl, bcmath, gd, zip
- **Shared `laravel.mk`** at `/usr/local/share/laravel.mk`

## Usage

### docker-compose.yml

```yaml
Expand All @@ -39,11 +49,9 @@ services:
- '.:/var/www/html'
```

The `HOST_UID`/`HOST_GID` build args map container permissions to your host user, avoiding file ownership issues.

### Makefile

Copy `laravel.mk` into your project. It works standalone or with a thin project `Makefile`:
Copy `laravel.mk` into your project or include it:

```makefile
include laravel.mk
Expand Down Expand Up @@ -77,8 +85,6 @@ TEST_CMD = php artisan test --coverage
LINT_CMD = composer phpcs:test && composer phpmd && composer pint:test

include laravel.mk

# Add project-specific targets below
```

| Variable | Default | Description |
Expand All @@ -88,7 +94,7 @@ include laravel.mk
| `TEST_CMD` | `php artisan test` | Command used by `make test` |
| `LINT_CMD` | `composer pint:test` | Command used by `make lint` |

### Available Targets
### App Targets

| Target | Description |
|--------|-------------|
Expand Down Expand Up @@ -116,6 +122,82 @@ include laravel.mk
| `clean` | Remove everything (containers, images, volumes) |
| `help` | Show available targets |

---

## Package Variant

Lightweight image for developing and testing Laravel packages with Orchestra Testbench.

### What's Included

- **PHP CLI** (8.2 or 8.4)
- **Composer** (latest)
- **PHP Extensions:** pdo_mysql, pdo_pgsql, mbstring, zip
- **Shared `package.mk`** at `/usr/local/share/package.mk`

### docker-compose.yml

```yaml
name: my-package
services:
app:
image: ghcr.io/whilesmartphp/laravel-dev:package-8.4
volumes:
- .:/app
working_dir: /app
command: tail -f /dev/null
environment:
- APP_ENV=testing
```

### Makefile

Include `package.mk` from the image:

```makefile
include package.mk
```

Or override defaults before the include:

```makefile
TEST_CMD = ./vendor/bin/testbench package:test --parallel
LINT_FIX_CMD = ./vendor/bin/pint

include package.mk
```

| Variable | Default | Description |
|----------|---------|-------------|
| `TEST_CMD` | `./vendor/bin/testbench package:test` | Command used by `make test` |
| `LINT_CMD` | `composer pint:test` | Command used by `make lint` |
| `LINT_FIX_CMD` | `composer pint` | Command used by `make lint-fix` |

### Package Targets

| Target | Description |
|--------|-------------|
| `up` | Start containers |
| `down` | Stop and remove containers |
| `restart` | Restart containers |
| `logs` | Show container logs |
| `bash` | Open a shell in the container |
| `install` | Install dependencies (starts containers first) |
| `update` | Update dependencies |
| `test` | Run tests |
| `lint` | Check code formatting |
| `lint-fix` | Fix code formatting |
| `build` | Build workbench |
| `serve` | Start development server |
| `autoload` | Dump composer autoloader |
| `fresh` | Fresh start (down + up + install) |
| `setup` | Complete setup (fresh + test) |
| `check` | Run all checks (lint + test) |
| `clean` | Remove everything (containers, images, volumes) |
| `help` | Show available targets |

---

## Production

For production, use [`ghcr.io/whilesmartphp/frankenphp`](https://github.com/whilesmartphp/frakenphp) instead.
29 changes: 29 additions & 0 deletions package/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
ARG PHP_VERSION=8.4
FROM php:${PHP_VERSION}-cli

ARG HOST_UID=1000
ARG HOST_GID=1000

RUN apt-get update && apt-get install -y \
Comment thread
nfebe marked this conversation as resolved.
git \
libzip-dev \
libonig-dev \
libpq-dev \
unzip \
&& docker-php-ext-install pdo_mysql pdo_pgsql mbstring zip \
&& rm -rf /var/lib/apt/lists/*

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

RUN set -eux; \
Comment thread
nfebe marked this conversation as resolved.
groupadd -o -g ${HOST_GID} devuser; \
useradd -o -u ${HOST_UID} -g devuser -m -s /bin/bash devuser; \
mkdir -p /home/devuser/.composer/cache; \
chown -R devuser:devuser /home/devuser; \
git config --global --add safe.directory '*'

COPY package.mk /usr/local/share/package.mk

WORKDIR /app

USER devuser
Loading
Loading