Deploying PHP Applications
This comprehensive guide covers everything you need to know about deploying PHP applications with Flux-Orbit, from lightweight Slim APIs to full Laravel applications.
Overview
Flux-Orbit automatically detects PHP applications by looking for:
composer.json(primary indicator)composer.lockfor dependency resolution- Framework detection via dependencies in composer.json
Basic PHP Deployment
Simple Slim API
docker run -d \
--name slim-api \
-e GIT_REPO_URL=https://github.com/your-username/slim-api \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
What Happens Automatically
- Detection: Finds
composer.jsonand identifies as PHP project - Version Selection:
- Checks
PHP_VERSIONenvironment variable - Checks
phporplatform.phpin composer.json - Falls back to PHP 8.2
- Checks
- Runtime Installation (First deployment only, ~90-120s):
- Installs PHP and common extensions via apt-get
- Installs Composer package manager
- Installs extensions: mysql, pgsql, sqlite3, curl, gd, mbstring, xml, zip, bcmath, intl, redis, opcache
- Future deployments skip this step (~10-15s updates)
- Dependencies: Runs
composer install --no-dev --optimize-autoloader - Build: Framework-specific optimization (cache config, routes, assets)
- Start: Executes appropriate server command (artisan serve, php -S, etc.)
Framework-Specific Guides
Laravel Framework
Laravel is a full-stack PHP framework. Flux-Orbit automatically detects and optimizes Laravel applications:
docker run -d \
--name laravel-app \
-e GIT_REPO_URL=https://github.com/your-username/laravel-app \
-e APP_PORT=8000 \
-e PHP_VERSION=8.2 \
-e SECRET_KEY_BASE=your-secret-key \
-p 8000:8000 \
runonflux/orbit:latest
What Flux-Orbit Does Automatically:
- Environment Setup: Copies
.env.exampleto.envif needed - Application Key: Runs
php artisan key:generateif APP_KEY not set - Configuration Caching: Runs
php artisan config:cachefor performance - Route Caching: Runs
php artisan route:cachefor faster routing - Frontend Assets: Builds assets if
package.jsonhas build script - Server Start: Uses
php artisan serve --host=0.0.0.0 --port=$APP_PORT
Laravel Octane Support:
If Laravel Octane is installed, Flux-Orbit automatically uses it for high-performance serving:
# Install Octane in your Laravel project
composer require laravel/octane
# Deploy - Flux-Orbit detects Octane automatically
docker run -d \
--name laravel-octane \
-e GIT_REPO_URL=https://github.com/your-username/laravel-app \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
Important Environment Variables:
docker run -d \
--name laravel-api \
-e GIT_REPO_URL=https://github.com/your-username/laravel-api \
-e APP_PORT=8000 \
-e PHP_VERSION=8.2 \
-e SECRET_KEY_BASE=base64:your-generated-key \
-e DB_CONNECTION=mysql \
-e DB_HOST=your-db-host \
-e DB_DATABASE=your_database \
-e DB_USERNAME=your_user \
-e DB_PASSWORD=your_password \
-p 8000:8000 \
runonflux/orbit:latest
Lumen Framework
Lumen is Laravel's micro-framework for APIs. Flux-Orbit detects Lumen before Laravel (important for correct detection):
docker run -d \
--name lumen-api \
-e GIT_REPO_URL=https://github.com/your-username/lumen-api \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
Example routes/web.php:
<?php
/** @var \Laravel\Lumen\Routing\Router $router */
$router->get('/', function () use ($router) {
return response()->json([
'message' => 'Lumen API',
'version' => $router->app->version()
]);
});
$router->get('/health', function () {
return response()->json(['status' => 'healthy']);
});
Server Used: PHP built-in server with public directory
- Command:
php -S 0.0.0.0:8000 -t public
Symfony Framework
Symfony is a flexible PHP framework for web applications:
docker run -d \
--name symfony-app \
-e GIT_REPO_URL=https://github.com/your-username/symfony-app \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
What Flux-Orbit Does:
- Cache Warmup: Runs
php bin/console cache:warmup --env=prod - Asset Building: Builds Symfony Encore assets if
webpack.config.jsexists - Server Start: Uses Symfony CLI if installed, otherwise PHP built-in server
Slim Framework
Slim is a micro-framework for APIs and simple web applications:
docker run -d \
--name slim-api \
-e GIT_REPO_URL=https://github.com/your-username/slim-api \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
Example public/index.php:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', function (Request $request, Response $response) {
$data = ['message' => 'Slim API', 'version' => '1.0.0'];
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');
});
$app->get('/health', function (Request $request, Response $response) {
$data = ['status' => 'healthy'];
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
Server Used: PHP built-in server with auto-detected document root (public/, web/, or root)
CodeIgniter 4
CodeIgniter is a powerful PHP framework with minimal configuration:
docker run -d \
--name codeigniter-app \
-e GIT_REPO_URL=https://github.com/your-username/codeigniter-app \
-e APP_PORT=8080 \
-p 8080:8080 \
runonflux/orbit:latest
What Flux-Orbit Does:
- Environment Setup: Copies
envto.envif needed - Permissions: Sets proper permissions for
writable/directory - Server Start: Uses
php spark serve --host=0.0.0.0 --port=$APP_PORT
CakePHP
CakePHP is a rapid development framework for PHP:
docker run -d \
--name cakephp-app \
-e GIT_REPO_URL=https://github.com/your-username/cakephp-app \
-e APP_PORT=8765 \
-p 8765:8765 \
runonflux/orbit:latest
What Flux-Orbit Does:
- Cache Clearing: Runs
php bin/cake cache clear_all - Permissions: Sets proper permissions for
tmp/andlogs/directories - Server Start: Uses
php bin/cake server -H 0.0.0.0 -p $APP_PORT
Version Management
Specify PHP Version
Option 1: Environment Variable
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/php-app \
-e APP_PORT=8000 \
-e PHP_VERSION=8.3 \
-p 8000:8000 \
runonflux/orbit:latest
Option 2: composer.json
{
"require": {
"php": "^8.2"
}
}
Or using platform config:
{
"config": {
"platform": {
"php": "8.2.0"
}
}
}
Supported Versions: PHP 7.4, 8.0, 8.1, 8.2, 8.3
Extension Management
Install Additional Extensions
Flux-Orbit installs common extensions by default. For additional extensions:
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/php-app \
-e APP_PORT=8000 \
-e PHP_VERSION=8.2 \
-e PHP_EXTENSIONS="imagick,memcached,xdebug" \
-p 8000:8000 \
runonflux/orbit:latest
Default Extensions Included:
- cli, common, mysql, pgsql, sqlite3
- curl, gd, mbstring, xml, zip
- bcmath, intl, redis, opcache
Popular Additional Extensions:
imagick- ImageMagick for image processingmemcached- Memcached clientxdebug- Debugging and profilingmongodb- MongoDB driveramqp- RabbitMQ clientsoap- SOAP protocol supportldap- LDAP support
Performance Optimization
PHP Configuration
Flux-Orbit automatically configures PHP for production:
Memory Limit: Auto-configured to 75% of container memory
- Minimum: 128MB
- Maximum: 2GB
- Override with custom php.ini if needed
OPcache Settings (automatically enabled):
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 0
Composer Optimization
Dependencies are installed with production optimizations:
composer install --no-dev --optimize-autoloader
Dependency Caching
Dependencies are cached based on composer.lock hash:
- First deployment: Installs all dependencies (~30-60s)
- Subsequent deployments: Skips installation if composer.lock unchanged
- Force reinstall: Use
FORCE_INSTALL=trueenvironment variable
Environment Variables
PHP-Specific Variables
| Variable | Description | Default |
|---|---|---|
PHP_VERSION | PHP version to install (7.4-8.3) | Auto-detected from composer.json |
PHP_EXTENSIONS | Additional extensions (comma-separated) | - |
Common Application Variables
docker run -d \
--name php-app \
-e GIT_REPO_URL=https://github.com/your-username/php-app \
-e APP_PORT=8000 \
-e PHP_VERSION=8.2 \
-e PHP_EXTENSIONS="imagick,memcached" \
-e DATABASE_URL=mysql://user:pass@db:3306/mydb \
-e REDIS_URL=redis://redis:6379 \
-e APP_ENV=production \
-e APP_DEBUG=false \
-p 8000:8000 \
runonflux/orbit:latest
Advanced Scenarios
Monorepo - Deploy Specific Service
docker run -d \
--name php-api-service \
-e GIT_REPO_URL=https://github.com/your-username/monorepo \
-e PROJECT_PATH=services/api \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
Private Repository
docker run -d \
--name private-php-app \
-e GIT_REPO_URL=https://github.com/your-username/private-app \
-e GIT_TOKEN=ghp_your_personal_access_token \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
With Deployment Hooks
Create pre-deploy.sh in your repository root:
#!/bin/bash
# Run database migrations before deployment
echo "Running database migrations..."
php artisan migrate --force
Create post-deploy.sh:
#!/bin/bash
# Clear and warm up cache after deployment
echo "Warming up application cache..."
curl -s http://localhost:$APP_PORT/health > /dev/null
docker run -d \
--name laravel-with-hooks \
-e GIT_REPO_URL=https://github.com/your-username/laravel-app \
-e APP_PORT=8000 \
-p 8000:8000 \
runonflux/orbit:latest
Large Laravel Application
For large Laravel applications with extensive dependencies:
# On Flux Cloud, increase container RAM:
RAM: 4096 MB # or higher
Environment Variables:
GIT_REPO_URL: https://github.com/your-username/large-laravel-app
APP_PORT: 8000
PHP_VERSION: 8.2
# PHP memory is auto-configured to 75% of container (3GB in this case)
CI/CD Integration
Automatic Deployment with Webhooks
docker run -d \
--name laravel-api \
-e GIT_REPO_URL=https://github.com/your-username/laravel-api \
-e APP_PORT=8000 \
-e WEBHOOK_SECRET=my-secret-phrase \
-p 8000:8000 \
-p 9001:9001 \
runonflux/orbit:latest
Configure GitHub Webhook:
- Payload URL:
https://your-app-9001.app.runonflux.io/webhook - Content type:
application/json - Secret:
my-secret-phrase - Events: Just the
pushevent
Polling for Updates
docker run -d \
--name laravel-api \
-e GIT_REPO_URL=https://github.com/your-username/laravel-api \
-e APP_PORT=8000 \
-e POLLING_INTERVAL=300 \
-p 8000:8000 \
runonflux/orbit:latest
Troubleshooting
Composer Install Fails
Problem: "Your requirements could not be resolved to an installable set of packages"
Solution: Check PHP version compatibility in composer.json:
{
"require": {
"php": "^8.2",
"laravel/framework": "^11.0"
}
}
Ensure PHP_VERSION env matches requirements.
Missing PHP Extension
Problem: "Class 'Redis' not found" or similar extension errors
Solution: Add required extension via PHP_EXTENSIONS:
-e PHP_EXTENSIONS="redis,imagick,memcached"
Laravel Key Not Set
Problem: "No application encryption key has been specified"
Solution: Either:
- Let Flux-Orbit generate it automatically (happens on first deploy if APP_KEY not set in .env)
- Set
SECRET_KEY_BASEenvironment variable with pre-generated key
Application Not Accessible
Problem: Can't access the application on configured port
Solution: Ensure your application binds to 0.0.0.0 (not localhost or 127.0.0.1):
For custom PHP servers, make sure they listen on all interfaces:
// Good: Accessible from outside container
$server->listen('0.0.0.0', $port);
// Bad: Only accessible from inside container
$server->listen('localhost', $port);
Laravel, Lumen, Symfony, and other frameworks handled by Flux-Orbit already bind correctly.
High Memory Usage
Problem: PHP process using too much memory
Solution: PHP memory is auto-configured, but you can adjust by increasing container RAM:
# On Flux Cloud
RAM: 4096 MB # PHP will use ~3GB (75%)
Slow Composer Install
Problem: composer install takes too long
Solution:
- Use dependency caching - don't modify
composer.lockunless adding/updating packages - Remove development dependencies:
These are excluded with
{
"require-dev": {
"phpunit/phpunit": "^10.0"
}
}--no-devflag (automatic in production)
Performance Tips
- Use Dependency Caching: Don't modify
composer.lockunless necessary - saves 30-60s per deployment - Enable OPcache: Automatically enabled for 2-3x performance boost
- Laravel Optimization: Use
php artisan config:cacheandroute:cache(done automatically) - Laravel Octane: For high-performance Laravel apps, add
laravel/octaneto composer.json - Production Environment: Set
APP_ENV=productionandAPP_DEBUG=false - Health Checks: Implement
/healthendpoint for faster deployment verification - First Deployment: Takes 90-120s (PHP installation), subsequent deploys are 10-15s
Deployment Timeline
First Deployment (~90-120 seconds):
- Git clone: 5-10s
- PHP installation: 60-90s (one-time, persists in container)
- Composer install: 15-30s
- Framework build: 5-10s
- Application start: 2-5s
Subsequent Deployments (~10-15 seconds):
- Git pull: 2-3s
- PHP check: <1s (already installed)
- Composer install: <1s (cached if composer.lock unchanged)
- Framework build: 3-5s
- Application restart: 2-3s
Example Repository Structure
my-laravel-app/
├── composer.json # Dependencies and PHP version
├── composer.lock # Locked dependency versions
├── .env.example # Environment template
├── artisan # Laravel CLI
├── pre-deploy.sh # Optional: Pre-deployment hook
├── post-deploy.sh # Optional: Post-deployment hook
├── app/
│ ├── Http/
│ │ └── Controllers/
│ └── Models/
├── config/ # Laravel configuration
├── database/
│ └── migrations/
├── public/ # Document root
│ └── index.php
├── resources/
│ └── views/
└── routes/
├── web.php
└── api.php