News & Updates

How to Run Supabase Locally with Docker: The Ultimate Development Guide

By Simone Delaney 7 min read 1479 views

How to Run Supabase Locally with Docker: The Ultimate Development Guide

Why Use Supabase in a Local Docker Environment?

Developing against a live cloud instance can feel like walking on thin ice—any change might affect real users or incur unexpected costs. By spinning up a Supabase Local Docker stack, you get a sandbox that mirrors the production API while staying safely on your machine. The result is faster feedback loops, repeatable test data, and the freedom to tweak Postgres extensions without a gatekeeper.

Docker also isolates dependencies, meaning your team members can start the same environment with a single command, no matter whether they run macOS, Windows, or Linux. In short, local Docker turns the “cloud” into a controllable, version‑controlled service.

Prerequisites Before You Start

  • Docker Engine (or Docker Desktop) version 20.10+ installed.
  • Docker Compose (usually bundled with Docker Desktop).
  • A recent git client to clone the Supabase repo.
  • Basic familiarity with terminal commands and environment variables.

If any of these are missing, pause the guide and install them first. The rest of the steps assume you can run docker and docker-compose from your shell.

Setting Up the Docker Compose File

The heart of the setup is a docker-compose.yml that defines Supabase’s core services: Postgres, Kong (the API gateway), GoTrue (auth), Realtime, and the storage server. Supabase provides an official example, but you can trim it down if you only need a subset.

version: '3.8'

services:

db:

image: supabase/postgres:15.1.0

environment:

POSTGRES_PASSWORD: postgres

POSTGRES_DB: postgres

ports:

- "5432:5432"

kong:

image: supabase/kong:0.34.1

depends_on:

- db

environment:

KONG_DATABASE: "off"

KONG_DECLARATIVE_CONFIG: /home/kong/kong.yml

ports:

- "8000:8000"

auth:

image: supabase/gotrue:2.36.1

depends_on:

- db

environment:

GOTRUE_DB_DRIVER: postgres

GOTRUE_DB_DATABASE_URL: postgres://postgres:postgres@db:5432/postgres

ports:

- "9999:9999"

realtime:

image: supabase/realtime:2.20.2

depends_on:

- db

environment:

DB_HOST: db

DB_PORT: 5432

ports:

- "4000:4000"

storage:

image: supabase/storage:0.20.0

depends_on:

- db

environment:

POSTGREST_URL: http://kong:8000

ports:

- "5000:5000"

Save this snippet as docker-compose.yml in a dedicated folder. The version numbers reflect the latest stable releases at the time of writing, but you can always check Supabase’s Docker Hub pages for newer tags.

Launching Supabase with Docker Compose

Open a terminal, navigate to the folder containing the compose file, and run:

docker-compose up -d

The -d flag detaches the containers, letting you keep working in the same shell. Docker will pull the images the first time—expect a few minutes depending on your network speed. Afterward, verify that every service is healthy:

docker-compose ps

If any container shows Exit or Restarting, inspect the logs with docker-compose logs <service> to pinpoint the issue. Common hiccups include port conflicts (especially if you already run a local Postgres) or insufficient memory allocation for Docker.

Connecting Your App to the Local Instance

Supabase’s JavaScript client reads configuration from an object, typically called supabaseUrl and supabaseKey. For a local Docker stack, point the URL to the Kong gateway:

const supabase = createClient(

'http://localhost:8000',

'anon-key-placeholder' // replace with actual JWT from GoTrue if needed

);

The default anon key is eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (truncated for brevity). In production you’d swap it for a secret stored in environment variables. Once the client is instantiated, you can query tables, trigger auth flows, or listen to realtime updates exactly as you would with the cloud service.

Troubleshooting Common Hiccups

Port already in use. Docker will refuse to start a service if the host port is occupied. Either stop the conflicting process or change the host port mapping in docker-compose.yml (e.g., "5433:5432" for Postgres).

Database migrations not applied. Supabase relies on a set of migration scripts located in the supabase/migrations folder of the repo. To run them manually, exec into the db container and use psql:

docker exec -it <project>_db_1 bash

psql -U postgres -d postgres -f /docker-entrypoint-initdb.d/migrations.sql

Most of the time the official images handle migrations automatically, but custom schemas may need a manual step.

Realtime not receiving events. Ensure the realtime service can reach the db container on port 5432. Network misconfigurations inside Docker Desktop (especially on Windows) sometimes block inter‑container traffic. Restarting Docker or adding an explicit network section often resolves the issue.

Next Steps: Extending Your Local Setup

Now that the core stack runs, you can experiment with add‑ons such as pgbouncer for connection pooling, or swap the storage backend for a MinIO container to mimic S3. For CI pipelines, spin up the same compose file in a GitHub Actions job and run integration tests against it—this guarantees parity between local development and automated testing.

Finally, consider version‑controlling the docker-compose.yml and any custom SQL migrations. When teammates pull the repository, a single docker-compose up -d reproduces the exact same environment, cutting down onboarding time dramatically.

FAQ

Can I run Supabase locally without Docker?

Yes, you could install each service manually (Postgres, GoTrue, Kong, etc.), but Docker bundles the correct versions and configures networking automatically, making it the most pragmatic choice for most developers.

Do I need an internet connection after the images are pulled?

No. Once Docker has cached the images, you can start and stop the stack entirely offline. Only actions that fetch external resources—like pulling new image tags—require connectivity.

Is the local anon key safe for production testing?

The default anon key is deliberately insecure; it grants full read/write access to any table. Use it only in isolated development environments. For staging or production‑like testing, generate a fresh JWT secret and configure it via environment variables.

How do I reset the database to a clean state?

Stop the containers, remove the db volume, and bring the stack up again:

docker-compose down -v

docker-compose up -d

This wipes all data, giving you a fresh Postgres instance identical to the initial migration state.

Supabase: A Guide to Setting Up Your Local Environment - DEV Community
Supabase local development with Docker on windows doesn't work running ...
How to Install Supabase with Docker on Debian 11
How to Install Supabase with Docker on Ubuntu 24.04 | Geek Rewind

Written by Simone Delaney

Simone Delaney is an Experienced Journalist specializing in human-interest stories, cultural developments, and social issues. Through interviews and contextual reporting, she places individual experiences within broader news developments, helping readers understand both the personal and public dimensions of each story.


You Might Like