|
1 | 1 | # Laravel Docker Base
|
2 | 2 |
|
3 |
| -> Docker base image for Laravel production applications |
| 3 | +> Docker base image for **Laravel production** applications using **FrankenPHP** |
| 4 | +
|
| 5 | +This repository provides a minimal yet comprehensive Docker *base* image for deploying |
| 6 | +your Laravel application in production. |
| 7 | +**It is intended purely as a foundation image** — you should **extend** it in your |
| 8 | +project rather than run it directly [*(see below)*](#sample-application-dockerfile). |
| 9 | + |
| 10 | +## Release Tags |
| 11 | + |
| 12 | +- **Development *(`:dev`)***: Built automatically from every commit to the `main` branch. |
| 13 | +- **Production *(`:vX.Y.Z`)***: Tagged versions for stable releases, with `:latest` |
| 14 | + pointing to the most recent version. |
| 15 | + |
| 16 | +## Table of Contents |
| 17 | + |
| 18 | +- [Release Tags](#release-tags) |
| 19 | +- [Table of Contents](#table-of-contents) |
| 20 | +- [Features](#features) |
| 21 | +- [Getting Started](#getting-started) |
| 22 | +- [Environment Variables](#environment-variables) |
| 23 | +- [Container Modes](#container-modes) |
| 24 | + - [`app`](#app) |
| 25 | + - [`worker`](#worker) |
| 26 | + - [`horizon`](#horizon) |
| 27 | + - [`scheduler`](#scheduler) |
| 28 | +- [Manual Setup vs Automatic Setup](#manual-setup-vs-automatic-setup) |
| 29 | +- [Testing Connections](#testing-connections) |
| 30 | +- [Contributing](#contributing) |
| 31 | +- [License](#license) |
| 32 | + |
| 33 | +## Features |
| 34 | + |
| 35 | +- **FrankenPHP**: Powered by the [FrankenPHP][] runtime, providing a performant way to |
| 36 | + serve Laravel. |
| 37 | +- **Container Modes**: Easily switch between `app`, `worker`, `horizon`, and `scheduler` |
| 38 | + modes. |
| 39 | +- **Connection Testing**: Optional checks for database, cache, S3, and SMTP connections |
| 40 | + before serving the app. |
| 41 | +- **Automatic Setup**: Laravel migrations, caches *(config, routes, views, events)*, and |
| 42 | + storage linking happen by default. |
| 43 | +- **PHP Extensions**: Commonly used PHP extensions for a typical Laravel application |
| 44 | + *(bcmath, bz2, intl, redis, etc.)*. |
| 45 | + |
| 46 | +## Getting Started |
| 47 | + |
| 48 | +Because this is a base image, you’ll typically reference it in your own `Dockerfile`. |
| 49 | +We strongly recommend using multi-stage builds to handle dependencies |
| 50 | +*(e.g., installing Composer or Node packages)*, ensuring your final production image is as |
| 51 | +lean as possible. |
| 52 | + |
| 53 | +Below is an example `Dockerfile` that extends `laravel-docker-base`: |
| 54 | + |
| 55 | +```dockerfile |
| 56 | +FROM ghcr.io/kloudkit/laravel-docker-base:latest AS base |
| 57 | + |
| 58 | +#################################### Vendor #################################### |
| 59 | + |
| 60 | +FROM base AS vendor |
| 61 | +WORKDIR /build |
| 62 | + |
| 63 | +COPY composer.json . |
| 64 | +COPY composer.lock . |
| 65 | +COPY packages packages |
| 66 | + |
| 67 | +RUN composer install \ |
| 68 | + --ignore-platform-reqs \ |
| 69 | + --no-cache \ |
| 70 | + --no-interaction \ |
| 71 | + --no-scripts \ |
| 72 | + --prefer-dist |
| 73 | + |
| 74 | +#################################### NodeJS #################################### |
| 75 | + |
| 76 | +FROM node:latest AS client |
| 77 | +WORKDIR /build |
| 78 | + |
| 79 | +COPY package*.json . |
| 80 | +COPY postcss.config.js . |
| 81 | +COPY tailwind.config.js . |
| 82 | +COPY vite.config.js . |
| 83 | + |
| 84 | +COPY resources resources |
| 85 | +COPY --from=vendor /build/vendor vendor |
| 86 | + |
| 87 | +RUN npm install && npm run build |
| 88 | + |
| 89 | +##################################### App ###################################### |
| 90 | + |
| 91 | +FROM base |
| 92 | + |
| 93 | +COPY --chown=laravel:laravel composer.json composer.json |
| 94 | +COPY --chown=laravel:laravel composer.lock composer.lock |
| 95 | +COPY --chown=laravel:laravel app app |
| 96 | +COPY --chown=laravel:laravel bootstrap bootstrap |
| 97 | +COPY --chown=laravel:laravel config config |
| 98 | +COPY --chown=laravel:laravel database database |
| 99 | +COPY --chown=laravel:laravel packages packages |
| 100 | +COPY --chown=laravel:laravel public public |
| 101 | +COPY --chown=laravel:laravel resources resources |
| 102 | +COPY --chown=laravel:laravel routes routes |
| 103 | +COPY --chown=laravel:laravel --from=client /build/public public |
| 104 | + |
| 105 | +RUN composer install \ |
| 106 | + --no-ansi \ |
| 107 | + --no-dev \ |
| 108 | + --no-interaction \ |
| 109 | + --no-progress \ |
| 110 | + --no-scripts \ |
| 111 | + --prefer-dist \ |
| 112 | + --quiet \ |
| 113 | + && composer dump-autoload \ |
| 114 | + --classmap-authoritative \ |
| 115 | + --no-dev |
| 116 | +``` |
4 | 117 |
|
5 | 118 | ## Environment Variables
|
6 | 119 |
|
7 |
| -| `env` | Default | Mode | |
8 |
| -| -------------------------- | -------------- | ------ | |
9 |
| -| `APP_DEBUG` | `false` | `*` | |
10 |
| -| `APP_ENV` | `"production"` | `*` | |
11 |
| -| `CONTAINER_MANUAL_SETUP` | ➖ | `*` | |
12 |
| -| `CONTAINER_MODE` | `"app"` | `*` | |
13 |
| -| `CONTAINER_PORT` | `8000` | app | |
14 |
| -| `CONTAINER_WORKER_DELAY` | `10` | worker | |
15 |
| -| `CONTAINER_WORKER_SLEEP` | `5` | worker | |
16 |
| -| `CONTAINER_WORKER_TRIES` | `3` | worker | |
17 |
| -| `CONTAINER_WORKER_TIMEOUT` | `300` | worker | |
18 |
| -| `TEST_DB_CONNECTION` | `true` | `*` | |
19 |
| -| `TEST_CACHE_CONNECTION` | `true` | `*` | |
20 |
| -| `TEST_CONNECTION_TIMEOUT` | `10` | `*` | |
| 120 | +You can customize the container by setting the following environment variables: |
| 121 | + |
| 122 | +| **Variable** | **Default** | **Modes** | **Description** | |
| 123 | +| -------------------------- | -------------- | --------- | --------------------------------------------------------------------- | |
| 124 | +| `APP_DEBUG` | `false` | `*` | Laravel debug mode | |
| 125 | +| `APP_ENV` | `"production"` | `*` | Laravel environment name | |
| 126 | +| `CONTAINER_MANUAL_SETUP` | *(empty)* | `*` | Skips automatic setup *(migrations, caching, etc.)* | |
| 127 | +| `CONTAINER_MODE` | `"app"` | `*` | Define the container mode *(see [Container Modes](#container-modes))* | |
| 128 | +| `CONTAINER_PORT` | `8000` | `app` | Port FrankenPHP listens to *(when in `app` mode)* | |
| 129 | +| `CONTAINER_WORKER_DELAY` | `10` | `worker` | `queue:work` delay | |
| 130 | +| `CONTAINER_WORKER_SLEEP` | `5` | `worker` | `queue:work` sleep | |
| 131 | +| `CONTAINER_WORKER_TRIES` | `3` | `worker` | `queue:work` tries | |
| 132 | +| `CONTAINER_WORKER_TIMEOUT` | `300` | `worker` | `queue:work` timeout | |
| 133 | +| `TEST_CACHE_CONNECTION` | `true` | `*` | Test cache connection on startup | |
| 134 | +| `TEST_DB_CONNECTION` | `true` | `*` | Test database connection on startup | |
| 135 | +| `TEST_S3_CONNECTION` | `false` | `*` | Test S3 connection on startup | |
| 136 | +| `TEST_SMTP_CONNECTION` | `false` | `*` | Test SMTP connection on startup | |
| 137 | +| `TEST_CONNECTION_TIMEOUT` | `10` | `*` | Seconds to attempt each connection test before failing | |
| 138 | + |
| 139 | +## Container Modes |
| 140 | + |
| 141 | +This image supports multiple container modes via the `CONTAINER_MODE` variable, each |
| 142 | +focusing on a specific type of service: |
| 143 | + |
| 144 | +### `app` |
| 145 | + |
| 146 | +- Serves the Laravel application using FrankenPHP on port `CONTAINER_PORT` |
| 147 | + *(default `8000`)*. |
| 148 | +- Ideal for load-balanced or standalone app containers. |
| 149 | + |
| 150 | +### `worker` |
| 151 | + |
| 152 | +- Runs `php artisan queue:work` with the provided settings *(`CONTAINER_WORKER_*`)*. |
| 153 | +- Suitable for handling asynchronous jobs. |
| 154 | + |
| 155 | +### `horizon` |
| 156 | + |
| 157 | +- Runs `php artisan horizon`. |
| 158 | +- Ideal if you prefer Laravel Horizon for managing queues. |
| 159 | + |
| 160 | +### `scheduler` |
| 161 | + |
| 162 | +- Runs `php artisan schedule:work` in the foreground. |
| 163 | +- Great for cron-like, scheduled tasks. |
| 164 | + |
| 165 | +## Manual Setup vs Automatic Setup |
| 166 | + |
| 167 | +By default, this image **automatically**: |
| 168 | + |
| 169 | +- Tests connections *(DB, cache, S3, SMTP)* if `TEST_*` variables are set to `true`. |
| 170 | +- Runs `php artisan migrate --force`. |
| 171 | +- Creates the storage symlink *(if not already present)*. |
| 172 | +- Caches config, events, routes, and views. |
| 173 | + |
| 174 | +If you need to skip these steps *(e.g., you manage migrations separately)*, set |
| 175 | +`CONTAINER_MANUAL_SETUP` to any non-empty value, and the container will **skip** all |
| 176 | +auto-setup steps, running the [Container Mode](#container-modes) command directly. |
| 177 | + |
| 178 | +## Testing Connections |
| 179 | + |
| 180 | +The image's entrypoint can optionally test common connections before starting |
| 181 | +*(or failing fast)*, depending on environment variables: |
| 182 | + |
| 183 | +- **Database:**: Controlled by `TEST_DB_CONNECTION` *(`true` by default)*. |
| 184 | +- **Cache:**: Controlled by `TEST_CACHE_CONNECTION` *(`true` by default)*. |
| 185 | +- **S3:**: Controlled by `TEST_S3_CONNECTION` *(`false` by default)*. |
| 186 | +- **SMTP:**: Controlled by `TEST_SMTP_CONNECTION` *(`false` by default)*. |
| 187 | + |
| 188 | +Each test will attempt a connection for up to `TEST_CONNECTION_TIMEOUT` seconds before |
| 189 | +giving up and exiting with a non-zero code. |
| 190 | +This ensures your container won’t fully start unless its dependencies are actually ready. |
| 191 | + |
| 192 | +> [!IMPORTANT] |
| 193 | +> Ensure you provide the correct authentication environment variables |
| 194 | +> *(DB_HOST, DB_USERNAME, DB_PASSWORD, etc.)* for any connections you enable. |
| 195 | +
|
| 196 | +## Contributing |
| 197 | + |
| 198 | +Contributions are welcome! |
| 199 | +Please open issues or submit pull requests for any improvements or fixes you find. |
| 200 | + |
| 201 | +## License |
| 202 | + |
| 203 | +This project is open-sourced software licensed under the [MIT license](LICENSE). |
| 204 | +Feel free to adapt it to your needs. |
| 205 | + |
| 206 | +[FrankenPHP]: https://frankenphp.dev |
0 commit comments