> ## Documentation Index
> Fetch the complete documentation index at: https://bunny.net/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby on Rails

> Deploy a Ruby on Rails application to Magic Containers

This guide walks you through building and deploying a Ruby on Rails application to Magic Containers with GitHub Container Registry. You'll need:

* A GitHub account for source code and container registry
* Ruby 3.2+ installed locally

> [!TIP]
>
> Don't have a bunny.net account yet? [Sign up](https://dash.bunny.net/auth/register) and enable Magic Containers to get started.

## Create the Rails app

> [tab] Full-stack
>
> Create a new Rails application with views and assets:
>
> ```bash theme={null}
> rails new app-rails
> cd app-rails
> ```
>
> Generate a controller with a view:
>
> ```bash theme={null}
> bin/rails generate controller Home index --skip-routes
> ```
>
> Add the route in `config/routes.rb`:
>
> ```ruby config/routes.rb theme={null}
> Rails.application.routes.draw do
>   root "home#index"
>   get "up", to: "rails/health#show", as: :rails_health_check
> end
> ```
>
> Update the view in `app/views/home/index.html.erb`:
>
> ```erb app/views/home/index.html.erb theme={null}
> <h1>Hello from Bunny 🐰</h1>
> ```

> [tab] API only
>
> Create a new Rails API application:
>
> ```bash theme={null}
> rails new app-rails --api
> cd app-rails
> ```
>
> Generate a controller with a simple endpoint:
>
> ```bash theme={null}
> bin/rails generate controller Api::Health index --skip-routes
> ```
>
> Add the route in `config/routes.rb`:
>
> ```ruby config/routes.rb theme={null}
> Rails.application.routes.draw do
>   get "/", to: "api/health#index"
>   get "up", to: "rails/health#show", as: :rails_health_check
> end
> ```
>
> Update the controller:
>
> ```ruby app/controllers/api/health_controller.rb theme={null}
> class Api::HealthController < ApplicationController
>   def index
>     render json: { message: "Hello from Bunny 🐰" }
>   end
> end
> ```

## Run locally

Start the Rails development server:

```bash theme={null}
bin/rails server
```

Test the app at [http://localhost:3000](http://localhost:3000), or with curl:

```bash theme={null}
curl http://localhost:3000/
```

## Prepare for production

Rails 7.1+ automatically generates a production-ready `Dockerfile` in your project root.

Before building, prepare the app:

```bash theme={null}
bin/rails db:migrate
rm config/credentials.yml.enc
```

The credentials file is removed since we'll use environment variables instead.

> [!NOTE]
>
> If you're using an older Rails version, you can generate a Dockerfile with:
> `bash bin/rails generate dockerfile `

## Review the Dockerfile

Rails 7.1+ generates a production-ready, multi-stage Dockerfile that includes:

* **jemalloc** for reduced memory usage
* **Bootsnap** precompilation for faster boot times
* **Non-root user** for security
* **Asset precompilation** (full-stack apps only)
* **Thruster** HTTP/2 proxy (full-stack apps only)

## Build and push to GitHub Container Registry

> [tab] GitHub Actions
>
> Create `.github/workflows/build.yml` to automatically build and push on every commit to `main`:
>
> ```yaml .github/workflows/build.yml theme={null}
> 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 }}:${{ github.sha }}
>
>       - name: Update container image on Magic Containers
>         uses: BunnyWay/actions/container-update-image@main
>         with:
>           app_id: ${{ vars.APP_ID }}
>           api_key: ${{ secrets.BUNNYNET_API_KEY }}
>           container: app
>           image_tag: "${{ github.sha }}"
> ```
>
> Push your code to trigger the workflow:
>
> ```bash theme={null}
> git init
> git add .
> git commit -m "Initial commit"
> git remote add origin https://github.com/YOUR_USERNAME/app-rails.git
> git push -u origin main
> ```

> [tab] Docker CLI
>
> Build and push manually from your local machine.
>
> **1. Create a Personal Access Token**
>
> Go to [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens) and create a token with `write:packages` scope.
>
> **2. Log in to GitHub Container Registry**
>
> ```bash theme={null}
> export CR_PAT=your_personal_access_token
> echo $CR_PAT | docker login ghcr.io -u YOUR_USERNAME --password-stdin
> ```
>
> **3. Build the image**
>
> ```bash theme={null}
> docker build --platform linux/amd64 -t ghcr.io/YOUR_USERNAME/app-rails:latest .
> ```
>
> > [!NOTE]
> >
> > Magic Containers only supports images built for the **linux/amd64** architecture. The `--platform` flag ensures compatibility regardless of your local machine's architecture.
>
> **4. Push to registry**
>
> ```bash theme={null}
> docker push ghcr.io/YOUR_USERNAME/app-rails:latest
> ```

> [!NOTE]
>
> If your package is private, set the visibility to **Public** in GitHub or
> [configure Magic Containers with registry
> credentials](https://bunny.net/docs/magic-containers/image-registries.md).

## 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:

| Field | Value |
| - | - |
| Registry | GitHub Container Registry |
| Image | `YOUR_USERNAME/app-rails` |
| Tag | `latest` |

**3. Configure environment variables**

Go to the **Environment Variables** tab and add:

| Variable | Value |
| - | - |
| `SECRET_KEY_BASE` | Generate with `bin/rails secret` |

**4. Add an endpoint**

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

**5. Deploy**

Click **Add Container**, then **Next Step**, and **Confirm and Create**.

For more details, see the [quickstart guide](https://bunny.net/docs/magic-containers/quickstart.md).

## Test your app

```bash theme={null}
curl https://mc-xxx.bunny.run/
```

```json Response theme={null}
{ "message": "Hello from Bunny 🐰" }
```

> [!NOTE]
>
> You can [add a custom hostname](https://bunny.net/docs/magic-containers/endpoints.md) from the **Endpoints** section in your app settings.

## Add persistent storage

Magic Containers are ephemeral, so data stored locally is lost on restarts. For Rails apps that need to persist data (Active Storage uploads, etc.), attach a [Persistent Volume](https://bunny.net/docs/magic-containers/persistent-volumes.md).

**1. Add a volume**

Go to your app's **Volumes** tab and click **Add Volume**. Set the mount path to `/rails/storage` and choose an initial size.

**2. Configure Rails storage**

Update `config/environments/production.rb` to use the volume for Active Storage:

```ruby config/environments/production.rb theme={null}
config.active_storage.service = :local
```

**3. Configure SQLite (optional)**

To persist your SQLite database, update `config/database.yml`:

```yaml config/database.yml theme={null}
production:
  <<: *default
  database: /rails/storage/production.sqlite3
```

See the [Persistent Volumes documentation](https://bunny.net/docs/magic-containers/persistent-volumes.md) for more details.

## Next steps

1. [Automate deploys with GitHub Actions](https://bunny.net/docs/magic-containers/deploy-with-github-actions.md)
2. [Add a custom hostname](https://bunny.net/docs/magic-containers/endpoints.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.