Skip to content

redfieldchristabel/laravel-dockerize

Repository files navigation

Build and Push Laravel Images to GHCR Build and Push Laravel Installer Image to GHCR Build and Push Octane-Swoole Images

Laravel-Optimized PHP Images πŸŽ‰

Welcome to the Laravel-Optimized PHP Images repository! πŸš€ These pre-built Docker images, hosted on the GitHub Container Registry (GHCR), are your fast track to Laravel awesomeness. Whether you’re scaffolding a new app with our Laravel installer (no local PHP needed!) or running Laravel 10, 11, or 12 with our PHP-optimized images, we’ve got you covered. Packed with essential PHP extensions, running as a non-root laravel user, and optimized for production, these images make development secure, fast, and fun. Let’s build something amazing! πŸ˜„

Why Choose These Images? 🌟

Forget wrestling with PHP setups or complex Docker configs. Our images are tailor-made for Laravel developers, offering:

  • Zero-Setup Scaffolding πŸ—οΈ: Create Laravel 10, 11, or 12 apps with just Docker using our installer imageβ€”no PHP or Composer required locally.
  • Top-Notch Security πŸ”’: Run as the non-root laravel user for safer development and production.
  • Blazing-Fast Setup ⚑: Pre-installed PHP extensions for instant local and CI/CD environments.
  • Streamlined Workflows πŸ› οΈ: Focus on coding, not configuring, with Laravel-friendly defaults.
  • Filament Support 🎨: Dedicated images for Filament projects (see Filament-Optimized Images).
  • Laravel Octane Support πŸš€: High-performance images with Swoole for Octane (see Octane-Optimized Images).
  • Flexible Deployment 🌍: Copy code into images for production speed, with minimal mounts for security.

Need imagick, pgsql, or custom tweaks? Our customization guides make it a breeze! πŸ› οΈ

Getting Started 🎬

Pull images from ghcr.io/redfieldchristabel/laravel and jump in! Start by creating a new app or scaffolding a Docker environment for an existing project, then run your app. Let’s go! πŸš€

Creating a New Laravel App πŸ—οΈ

Kick off your project with our laravel:installer image! This lightweight image (~120-150 MB) includes the latest Laravel CLI and scaffolds Laravel 10, 11, or 12 apps with just Dockerβ€”no local PHP or Composer needed. Perfect for Linux, Mac, or Windows (with WSL2)!

Example:

docker run -it -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-app

This creates a Laravel 12 app (latest) in ./example-app/. The image runs laravel directly, so you just add new example-app.

Older Versions:

  • Use --version to scaffold Laravel 10 or 11.
  • Example: docker run -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-app --version=11 (Laravel 11 app).

Customize Your App:

  • Add stacks: --breeze (Blade), --jet (Livewire/Inertia), or --api for API-only apps.
  • Example: docker run -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-app --breeze --version=11

Notes:

  • Saves output to a volume (e.g., ./:/app), accessible locally.
  • Runs as a non-root laravel user for security.
  • No PHP extensions installed, keeping it lean for scaffolding.

After scaffolding, use our PHP-based images (e.g., laravel:8.3-fpm) to run your app or scaffold a Docker environment.

Scaffolding a Docker Environment for Existing Projects πŸ› οΈ

For existing Laravel projects, you can use our optional bash script to set up a complete Docker environment for development and production. This script, designed to run after your Laravel project is created, generates all necessary Docker files, including docker-compose.yml for development and production, Nginx configurations, and PHP settings. It also ensures Vite is Docker-ready by setting server.host to "0.0.0.0" in vite.config.js.

Usage: Run the script in your Laravel project directory (must contain artisan and app/):

bash -c "$(curl -fsSL https://raw.githubusercontent.com/redfieldchristabel/laravel-dockerize/main/scaffold/setup.sh)"

