Skip to content

Bug: Docker image missing /app/drizzle/migrations directory - database initialization fails on fresh install #546

@bytefrostdev

Description

@bytefrostdev

Description

Fresh installations using the official Docker images fail to initialize the database correctly. The backend container skips all migrations because the /app/drizzle/migrations/ directory is not present in the published Docker image.

Environment

  • DeployStack Version: 0.50.0
  • Docker Images: deploystack/backend:latest, deploystack/frontend:latest, deploystack/satellite:latest
  • Host OS: Ubuntu 24.04
  • Database: PostgreSQL 17-alpine
  • Deployment Method: Docker Compose (as per documentation)

Expected Behavior

According to the documentation, database migrations should run automatically on first startup:

"The backend automatically runs database migrations on startup"

Actual Behavior

Backend logs show migrations are skipped because the directory doesn't exist:

{"level":30,"msg":"Migrations directory not found at: /app/drizzle/migrations, skipping migrations."}

The database only contains 2 plugin-related tables instead of the expected 37+ core tables, causing 500 errors on API endpoints:

{
  "statusCode": 500,
  "code": "42P01",
  "error": "Internal Server Error", 
  "message": "relation \"roles\" does not exist"
}

Root Cause Analysis

I investigated the Dockerfile at services/backend/Dockerfile and found the issue:

Current Dockerfile (lines 47-58):

# Production image
FROM node:24-alpine
WORKDIR /app

COPY services/backend/package.json ./
RUN npm install --omit=dev --no-package-lock

COPY services/backend/dist ./dist
COPY services/backend/plugins ./plugins

EXPOSE 3000
CMD ["node", "dist/index.js"]

Problem: Only dist/ and plugins/ are copied to the production image. The drizzle/ directory containing migration files is not copied.

Verification inside container:

$ docker exec deploystack-backend ls -la /app/
total 96
drwxr-xr-x  1 root root  4096 Dec  5 22:32 .
drwxr-xr-x  1 root root  4096 Dec  6 06:14 ..
drwxr-xr-x  8 root root  4096 Dec  5 22:27 dist
drwxr-xr-x 85 root root  4096 Dec  5 22:32 node_modules
-rw-r--r--  1 root root  1566 Dec  5 22:21 package.json
drwxr-xr-x  2 root root  4096 Dec  5 22:27 persistent_data
drwxr-xr-x  3 root root  4096 Dec  5 22:27 plugins
# Note: No 'drizzle' directory present

Migration files exist in source repo but not in image:

services/backend/drizzle/migrations/
├── 0000_perfect_rogue.sql      (40KB - main schema, 176 statements)
├── 0001_wild_selene.sql
├── 0002_bouncy_sphinx.sql
├── 0003_keen_fenris.sql
├── 0004_dazzling_mister_sinister.sql
├── 0005_wakeful_chimera.sql
├── 0006_perfect_thing.sql
└── meta/
    ├── _journal.json
    └── 0000_snapshot.json ... 0006_snapshot.json

Workaround

I was able to get DeployStack working by manually downloading the migrations from GitHub and mounting them as a volume:

Step 1: Download migrations from GitHub

mkdir -p ./drizzle/migrations/meta
BASE_URL="https://raw.githubusercontent.com/deploystackio/deploystack/main/services/backend/drizzle/migrations"

# Download SQL migrations
for file in 0000_perfect_rogue.sql 0001_wild_selene.sql 0002_bouncy_sphinx.sql \
            0003_keen_fenris.sql 0004_dazzling_mister_sinister.sql \
            0005_wakeful_chimera.sql 0006_perfect_thing.sql; do
    curl -s "$BASE_URL/$file" -o "./drizzle/migrations/$file"
done

# Download meta files
curl -s "$BASE_URL/meta/_journal.json" -o "./drizzle/migrations/meta/_journal.json"
for i in {0..6}; do
    curl -s "$BASE_URL/meta/000${i}_snapshot.json" -o "./drizzle/migrations/meta/000${i}_snapshot.json"
done

Step 2: Add volume mount in docker-compose.yml

backend:
  image: deploystack/backend:latest
  volumes:
    - deploystack_backend_data:/app/persistent_data
    - ./drizzle:/app/drizzle:ro  # Workaround for missing migrations

Step 3: Restart containers

docker compose down && docker compose up -d

After this workaround, all 7 migrations were applied successfully and DeployStack is fully functional.

Suggested Fix

Add the missing COPY instruction to services/backend/Dockerfile:

# Production image
FROM node:24-alpine
WORKDIR /app

COPY services/backend/package.json ./
RUN npm install --omit=dev --no-package-lock

COPY services/backend/dist ./dist
COPY services/backend/drizzle ./drizzle    # <-- ADD THIS LINE
COPY services/backend/plugins ./plugins

EXPOSE 3000
CMD ["node", "dist/index.js"]

Impact

  • Severity: Critical - DeployStack is unusable out-of-the-box
  • Affected users: All new installations using Docker Compose
  • Documentation states automatic migration but this cannot work without the files present in the image

Additional Notes

This issue affects fresh installations only. Users who somehow got past initial setup (perhaps from an older image version that included migrations) would not notice this issue until they need to reset their database.

Thank you for your work on DeployStack - it's a great project! 🚀

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions