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

# Redis

> Deploy Redis to Magic Containers

This guide walks you through deploying Redis to Magic Containers, either as a standalone container or as part of a [multi-container](/docs/magic-containers/multi-container.md) app alongside your application.

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

## Quickstart

**1. Create a new app**

Go to the [bunny.net dashboard](https://dash.bunny.net), select **Magic Containers**, and click **Add App**. Select **Single region deployment**.

> [!WARNING]
>
> Databases should use single region deployment with a single instance. Each pod gets its own dedicated volume with no data replication — this applies both across regions and within the same region. Scaling to multiple pods or regions would result in separate, isolated databases each with their own data.

**2. Add the Redis container**

Click **Add Container** and configure the image:

* **Registry**: Docker Hub
* **Image**: `library/redis`
* **Tag**: `7-alpine`

Magic Containers will automatically detect the required endpoint and environment variables for the image.

**3. Add a persistent volume**

In the **Volumes** section of the container settings, add a volume:

* **Name**: `redis-data`
* **Mount path**: `/data`

This ensures your data persists across restarts and redeployments. Without a volume, all data is lost when the container stops.

See [persistent volumes](/docs/magic-containers/persistent-volumes.md) for more details on volume behavior and pricing.

**4. Deploy**

Review your settings and click **Confirm and Create**.

## Redis 8+ volume permissions

Redis 8 changed its default user from `root` to a non-root user (`uid 999`, group `redis`). When Magic Containers mounts a persistent volume at `/data`, the directory is owned by `root`. This means the Redis process cannot write its RDB/AOF persistence files to this directory, causing the container to fail on startup with an error like:

```
Failed opening the temp RDB file temp-26.rdb (in server root dir /data) for saving: Permission denied
```

To fix this, configure a **Startup Command** that changes the ownership of the `/data` directory before starting Redis. In your container settings, set the startup command as:

```json theme={null}
["sh", "-c", "chown -R 999:999 /data && exec /usr/local/bin/docker-entrypoint.sh redis-server"]
```

> [!WARNING]
>
> The startup command must be specified as a array, not a string. This ensures proper argument parsing and execution.

This command:

1. Changes ownership of `/data` to the `redis` user (uid 999)
2. Executes the standard Redis entrypoint script

> [!NOTE]
>
> Redis 7 and earlier versions run as `root` by default and do not have this issue. If you're using Redis 7 (e.g., `redis:7-alpine`), no startup command is needed.

> [!NOTE]
>
> Redis has no authentication enabled by default. It's recommended to set a
> password even if Redis is not exposed externally. Other containers in the same
> pod can access the network. Set a password by configuring the container
> command to `redis-server --requirepass YOUR_PASSWORD`, and update your
> connection string to `redis://:YOUR_PASSWORD@127.0.0.1:6379`.

> [!NOTE]
>
> Redis uses `/data` as its default data directory. The official image is
> configured to use append-only file (AOF) persistence by default, which writes
> every operation to disk in the mounted volume.

## Connect from your app

In a [multi-container](/docs/magic-containers/multi-container.md) setup, your app and Redis share the same localhost network. Connect using `127.0.0.1` and the default port `6379`.

**Connection string**

```
redis://127.0.0.1:6379
```

**Node.js**

```javascript theme={null}
import { createClient } from "redis";

const client = createClient({
  url: process.env.REDIS_URL,
});

await client.connect();
await client.set("key", "value");
const value = await client.get("key");
```

**Go**

```go theme={null}
import (
	"context"
	"os"

	"github.com/redis/go-redis/v9"
)

client := redis.NewClient(&redis.Options{
	Addr: "127.0.0.1:6379",
})

ctx := context.Background()
client.Set(ctx, "key", "value", 0)
val, err := client.Get(ctx, "key").Result()
```

**Python**

```python theme={null}
import redis

r = redis.Redis(host="127.0.0.1", port=6379)

r.set("key", "value")
value = r.get("key")
```

**PHP**

```php theme={null}
<?php

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$redis->set('key', 'value');
$value = $redis->get('key');
```

## Multi-container example

A typical setup pairs Redis with your application. When configuring the app, add two containers:

### App container

* **Image**: your app image (e.g. `ghcr.io/<your-username>/my-app:latest`)
* **Endpoint**: the port your app listens on
* **Environment variables**:
  * `REDIS_URL` = `redis://127.0.0.1:6379`

### Redis container

* **Image**: `library/redis:7-alpine`
* **Volume**: mount path `/data`

> [!NOTE]
>
> Both containers share the same localhost network, so your app connects to
> Redis at `127.0.0.1:6379`. See [multi-container
> apps](/docs/magic-containers/multi-container.md) for more details.

## External access

To connect to Redis from outside Magic Containers (e.g. from your local terminal), add an [Anycast endpoint](/docs/magic-containers/endpoints.md):

1. Go to your app's **Endpoints** tab and click **Add New Endpoint**
2. Select **Anycast** as the type
3. Set **Container Port** to `6379`
4. Set **Exposed Port** to `6379`
5. Click **Add Endpoint**

Then connect using the Anycast IP and the **exposed port**:

```bash theme={null}
redis-cli -h <anycast-ip> -p <exposed-port>
```

> [!NOTE]
>
> The exposed port and container port may differ. When connecting externally,
> always use the exposed port shown in your endpoint configuration.

> [!WARNING]
>
> Redis has no authentication enabled by default. Exposing it to the internet
> without a password is a serious security risk. Consider setting a password by
> using the container command `redis-server --requirepass YOUR_PASSWORD`, and
> removing the Anycast endpoint when external access is no longer needed.


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