Platform Notes:

  • Linux: Run the script directly in your terminal.
  • Mac: Run the script directly in Terminal or iTerm2.
  • Windows: Run the script in WSL2 (Windows Subsystem for Linux 2). Install WSL2 with wsl --install and enable Docker Desktop’s WSL2 integration. Git Bash is not recommended due to potential compatibility issues.

What the Script Does:

  • Creates Docker Files: Generates docker-compose.yml (development), build.docker-compose.yml, prod.docker-compose.yml, and Dockerfiles for PHP, Nginx, and Vite.
  • Configures Nginx and PHP: Adds docker/nginx/conf/app.conf, docker/nginx/include/fpm-handler.conf, and docker/php/file.ini for seamless integration.
  • Sets Up Tools: Downloads helper scripts (art, cmpsr, pint, nd, iart) for Artisan, Composer, Node, and more.
  • Vite Compatibility: Modifies vite.config.js to set server.host to "0.0.0.0" (required for Docker), updating existing server blocks or adding a new one.
  • Environment Setup: Copies .env.example to .env if .env is missing.
  • Requirements: Needs curl and docker installed. Must be run in a Laravel project directory.

Using Helper Scripts: The script generates the following helper scripts in your project root to simplify running commands in Docker containers:

  • art: Run Artisan commands in the app container (uses laravel:8.3-cli).
    ./art migrate
    ./art queue:work --queue=high,default
  • cmpsr: Run Composer commands in the app container.
    ./cmpsr install
    ./cmpsr require laravel/ui
  • pint: Run Laravel Pint (code style fixer) in the app container.
    ./pint
    ./pint --test
  • nd: Run Node.js or npm commands in the vite container (for Vite-based projects).
    ./nd npm install
    ./nd npm run dev
  • iart: A shortcut for the php artisan command, primarily used when you are already inside the container shell (e.g., via docker exec or Portainer CLI).
    ./iart tinker

Example Output: After running, you’ll have:

  • docker-compose.yml: Development setup with app, nginx, mysql, redis, and more.
  • prod.docker-compose.yml: Production setup with minimal mounts (vendor, public).
  • vite.config.js: Updated with server: { host: "0.0.0.0" } for Vite in Docker.
  • Helper scripts (art, cmpsr, pint, nd, iart) in the project root for easy Artisan/Composer/Node commands.

Notes:

  • Run this script after creating your Laravel app (e.g., via laravel:installer).
  • The generated docker-compose.yml matches the Development Environment section.
  • Production files align with the Production Deployment section.
  • The script uses images from ghcr.io/redfieldchristabel/laravel (e.g., laravel:8.3-fpm).
  • If vite.config.js is missing, the script skips Vite configuration.

Proceed to Running Your Laravel App to start your Dockerized environment with docker-compose up -d.

Running Your Laravel App 🐘

Our PHP-based images are pre-loaded with Laravel’s essential extensions and optimized for Laravel 10, 11, and 12. Use them for development, CI/CD, or production.

Supported PHP Versions:

  • 8.1, 8.2, 8.3, 8.4 (latest patches via daily builds).
  • Tags: laravel:<version> (e.g., ghcr.io/redfieldchristabel/laravel:8.3, defaults to fpm) or <version>-<variant> (e.g., laravel:8.3-cli).

Variants:

  • cli πŸ–₯️: CLI PHP (Debian), great for Artisan, scripts, or cron jobs.
  • fpm 🌐: PHP-FPM (Debian), ideal for Nginx or Apache.
  • cli-alpine πŸ”οΈ: CLI PHP (Alpine), lightweight.
  • fpm-alpine πŸ”οΈ: PHP-FPM (Alpine), compact.
  • filament 🎨: CLI/FPM with Filament dependencies (e.g., laravel:8.3-cli-filament).
  • octane-swoole πŸš€: CLI with Swoole for Laravel Octane (e.g., laravel:8.3-cli-alpine-octane-swoole).

Example (Development): Use the docker-compose.yml from the Development Environment section (or generated by the scaffolding script) to spin up a Laravel app with Nginx, MySQL, Redis, and more.

Image Features ✨

