Migrating Your App to a Dedicated Database Stack

This guide walks you through converting your existing vibe-dev application from using the shared postgres database to running your own dedicated PostgreSQL container as part of a self-contained stack.


Why migrate?

The shared postgres instance on vibe-dev was intended as a convenience for early development. Moving to a dedicated database per application gives you:

  • Isolation — your database lives and dies with your app, no cross-app dependencies
  • Portability — your entire app is defined in one docker-compose.yml
  • Safety — schema changes, migrations, and credential rotation don't affect other apps
  • Easier backups — your data volume is scoped to your app

Before you start

You will need:

  • SSH access to vibe-dev.emerson.edu
  • Your app located in /opt/apps/<your-app-name>
  • Your current database name, user, and password from your .env file
  • A port in the 545x range that isn't already in use (check with sudo docker ps --format "table {{.Ports}}")

Step 1 — Export your existing data

Before moving off the shared database, export your data so you can import it into your new dedicated container.

docker exec postgres pg_dump -U postgres <your_database_name> > /opt/apps/<your-app-name>/backup.sql

Verify the dump looks reasonable:

head -20 /opt/apps/<your-app-name>/backup.sql

Step 2 — Update your docker-compose.yml

Add a db service and a named volume to your existing docker-compose.yml. Below is the standard template — replace all <placeholders> before using.

services:
  web:
    # ... your existing web service definition, unchanged ...

  db:
    image: postgres:17
    container_name: <your-app-name>_postgres
    restart: always
    ports:
      - "<545x>:5432"       # Replace 545x with your assigned port, e.g. 5452
    environment:
      - POSTGRES_PASSWORD=<your-db-password>
    volumes:
      - <your-app-name>_postgres:/var/lib/postgresql/data

volumes:
  <your-app-name>_postgres:

Key things to change in your web service:

Update your DATABASE_URL environment variable (or .env file) from pointing at host.docker.internal:5432 to pointing at the db service instead:

# Before (shared database)
DATABASE_URL=postgresql://postgres:<password>@host.docker.internal:5432/<your_database_name>

# After (dedicated database)
DATABASE_URL=postgresql://postgres:<password>@db:5432/<your_database_name>

Also add a dependency so your web service waits for the database to be ready:

  web:
    depends_on:
      - db

Step 3 — Deploy the updated stack

From your app directory:

cd /opt/apps/<your-app-name>
docker compose up -d

This will start your new dedicated postgres container alongside your web service.


Step 4 — Import your data

Wait a few seconds for postgres to initialize, then import your dump:

docker exec -i <your-app-name>_postgres psql -U postgres -c "CREATE DATABASE <your_database_name>;"
docker exec -i <your-app-name>_postgres psql -U postgres <your_database_name> < /opt/apps/<your-app-name>/backup.sql

Verify the import:

docker exec -it <your-app-name>_postgres psql -U postgres -d <your_database_name> -c "\dt"

Step 5 — Test your application

Hit your app and verify everything works as expected with the new database. Check logs if anything looks off:

docker compose logs -f

Step 6 — Clean up the shared database

Once you've confirmed your app is working correctly with its dedicated database, drop your database from the shared instance to free up resources:

docker exec postgres psql -U postgres -c "DROP DATABASE <your_database_name>;"

Also delete your backup file if you no longer need it:

rm /opt/apps/<your-app-name>/backup.sql

Using Portainer instead of the CLI

If you prefer a GUI, you can deploy and manage your stack through Portainer at https://vibe-dev.emerson.edu:9443.

  1. Go to Stacks → Add stack
  2. Give it the same name as your app directory (e.g. myapp)
  3. Paste your updated docker-compose.yml into the web editor
  4. Note: if your compose file uses env_file, you'll need to inline your environment variables directly in the compose editor — Portainer cannot read files from disk
  5. Click Deploy the stack

Portainer is optional — CLI deployments work just as well and are required for apps that use env_file or build: directives.


Reference: complete example

Here is a complete example for an app called myapp using port 5452:

services:
  web:
    image: localhost:5443/myapp:latest
    container_name: myapp
    restart: always
    ports:
      - "8090:8000"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - /opt/apps/myapp:/app
    environment:
      - DATABASE_URL=postgresql://postgres:mysecretpassword@db:5432/myapp_db
    depends_on:
      - db

  db:
    image: postgres:17
    container_name: myapp_postgres
    restart: always
    ports:
      - "5452:5432"
    environment:
      - POSTGRES_PASSWORD=mysecretpassword
    volumes:
      - myapp_postgres:/var/lib/postgresql/data

volumes:
  myapp_postgres:

Port assignments

Postgres ports start at 5450 and increment per app. Check what's already in use before picking yours:

sudo docker ps --format "table {{.Names}}\t{{.Ports}}" | grep 54

Current known assignments:

AppPostgres Port
emersonformsportal5450
castletravel5451
(your app)5452+

Need help?

Contact the infrastructure team or open a ticket with IT.