- A GitHub account for source code and container registry
- A bunny.net account with Magic Containers enabled
Create the Laravel app
Create a new Laravel project:.env to use MariaDB:
.env
Create the Nginx config
Createdocker/nginx.conf:
docker/nginx.conf
Create the supervisord config
The app container runs both PHP-FPM and Nginx using supervisord. Createdocker/supervisord.conf:
docker/supervisord.conf
Create the entrypoint script
Createdocker/entrypoint.sh:
docker/entrypoint.sh
The entrypoint creates an empty
.env file so Laravel reads configuration
from the container’s environment variables instead of a file. Config caching
happens at startup (not at build time) so it picks up the runtime environment.
The script also waits for MariaDB to be ready before running migrations.Create the Dockerfile
Dockerfile
.dockerignore to keep the .env file out of the image:
.dockerignore
Create the docker-compose file
Createdocker-compose.yml for local development:
docker-compose.yml
The
docker-compose.yml uses DB_HOST=db (the service name) for local
development. In Magic Containers, the bunny.json sets DB_HOST=127.0.0.1
since containers share the same localhost network.Run locally
Generate an app key
Generate a key to use in production:Build and push to GitHub Container Registry
- GitHub Actions
- Docker CLI
Create Push your code to trigger the workflow:
.github/workflows/deploy.yml to automatically build and push on every commit to main:.github/workflows/build.yml
If your package is private, set the visibility to Public in GitHub or
configure Magic Containers with registry
credentials.
Deploy to Magic Containers
Create a new app
In the bunny.net dashboard, go to Magic Containers and click Add
App. Enter a name and select your deployment option.
Add a container
Click Add Container, then configure:
| Field | Value |
|---|---|
| Registry | GitHub Container Registry |
| Image | YOUR_USERNAME/{imageName} |
| Tag | latest for Docker CLI, or the commit SHA from your GitHub Actions workflow |
App container
- Image:
ghcr.io/<your-username>/app-laravel:latest - Endpoint: port
80 - Environment variables:
APP_ENV=productionAPP_DEBUG=falseAPP_KEY= the key fromphp artisan key:generate --showDB_CONNECTION=mariadbDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=laravelDB_USERNAME=laravelDB_PASSWORD=laravel
Database container
- Image:
mariadb:11 - Volume:
/var/lib/mysql - Environment variables:
MARIADB_DATABASE=laravelMARIADB_USER=laravelMARIADB_PASSWORD=laravelMARIADB_ROOT_PASSWORD=root
Test your app
You can add a custom hostname from the Endpoints section in your app settings.
Continuous deployment
The workflow automatically deploys to Magic Containers on every push tomain. Configure the following in your repository settings:
- Variable
APP_ID- your Magic Containers app ID - Secret
BUNNYNET_API_KEY- your bunny.net API key
Key differences for Magic Containers
When deploying Laravel to Magic Containers, there are a few important things to keep in mind:| Topic | What to do | Why |
|---|---|---|
DB_HOST | Use 127.0.0.1, not localhost | PHP/PDO treats localhost as a Unix socket. Magic Containers share a localhost network, so TCP via 127.0.0.1 is required. |
| Config caching | Cache at startup, not build time | php artisan config:cache in the Dockerfile bakes in build-time values. Cache in the entrypoint so runtime env vars are used. |
.env file | Exclude from Docker image | Add .env to .dockerignore and touch .env in the entrypoint. This ensures Laravel reads from container environment variables. |
| Migrations | Run at startup | The entrypoint waits for MariaDB, then runs php artisan migrate --force so the database is always up to date. |
| App key | Set via environment variable | Generate with php artisan key:generate --show and set APP_KEY in the container environment. |