Non-Root laravel User by Default πŸ”’

All images run as the non-root laravel user, reducing risks in development and production. No root privileges needed, keeping your apps secure! 😊

Built on Official PHP Images 🐳

Based on Docker Hub’s official PHP images, ensuring compatibility and reliability with standard tagging conventions.

Pre-Installed PHP Extensions πŸ”§

Includes Laravel 11/12’s minimum extensions:

  • bcmath
  • ctype
  • fileinfo
  • json
  • mbstring
  • openssl
  • pdo
  • pdo_mysql
  • tokenizer
  • xml

Add more (e.g., gd, imagick) via customization.

Exposed Ports 🌍

  • fpm variants 🌐: Port 9000 for PHP-FPM (Nginx/Apache).
  • cli variants πŸ–₯️: No ports, for command-line tasks.
  • installer image πŸ—οΈ: No ports, for scaffolding.
  • octane-swoole πŸš€: Port 8000 for Laravel Octane with Swoole.

Default Entrypoint πŸšͺ

Smart entrypoints for each image:

  • cli variants πŸ–₯️: Runs php (e.g., php artisan queue:work) via /usr/local/bin/docker-entrypoint.sh.
  • fpm variants 🌐: Starts PHP-FPM via /usr/local/bin/docker-entrypoint.sh.
  • installer image πŸ—οΈ: Runs laravel directly (e.g., new example-app).
  • octane-swoole πŸš€: Runs php artisan octane:start via /usr/local/bin/docker-php-entrypoint.

PHP images handle setup (permissions, composer install) and sync code in development (./:/var/www) or mount only vendor in production (./vendor:/var/www/vendor). The installer simplifies scaffolding to one command. Most apps don’t need custom entrypoints! 😊

Filament-Optimized Images 🎨

Filament projects? Use -filament images with pre-installed dependencies:

  • ghcr.io/redfieldchristabel/laravel:8.3-cli-filament
  • ghcr.io/redfieldchristabel/laravel:8.3-fpm-alpine-filament

Octane-Optimized Images πŸš€

For high-performance Laravel apps, use our Octane images with Swoole, the most popular and fastest server for Laravel Octane. These images include the Swoole binary pre-installed, so you don’t need to wait for a lengthy pecl install swoole. Laravel is not pre-installed; scaffold your app with the Laravel installer first.

  • Available for PHP 8.1, 8.2, 8.3, 8.4.
  • Tags: laravel:<version>-cli-<variant>-octane-swoole (e.g., laravel:8.3-cli-alpine-octane-swoole, laravel:8.3-cli-debian-octane-swoole).
  • Note: Currently supports only Swoole (no RoadRunner). SSL support requires extending the image (no openssl by default for minimal size).

Example (Running Octane):

docker run -v $(pwd):/var/www -p 8000:8000 ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
  • Assumes a Laravel app with Octane installed (composer require laravel/octane) in the current directory.
  • Starts Octane on http://localhost:8000.

Docker Best Practices 🐳

We follow best practices for efficient containers:

  • One Process Per Container βœ…: Separate containers for app, queue, scheduler (no bundled Nginx/Apache).
  • Unified Logging πŸ“œ: Logs to stdout for easy docker logs monitoring.

Development Environment with Docker Compose πŸ› οΈ

Set up a dev environment with this docker-compose.yml, syncing code for real-time edits. Includes app, nginx, mysql, redis, queue, scheduler, mailpit, and phpmyadmin. This file is automatically generated by the scaffolding script.

version: '3.8'

