Best practice for zero-downtime deployments with database migrations? #4154
-
|
Hey everyone 👋 I've been running Dokploy for a few months now and loving it, but I'm hitting a deployment pattern issue I can't quite solve cleanly. The situation: I have a Node.js app (Express + Postgres) deployed through Dokploy. When I push updates that include database migrations, I'm seeing brief downtime because:
What I've tried:
My current workaround: I'm just accepting the 10-15 seconds of errors during migration window and relying on my frontend to retry failed requests. Not ideal for production though. Questions:
I know this is more of a general deployment problem, but curious if Dokploy has any features that make this easier that I'm not aware of. Running Dokploy 0.8.x if that matters. Thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
hey @BittuChan , thanks for sharing your problem! I was recently able to figure this out after digging through the Dokploy docs and Docker Compose options. The solution that worked for me: Use Dokploy's Advanced Configuration to separate migration logic from app startup, combined with healthchecks to prevent traffic during migration. Here's what I changed: 1. Update your DockerfileInstead of running migrations in the start command, use a separate entrypoint script: # entrypoint.sh
#!/bin/sh
set -e
# Run migrations first
npm run migrate
# Then start the app
exec npm startFROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
# Make entrypoint executable
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 3000
ENTRYPOINT ["/entrypoint.sh"]2. Configure healthcheck in DokployIn your application settings → Advanced → Add this to Docker Labels or use the healthcheck option: HEALTHCHECK CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" || exit 1Make sure your app has a app.get('/health', async (req, res) => {
try {
await db.query('SELECT 1'); // Quick DB check
res.status(200).send('OK');
} catch (err) {
res.status(500).send('DB not ready');
}
});3. Adjust deployment strategyIn Dokploy application settings:
How it works:
Result: Zero user-facing downtime. Old container serves traffic while new one is getting ready. 4. For complex migrations (optional)If your migrations are backward-incompatible, I also started using this pattern: Deploy 1: Add new columns (nullable), deploy code that handles both schemas Yeah it's more work, but for production-critical stuff it's worth it. |
Beta Was this translation helpful? Give feedback.
knex,prisma, ornode-pg-migratethat handle this)Let me know if this helps or if you're running into any specific issues with this setup. Happy to share my full docker-compose.yml if needed.