php-deploy
GitHub用于构建和部署PHP应用,支持Laravel、Symfony等框架。自动检测环境、依赖及框架类型,生成Dockerfile,处理Composer安装、启动优化及Node.js集成,确保高效稳定的PHP服务发布。
Trigger Scenarios
Install
npx skills add nixopus/nixopus --skill php-deploy -g -y
SKILL.md
Frontmatter
{
"name": "php-deploy",
"metadata": {
"version": "1.0"
},
"description": "Build and deploy PHP applications — Composer, Laravel, Symfony, FrankenPHP, PHP-FPM, and Dockerfile patterns. Use when deploying a PHP project, or when composer.json or index.php is detected."
}
PHP Deployment
Detection
Project is PHP if any of these exist:
composer.jsonat the build context rootindex.phpat the root
Versions
PHP 8.2+ only.
composer.json→require.php(e.g.">=8.2").php-versionormise.toml/.tool-versions- Defaults to 8.4
Package Manager
Composer. Detect composer.json and composer.lock.
| Has lock file | Command |
|---|---|
| yes | composer install --no-dev --optimize-autoloader |
| no | composer install --no-dev --optimize-autoloader |
Document Root
Laravel and Symfony use public/. Generic PHP uses the project root.
PHP Extensions
Detected from composer.json → require section with ext-* entries.
Framework Detection
| Signal | Framework |
|---|---|
artisan |
Laravel |
symfony.lock or config/ structure |
Symfony |
wp-config.php |
WordPress |
index.php + routing |
Generic PHP |
Laravel-Specific
When artisan is present:
- Document root:
public/ - Migrations run by default during startup. Skip by setting
SKIP_MIGRATIONS=true. - Storage symlinks, optimization
- Build-time artisan caches: config, routes, views, events
- Storage directory must be writable
Startup Process
- Run migrations (Laravel; skip if
SKIP_MIGRATIONS=true) - Create storage symlinks (Laravel:
php artisan storage:link) - Optimize (Laravel: config/route/view cache)
- Start PHP server (FrankenPHP, PHP-FPM, or
php -S)
Override by providing custom start-container.sh in project root.
Node.js Integration
If package.json detected alongside PHP (e.g. Laravel + Vite):
- Install Node.js
- Run
npm installor equivalent - Execute build scripts from
package.json - Prune dev dependencies in final image
Install Stage Optimization
Copy composer.json + composer.lock first for layer caching.
Caching
RUN --mount=type=cache,target=/root/.composer/cache \
composer install --no-dev --optimize-autoloader
Base Images
| Use case | Image |
|---|---|
| FrankenPHP | dunglas/frankenphp:latest or dunglas/frankenphp:php8.4 |
| PHP-FPM | php:8.4-fpm-alpine |
| CLI / built-in server | php:8.4-cli-alpine |
Dockerfile Patterns
Laravel with FrankenPHP
FROM composer:2 AS deps
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
FROM php:8.4-cli-alpine AS build
WORKDIR /app
COPY --from=deps /app/vendor ./vendor
COPY . .
RUN php artisan config:cache && php artisan route:cache && php artisan view:cache
FROM dunglas/frankenphp:php8.4
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
CMD ["frankenphp", "run", "--config", "/app/Caddyfile"]
Generic PHP + Composer
FROM composer:2 AS deps
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
FROM php:8.4-fpm-alpine
WORKDIR /app
COPY --from=deps /app/vendor ./vendor
COPY . .
EXPOSE 9000
CMD ["php-fpm"]
Gotchas
- Laravel
storage/andbootstrap/cache/must be writable —chownthese directories in the Dockerfile for non-root users - FrankenPHP defaults to port 8080, not 80 — ensure EXPOSE and proxy config match
- Composer
post-autoload-dumpscripts may fail during Docker build if the app isn't fully configured — use--no-scriptsduring install, then runcomposer dump-autoload --optimizeafter copying source - PHP OPcache should be enabled in production (
opcache.enable=1,opcache.validate_timestamps=0) for significant performance gains - Extensions listed in
requireasext-*must be installed in the Docker image — they are not bundled with base PHP images
Version History
- cf05d97 Current 2026-08-20 14:52