services:
  app:
    image: ghcr.io/redfieldchristabel/laravel:8.3-fpm
    volumes:
      - .:/var/www # Sync codebase
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - mysql
      - redis
    env_file:
      - .env

  queue:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "queue:work", "--queue=high,default"]
    volumes:
      - .:/var/www
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env

  scheduler:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "schedule:work"]
    volumes:
      - .:/var/www
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - .:/var/www
      - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./docker/nginx/include:/etc/nginx/include
    depends_on:
      - app

  mysql:
    image: mysql:8.0
    volumes:
      - mysql-data:/var/lib/mysql
    env_file:
      - .env
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      retries: 3
      timeout: 5s

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      retries: 3
      timeout: 5s

  mailpit:
    image: axllent/mailpit
    ports:
      - "8025:8025" # Web UI
      - "1025:1025" # SMTP
    environment:
      MP_MAX_MESSAGES: 5000
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1

  phpmyadmin:
    image: phpmyadmin
    ports:
      - "8081:80"
    environment:
      PMA_HOST: mysql
    depends_on:
      - mysql

volumes:
  mysql-data:
  redis-data:

Usage:

  1. Save as docker-compose.yml in your project root (or use the one generated by the scaffolding script).
  2. Create .env (e.g., DB_HOST=mysql, REDIS_HOST=redis, DB_DATABASE=laravel).
  3. Add docker/php/php.ini (e.g., memory_limit = 256M).
  4. Create docker/nginx/nginx.conf and docker/nginx/include/fpm-handler.conf (below, or use script-generated versions).
  5. Run docker-compose up -d and visit http://localhost or http://localhost:8081 (phpMyAdmin).

Example docker/nginx/nginx.conf:

