Multi-Stage Builds
php-ci is a pre-built CI runtime — pull a tag and run tests. You usually do not need a custom Dockerfile. Reach for multi-stage builds when you must bake in proprietary tooling, OS packages not in the base image, or a golden application artifact.
When php-ci alone is enough
- PHPUnit, Pest, PHPStan, PHPCS and Composer scripts
- TYPO3 and Laravel test suites with standard extensions
- Matrix jobs across PHP 8.1–8.4
See Installation for pull and pin commands.
Extending php-ci in a Dockerfile
Add project-specific OS packages on top of a pinned php-ci tag:
FROM himanshuramavat/php-ci:8.3
USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
your-package \
&& rm -rf /var/lib/apt/lists/*
USER www-data
Build once, push to your registry, and reference that image in CI.
Multi-stage pattern
Use a builder stage for Composer and a slim runtime only when you ship containers to production — not for typical test jobs:
# Builder — install vendor/
FROM himanshuramavat/php-ci:8.3 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist --no-interaction
# Runtime — copy vendor + app (example only)
FROM himanshuramavat/php-ci:8.3
WORKDIR /app
COPY /app/vendor ./vendor
COPY . .
For CI test pipelines, mounting the repo with -v "$(pwd):/app" is simpler and
faster than rebuilding layers on every commit.
Layer caching in CI
Cache Composer's vendor/ directory between jobs instead of baking dependencies
into an image. Examples:
- GitHub Actions —
actions/cache - GitLab CI —
cache:key onvendor/