Skip to main content
This guide walks you through building and deploying a PHP API using Slim Framework to Magic Containers with GitHub Container Registry. You’ll need:
  • A GitHub account for source code and container registry
  • A bunny.net account with Magic Containers enabled

Create the Slim app

Create a new directory and initialize the project:
mkdir app-slim-api
cd app-slim-api
composer require slim/slim slim/psr7
Create the following files:
<?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) {
    $response->getBody()->write(json_encode(['message' => 'Hello from Bunny 🐰']));
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();

Run locally

Start the PHP development server:
php -S localhost:8080 -t public
Test the API:
curl http://localhost:8080/

Create the Dockerfile

Dockerfile
FROM php:8.3-apache

RUN a2enmod rewrite

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY composer.json .
RUN composer install --no-dev --optimize-autoloader

COPY public/ public/

RUN sed -i 's|/var/www/html|/var/www/html/public|g' /etc/apache2/sites-available/000-default.conf
RUN echo '<Directory /var/www/html/public>\n\
    AllowOverride All\n\
    Require all granted\n\
</Directory>' >> /etc/apache2/apache2.conf

RUN echo 'RewriteEngine On\n\
RewriteCond %{REQUEST_FILENAME} !-f\n\
RewriteCond %{REQUEST_FILENAME} !-d\n\
RewriteRule ^ index.php [QSA,L]' > public/.htaccess

EXPOSE 80

Build and push to GitHub Container Registry

Create .github/workflows/build.yml to automatically build and push on every commit to main:
.github/workflows/build.yml
name: Build and Push

on:
  push:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v4

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
Push your code to trigger the workflow:
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/YOUR_USERNAME/app-slim-api.git
git push -u origin main
If your package is private, set the visibility to Public in GitHub or configure Magic Containers with registry credentials.

Deploy to Magic Containers

1

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.
2

Add a container

Click Add Container, then configure:
FieldValue
RegistryGitHub Container Registry
ImageYOUR_USERNAME/{imageName}
Taglatest
3

Add an endpoint

Go to the Endpoints tab, click Add New Endpoint, and set the container port to 80.
4

Deploy

Click Add Container, then Next Step, and Confirm and Create.
For more details, see the quickstart guide.

Test your API

curl https://mc-xxx.bunny.run/
Response
{ "message": "Hello from Bunny 🐰" }
You can add a custom hostname from the Endpoints section in your app settings.

Connect a database

You can connect your app to Bunny Database directly from the dashboard:
  1. Go to Database > [Your Database] > Access
  2. Click Generate Tokens
  3. Click Add Secrets to Magic Container App
  4. Select your app
The DB_URL and DB_TOKEN environment variables are now available in your app. Install the libSQL PHP extension or use HTTP requests to connect:
<?php

$dbUrl = getenv('DB_URL');
$dbToken = getenv('DB_TOKEN');

$ch = curl_init($dbUrl);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $dbToken,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'statements' => ['SELECT * FROM users']
    ]),
]);

$result = json_decode(curl_exec($ch), true);
curl_close($ch);
See the Bunny Database documentation for more details.

Next steps

  1. Automate deploys with GitHub Actions
  2. Add a custom hostname
  3. Add a persistent volume