server {
    listen 80 default_server;
    server_name localhost;
    client_max_body_size 120M;

    access_log /dev/stderr;
    error_log /dev/stderr;

    root /var/www/public;
    index index.php;

    # Remove trailing slash
    location ~ ^(.+)/$ {
        return 301 $1$is_args$args;
    }

    # Serve static files
    location ~* \.(css|js|gif|jpeg|jpg|png|webp|woff2|woff|ico)$ {
        root /var/www/public;
        add_header X-Serve-Type 'static';
    }

    # Soketi WebSocket
    location /app {
        proxy_pass http://soketi:6001;
        proxy_read_timeout 60;
        proxy_connect_timeout 60;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    location / {
        include include/fpm-handler.conf;
    }
}

Example docker/nginx/include/fpm-handler.conf:

add_header X-Serve-Type 'php';
add_header X-Serve-Uri '$uri';
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;

Notes:

  • Use 8.3-fpm for app to match production. For quick dev, try 8.3-cli with command: php artisan serve --host 0.0.0.0 --port 8000 and port 8000, or use 8.3-cli-alpine-octane-swoole for Octane with command: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000.
  • queue and scheduler use 8.3-cli in separate containers, per Docker best practices.
  • .:/var/www syncs code for fast composer update.
  • The scaffolding script generates these files automatically.

Customizing the Images πŸ”§

Add extensions or tweak PHP settings with a custom Dockerfile or volume mounts.

Installing Additional Extensions

Extend images for extensions like imagick or pgsql. Switch to root for installs, then revert to $user.

Example (Alpine):

FROM ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine

USER root
RUN apk add --no-cache imagemagick-dev && \
    pecl install imagick && \
    docker-php-ext-enable imagick && \
    rm -rf /var/cache/apk/*
USER $user

Example (Debian):

FROM ghcr.io/redfieldchristabel/laravel:8.3-cli

USER root
RUN apt-get update && apt-get install -y libpq-dev && \
    docker-php-ext-install pgsql && \
    apt-get clean && rm -rf /var/lib/apt/lists/*
USER $user

Example (Octane with SSL):

FROM ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole

USER root
RUN apk add --no-cache openssl-dev && \
    pecl install swoole --enable-openssl=yes && \
    docker-php-ext-enable swoole && \
    rm -rf /var/cache/apk/*
USER $user

Usage:

  1. Save Dockerfile in project root.
  2. Update docker-compose.yml:
    services:
      app:
        build:
          context: .
          dockerfile: Dockerfile
        volumes:
          - .:/var/www
  3. Run docker-compose up -d --build.

Modifying PHP Settings

Tweak php.ini (e.g., memory_limit):

  1. Create docker/php/php.ini:
    memory_limit = 256M
    upload_max_filesize = 64M
  2. Mount in docker-compose.yml:
    volumes:
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini

Note: Use default entrypoints for PHP images (docker-entrypoint.sh) to handle setup and logging. The installer uses laravel directly, and Octane uses docker-php-entrypoint for octane:start.

Production Deployment 🏭

For production, use fpm or fpm-alpine with Nginx, copying the codebase into the image for speed and mounting only ./vendor:/var/www/vendor. For Octane, use cli-alpine-octane-swoole or cli-debian-octane-swoole. The non-root laravel user ensures safety. Two docker-compose.yml options: standard or with Kong API Gateway. These files are generated by the scaffolding script as prod.docker-compose.yml.

Production Docker Compose (Standard)

version: '3.8'

services:
  app:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    ports:
      - "80:8000"
    depends_on:
      - mysql
      - redis
    env_file:
      - .env.production
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000"]
      interval: 30s
      retries: 3
      timeout: 10s

  queue:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "queue:work", "--queue=high,default"]
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env.production

  scheduler:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "schedule:work"]
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env.production

  mysql:
    image: mysql:8.0
    volumes:
      - mysql-data:/var/lib/mysql
    env_file:
      - .env.production
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      retries: 3
      timeout: 10s

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      retries: 3
      timeout: 10s

volumes:
  mysql-data:
  redis-data:

Production Docker Compose (with Kong API Gateway)

Uses Kong for routing, authentication, and rate-limiting, with Octane as the backend.

version: '3.8'

services:
  app:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - mysql
      - redis
    env_file:
      - .env.production
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000"]
      interval: 30s
      retries: 3
      timeout: 10s

  queue:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "queue:work", "--queue=high,default"]
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env.production

  scheduler:
    image: ghcr.io/redfieldchristabel/laravel:8.3-cli
    command: ["php", "artisan", "schedule:work"]
    volumes:
      - ./vendor:/var/www/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    depends_on:
      - app
      - mysql
      - redis
    env_file:
      - .env.production

  kong:
    image: kong:latest
    environment:
      KONG_DATABASE: "off"
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: "0.0.0.0:8001"
    ports:
      - "80:8000"
      - "443:8443"
      - "8001:8001"
    volumes:
      - ./docker/kong/kong.yml:/usr/local/kong/declarative/kong.yml:ro
    depends_on:
      - app
    networks:
      - kong

  mysql:
    image: mysql:8.0
    volumes:
      - mysql-data:/var/lib/mysql
    env_file:
      - .env.production
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      retries: 3
      timeout: 10s

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      retries: 3
      timeout: 10s

networks:
  kong:
    external: true

volumes:
  mysql-data:
  redis-data:

Example docker/kong/kong.yml:

_format_version: "3.0"
services:
  - name: laravel-app
    url: http://app:8000
    routes:
      - name: laravel-route
        paths:
          - /

Production Usage:

  1. Run composer install --no-dev --optimize-autoloader locally to generate vendor.
  2. Copy vendor, public, docker/, .env.production to the server.
  3. For Kong, add docker/kong/kong.yml.
  4. Run docker-compose -f prod.docker-compose.yml up -d (generated by the scaffolding script).
  5. Access at http://<server-ip> (standard) or Kong’s proxy.

Notes:

  • Standard: Octane on port 8000 (no Nginx needed for Octane).
  • Kong: Proxies via Kong; configure kong.yml for auth/rate-limiting.
  • Use .env.production (e.g., APP_ENV=production, DB_HOST=mysql).
  • Mount only ./vendor:/var/www/vendor for security.
  • Healthchecks and stdout logs ensure reliability.
  • The scaffolding script generates prod.docker-compose.yml for this setup.

Support and Contributions 🀝

Questions or ideas? Open an issue at redfieldchristabel/laravel-dockerize. Pull requests are welcome! Join us to make Laravel + Docker even better! πŸ˜„

Happy coding with Laravel! πŸ˜πŸŽ‰

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages