Skip to main content
This guide walks through deploying Toots using Docker Compose. The project includes a compose.yaml file that sets up PostgreSQL for local development and can be adapted for production use.

Docker Compose setup

The included compose.yaml file provides a PostgreSQL database service:
services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Environment setup

1

Create environment file

Create a .env file in the root directory with the following variables:
# Database (for Docker Compose)
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_secure_password
POSTGRES_DB=toots

# Application (for apps/web)
DATABASE_URL=postgresql://postgres:your_secure_password@localhost:5432/toots
BETTER_AUTH_SECRET=your_random_secret_key
BETTER_AUTH_URL=http://localhost:3000
GOOGLE_GENERATIVE_AI_API_KEY=your_gemini_api_key
Generate a secure random secret for BETTER_AUTH_SECRET using:
openssl rand -base64 32
2

Start PostgreSQL

Launch the database container:
docker compose up -d
This starts PostgreSQL in the background with persistent storage.
3

Install dependencies

Install project dependencies using pnpm:
pnpm install
4

Run database migrations

Apply Prisma migrations to set up the database schema:
pnpm --filter web db:migrate
Or from the apps/web directory:
cd apps/web
pnpm db:migrate
5

Build the application

Build the Next.js application for production:
pnpm build
This command:
  • Generates the Prisma client
  • Deploys migrations
  • Builds the Next.js app
6

Start the application

Start the production server:
pnpm --filter web start
Or from the apps/web directory:
cd apps/web
pnpm start
The application will be available at http://localhost:3000.

Adding a web service

To containerize the Toots application itself, extend the compose.yaml file:
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
      BETTER_AUTH_URL: ${BETTER_AUTH_URL}
      GOOGLE_GENERATIVE_AI_API_KEY: ${GOOGLE_GENERATIVE_AI_API_KEY}
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:
You’ll need to create a Dockerfile in the project root. See the production deployment guide for Dockerfile recommendations.

Useful commands

CommandDescription
docker compose up -dStart services in background
docker compose downStop and remove containers
docker compose logs -fView container logs
docker compose psList running services
docker compose restartRestart all services
pnpm --filter web db:studioOpen Prisma Studio

Troubleshooting

Connection refused errors

If you see “connection refused” errors when connecting to the database:
  1. Verify PostgreSQL is running: docker compose ps
  2. Check the DATABASE_URL matches your Compose configuration
  3. Ensure the database port (5432) isn’t already in use

Migration failures

If migrations fail:
  1. Verify the database is accessible
  2. Check database credentials in .env
  3. Try resetting the database (⚠️ this will delete all data):
    docker compose down -v
    docker compose up -d
    pnpm --filter web db:migrate
    

Build docs developers (and LLMs) love