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
109 changes: 31 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,60 @@
# php-cli-workspace

PHP CLI Docker image for Symfony development. Published for **PHP 8.3, 8.4 and 8.5**, on **`linux/arm64` and `linux/amd64`** (Docker pulls only the platform matching your machine).
PHP CLI Docker image for Symfony development, published for **PHP 8.3, 8.4 and 8.5** on **`linux/arm64` and `linux/amd64`** (Docker pulls only the platform matching your machine).

## Usage
![CI](https://github.com/brei0x/php-cli-workspace/actions/workflows/ci.yml/badge.svg) ![Publish](https://github.com/brei0x/php-cli-workspace/actions/workflows/publish.yml/badge.svg)

```bash
# Latest stable (PHP 8.5)
docker pull ghcr.io/brei0x/php-cli-workspace:latest
**Stack**: Docker · PHP on Debian Trixie (`php:*-cli-trixie`) · Composer 2 · Xdebug 3 · GitHub Container Registry · GitHub Actions

## Documentation

| Doc | Content |
| --- | --- |
| [docs/SETUP.md](docs/SETUP.md) | Usage, updating, other platform, Xdebug and JetBrains setup, local build, pipeline |
| [Releases](https://github.com/brei0x/php-cli-workspace/releases) | Dockerfile versions (`vX.Y.Z`) and their changes |
| [Security policy](https://github.com/brei0x/php-cli-workspace/security/policy) | How to report a vulnerability; served by `brei0x/.github` |
| [CLAUDE.md](CLAUDE.md) | Project context for Claude Code: pipeline internals, version policy, extensions |

# Pin a specific PHP version
docker pull ghcr.io/brei0x/php-cli-workspace:8.3
## Quick start

# Interactive shell
docker run --rm -it ghcr.io/brei0x/php-cli-workspace
Requires **Docker** (or any OCI runtime).

# Mount a project
```bash
docker pull ghcr.io/brei0x/php-cli-workspace:latest
docker run --rm -it -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php bin/console list
```

Xdebug is off by default: run with `-e XDEBUG_MODE=debug` to step-debug. IDE setup and the other recipes are in **[docs/SETUP.md](docs/SETUP.md)**.

## What's included

- PHP 8.3, 8.4 or 8.5 (Debian Trixie)
- Composer 2
- Xdebug 3 (mode `off` by default)
- Xdebug 3 (mode `off` by default; `client_host=host.docker.internal`, `client_port=9003`, `idekey=PHPSTORM`)
- Extensions: `bcmath` `bz2` `curl` `exif` `fileinfo` `gd` `intl` `mbstring` `opcache` `openssl` `pcntl` `pdo_mysql` `pdo_pgsql` `pgsql` `sodium` `sockets` `xsl` `zip`

## Debugging (Xdebug)

Xdebug is installed but disabled by default to avoid overhead. Enable it at runtime via the `XDEBUG_MODE` environment variable:
## Commands

```bash
# Step debugging (PHPStorm / any DAP client)
docker run --rm -it -e XDEBUG_MODE=debug -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php bin/console …

# Profiling
docker run --rm -it -e XDEBUG_MODE=profile -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php …
docker build -t php-cli-workspace . # Build the default version (PHP 8.5)
docker build --build-arg PHP_VERSION=8.3 -t php-cli-workspace:8.3 . # Build a specific version
docker run --rm php-cli-workspace php -m # List the extensions, as CI does
```

Default settings: `client_host=host.docker.internal`, `client_port=9003`, `idekey=PHPSTORM`.

### JetBrains integration (PhpStorm / IntelliJ IDEA + PHP plugin)

Both IDEs share the same PHP plugin, so the setup is identical.

1. **Interpreter**: Settings → PHP → CLI Interpreter → **…** → **+** → From Docker, image `ghcr.io/brei0x/php-cli-workspace:latest`. Keep the default container volume (project root → `/opt/project`). Optional configuration options: `-dmemory_limit=512M`.
2. **Composer**: Settings → PHP → Composer → Execution: **Remote Interpreter**. Then use Tools → Composer → Install, or the links above `composer.json`.
3. **Commands**: Settings → Tools → PHP Command Line Tool Support → **+**, remote interpreter:
## Environments

| Tool | Path | Alias |
|----------------------------------------|----------------------------|-------|
| Symfony | `/opt/project/bin/console` | `s` |
| Composer (composer.phar or php script) | `/usr/local/bin/composer` | `c` |
| Branch | Registry | Tags |
| ------ | --------------------------------------- | ----------------------------------------- |
| `main` | `ghcr.io/brei0x/php-cli-workspace` | `latest` (8.5), `8.5`, `8.4`, `8.3` |

Run them from Tools → Run Command… (`Ctrl+Shift+X`): `s about`, `c -d /opt/project install`, `c -d /opt/project require symfony/mailer --dev`. `Process finished with exit code 0` means success.
The IDE runs a tool from its script's directory, so `c` starts in `/usr/local/bin`: `-d /opt/project` points Composer at the project, or use step 2 instead.
4. **Debugging**: in a run/debug configuration, set `XDEBUG_MODE=debug` and start listening on port 9003 (default).
Publishing is **automatic** on every push to `main`, which also tags the commit and publishes its GitHub release. Every tag is rebuilt each Monday to pick up PHP and Debian security patches. Pipeline details: [docs/SETUP.md](docs/SETUP.md#pipeline).

Notes:
## Workflow

- Use a real Xdebug mode (`debug`, `profile`…), never `on`: PHP reads it as `1`, which Xdebug rejects.
- `bin/console about` shows `Xdebug true` as soon as the extension is loaded, even with mode `off`.
- Each command runs in a fresh container: add `--network <name>` to the interpreter's Docker container options to reach a database or other services.
- The IDE's built-in Terminal runs on your machine, not in the container: aliases `s` and `c` do not exist there.

## Updating the image

If you already have the image pulled, re-pull to get the latest version (Docker only downloads changed layers):
One branch per task (`feat/…`, `fix/…`, `chore/…`), Conventional Commits, PRs target `main`. Before pushing:

```bash
docker pull ghcr.io/brei0x/php-cli-workspace:latest
```

To verify the image date after pulling:

```bash
docker inspect ghcr.io/brei0x/php-cli-workspace:latest --format '{{.Created}}'
```

## Tags

| Tag | PHP |
|----------|-----|
| `latest` | 8.5 |
| `8.5` | 8.5 |
| `8.4` | 8.4 |
| `8.3` | 8.3 |

Each tag covers `linux/arm64` and `linux/amd64`. To pull the other platform (for example an amd64 image on Apple Silicon, run under emulation):

```bash
docker pull --platform linux/amd64 ghcr.io/brei0x/php-cli-workspace:latest
```

The Dockerfile itself is versioned by git tags (`vX.Y.Z`) and [GitHub releases](https://github.com/brei0x/php-cli-workspace/releases), cut from the Conventional Commits of each push to `main`. Image tags stay by PHP version, and every tag is rebuilt each Monday to pick up PHP and Debian security patches.

## Build locally

```bash
# Default (PHP 8.5)
docker build -t php-cli-workspace .

# A specific version
docker build --build-arg PHP_VERSION=8.3 -t php-cli-workspace:8.3 .
docker build -t php-cli-workspace . && docker run --rm php-cli-workspace php -m
```

## License
Expand Down
95 changes: 95 additions & 0 deletions docs/SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Setup

Using, debugging, building and releasing the `ghcr.io/brei0x/php-cli-workspace` image.

## Use the image

```bash
# Latest stable (PHP 8.5)
docker pull ghcr.io/brei0x/php-cli-workspace:latest

# Pin a specific PHP version
docker pull ghcr.io/brei0x/php-cli-workspace:8.3

# Interactive shell
docker run --rm -it ghcr.io/brei0x/php-cli-workspace

# Mount a project
docker run --rm -it -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php bin/console list
```

### Update a pulled image

Re-pull to get the latest build (Docker only downloads changed layers), then check its date:

```bash
docker pull ghcr.io/brei0x/php-cli-workspace:latest
docker inspect ghcr.io/brei0x/php-cli-workspace:latest --format '{{.Created}}'
```

### Pull the other platform

Each tag covers `linux/arm64` and `linux/amd64`. To pull the other platform (for example an amd64 image on Apple Silicon, run under emulation):

```bash
docker pull --platform linux/amd64 ghcr.io/brei0x/php-cli-workspace:latest
```

## Debugging (Xdebug)

Xdebug is installed but disabled by default to avoid overhead. Enable it at runtime via the `XDEBUG_MODE` environment variable:

```bash
# Step debugging (PHPStorm / any DAP client)
docker run --rm -it -e XDEBUG_MODE=debug -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php bin/console …

# Profiling
docker run --rm -it -e XDEBUG_MODE=profile -v $(pwd):/app ghcr.io/brei0x/php-cli-workspace php …
```

Default settings: `client_host=host.docker.internal`, `client_port=9003`, `idekey=PHPSTORM`.

### JetBrains integration (PhpStorm / IntelliJ IDEA + PHP plugin)

Both IDEs share the same PHP plugin, so the setup is identical.

1. **Interpreter**: Settings → PHP → CLI Interpreter → **…** → **+** → From Docker, image `ghcr.io/brei0x/php-cli-workspace:latest`. Keep the default container volume (project root → `/opt/project`). Optional configuration options: `-dmemory_limit=512M`.
2. **Composer**: Settings → PHP → Composer → Execution: **Remote Interpreter**. Then use Tools → Composer → Install, or the links above `composer.json`.
3. **Commands**: Settings → Tools → PHP Command Line Tool Support → **+**, remote interpreter:

| Tool | Path | Alias |
|----------------------------------------|----------------------------|-------|
| Symfony | `/opt/project/bin/console` | `s` |
| Composer (composer.phar or php script) | `/usr/local/bin/composer` | `c` |

Run them from Tools → Run Command… (`Ctrl+Shift+X`): `s about`, `c -d /opt/project install`, `c -d /opt/project require symfony/mailer --dev`. `Process finished with exit code 0` means success.
The IDE runs a tool from its script's directory, so `c` starts in `/usr/local/bin`: `-d /opt/project` points Composer at the project, or use step 2 instead.
4. **Debugging**: in a run/debug configuration, set `XDEBUG_MODE=debug` and start listening on port 9003 (default).

Notes:

- Use a real Xdebug mode (`debug`, `profile`…), never `on`: PHP reads it as `1`, which Xdebug rejects.
- `bin/console about` shows `Xdebug true` as soon as the extension is loaded, even with mode `off`.
- Each command runs in a fresh container: add `--network <name>` to the interpreter's Docker container options to reach a database or other services.
- The IDE's built-in Terminal runs on your machine, not in the container: aliases `s` and `c` do not exist there.

## Build locally

```bash
# Default (PHP 8.5)
docker build -t php-cli-workspace .

# A specific version
docker build --build-arg PHP_VERSION=8.3 -t php-cli-workspace:8.3 .

# Smoke-test the extensions, as CI does
docker run --rm php-cli-workspace php -m
```

## Pipeline

- **Pull request**: `ci.yml` builds every PHP version on each platform's native runner and lists its extensions with `php -m`.
- **Push to `main`**: `publish.yml` builds and pushes every PHP version for both platforms, applies the image tags, prunes the untagged images of earlier runs, then tags the commit (`vX.Y.Z`, from the Conventional Commits since the last tag) and publishes the [GitHub release](https://github.com/brei0x/php-cli-workspace/releases).
- **Every Monday**: `publish.yml` rebuilds every tag on fresh base images to pick up PHP and Debian security patches, without cutting a release.

Image tags stay by PHP version; the git tags version the Dockerfile. Adding or dropping a PHP version, and the pipeline internals, are in [CLAUDE.md](../CLAUDE.md).
Loading