Manual deployments work for side projects. Production needs automation. This guide covers connecting Dokploy to your Git provider, automatic deployments on push, branch-based environments, and rollbacks when things go wrong.
Git Provider Integration
Dokploy supports GitHub, GitLab, and Bitbucket. The setup flow is similar for each.
Connecting GitHub
Two methods available: GitHub App (recommended) or Personal Access Token
GitHub App Method (Recommended)
- Go to Dokploy Settings → Git Providers
- Click Install GitHub App
- Authorize Dokploy to access your repositories
- Select which repos to grant access (all or specific ones)
- Complete installation
Personal Access Token Method
- Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token with scopes:
repoandadmin:repo_hook - Paste token in Dokploy
Automatic Deployments
Once your Git provider is connected, enable auto-deploy for your applications.
Setting Up Auto-Deploy
- Go to your application in Dokploy
- Open the Git tab
- Configure:
- Repository: Select from your connected repos
- Branch:
main(or your production branch) - Auto Deploy: Toggle ON
- Save
Now every push to that branch triggers a deployment.
How It Works
- You push code to GitHub/GitLab/Bitbucket
- Git provider sends a webhook to Dokploy
- Dokploy pulls the latest code
- Docker builds your image
- New container replaces the old one
- Traffic routes to the new container
The whole process typically takes 1-5 minutes depending on your build.
Manual Webhook Setup
For self-hosted GitLab instances that require manual configuration
- Go to your application → Git tab
- Copy the Webhook URL
- In your Git provider, add a webhook:
- URL: The copied webhook URL
- Content type:
application/json - Events: Push events (and optionally Pull Request events)
- Secret: Copy from Dokploy if shown
Branch-Based Deployments
Production and staging should be separate environments with different configurations.
Strategy 1: Separate Applications (Recommended)
Full isolation between environments
Production App
- Branch:
main - Domain:
app.yourdomain.com - Environment: Production database credentials,
NODE_ENV=production
Staging App
- Branch:
developorstaging - Domain:
staging.yourdomain.com - Environment: Staging database credentials,
NODE_ENV=staging
Staging Database
Don't share databases between staging and production. Create a separate database service for staging:
- Create Service → Database → PostgreSQL
- Name it
staging-db - Use different credentials
- Point your staging app at this database
Preview Deployments for Pull Requests
Deploy every PR to a temporary environment for review. This requires a bit more setup but is invaluable for teams.
Manual PR Previews
- Create a new application in Dokploy
- Set the branch to your PR branch (e.g.,
feature/new-login) - Set a preview domain:
pr-123.preview.yourdomain.com - Deploy
When the PR merges, delete the preview app.
Automated PR Previews with GitHub Actions
name: Deploy PR Preview
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- name: Deploy to Dokploy
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.DOKPLOY_API_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{
"projectId": "${{ secrets.DOKPLOY_PROJECT_ID }}",
"branch": "${{ github.head_ref }}",
"domain": "pr-${{ github.event.number }}.preview.yourdomain.com"
}' \
https://your-dokploy-server:3000/api/applications/deploy
- name: Comment PR with preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 Preview deployed to https://pr-${{ github.event.number }}.preview.yourdomain.com'
})Note: You'll need to create a Dokploy API token and set up the API endpoint. Check Dokploy's documentation for current API details.
Wildcard DNS for Previews
To support dynamic preview subdomains:
*.preview.yourdomain.com → your-server-ipIn Dokploy/Traefik, configure wildcard certificate handling (Let's Encrypt supports this via DNS challenge).
Build Caching
Slow builds kill productivity. Optimize your Docker builds.
Layer Caching Basics
Docker caches each layer. Order your Dockerfile to maximize cache hits.
# Dependencies change less often — cache these
COPY package.json package-lock.json ./
RUN npm ci
# Source changes frequently — put last
COPY . .
RUN npm run buildBuildKit Cache Mounts
Persist downloaded packages across builds
# npm
RUN --mount=type=cache,target=/root/.npm npm ci
# pip
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
# composer
RUN --mount=type=cache,target=/root/.composer/cache composer installEnable BuildKit in Dokploy (usually enabled by default):
export DOCKER_BUILDKIT=1Multi-Stage Builds
Don't ship build tools to production
# Build stage — has all the tools
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage — minimal
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"].dockerignore
Exclude unnecessary files from the build context
.git
node_modules
*.md
.env*
.DS_Store
coverage
.next
distA smaller build context means faster uploads and builds.
Deployment Strategies
Rolling Deployments (Default)
Dokploy's default behavior:
- Build new container
- Start new container
- Health check passes
- Route traffic to new container
- Stop old container
Zero downtime if your health checks work correctly.
Blue-Green Deployments
For critical applications, keep the old version running until you're confident:
- Deploy to a "green" environment (separate app in Dokploy)
- Test the green environment
- Switch DNS/load balancer to green
- Keep blue running as instant rollback
- After confidence period, tear down blue
Canary Deployments
Route a percentage of traffic to the new version. This requires a load balancer in front of Dokploy. Use Traefik's weighted routing or an external load balancer like HAProxy.
Rollbacks
Deployments fail. Be ready.
Quick Rollback via Dokploy
- Go to your application → Deployments tab
- Find the last working deployment
- Click Redeploy on that version
Dokploy rebuilds from that commit and deploys it.
Preventing Bad Deployments
- Health checks — Dokploy won't route traffic to unhealthy containers
- Smoke tests — Run basic tests post-deployment
- Gradual rollout — Deploy to staging first, always
Deployment Hooks
Run commands at specific points in the deployment lifecycle.
Pre-Build Hook
Runs before Docker build starts
Use for: Fetching secrets, generating files, validating configuration
echo "Starting build at $(date)"Post-Build Hook
Runs after successful build, before container starts
Use for: Database migrations, cache warming, Slack notifications
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Deployment starting for myapp"}' \
$SLACK_WEBHOOK_URLPost-Deploy Hook
Runs after container is live and healthy
Use for: Smoke tests, cache invalidation, success notifications
# Run smoke test
curl -f https://app.yourdomain.com/health || exit 1
# Notify success
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"✅ myapp deployed successfully"}' \
$SLACK_WEBHOOK_URLMonorepo Deployments
Deploying multiple apps from one repository.
Subdirectory Builds
/
├── apps/
│ ├── frontend/
│ │ └── Dockerfile
│ └── backend/
│ └── Dockerfile
└── packages/In Dokploy, set:
- Build Context:
apps/frontend - Dockerfile Path:
apps/frontend/Dockerfile
Create separate Dokploy applications for frontend and backend, each pointing to their subdirectory.
Triggering Specific Apps
By default, any push triggers all apps watching the repo. To be selective, use path filters in your CI:
on:
push:
paths:
- 'apps/frontend/**'
jobs:
deploy-frontend:
# ... deploy frontend onlySecrets in CI/CD
Never commit secrets. Here's how to handle them.
Environment Variables in Dokploy
Store secrets in Dokploy's environment variables (they're encrypted at rest):
- Application → Environment tab
- Add sensitive values
- They're injected at runtime
External Secrets
For more control, use a secrets manager:
- Infisical — See our guide
- Vault — HashiCorp's solution
- AWS Secrets Manager / Parameter Store
export DATABASE_URL=$(infisical secrets get DATABASE_URL --plain)Git-Ignored .env Files
For local development, use .env files but never commit them:
.env
.env.local
.env.productionUse .env.example to document required variables:
DATABASE_URL=postgresql://user:pass@localhost:5432/myapp
REDIS_URL=redis://localhost:6379/0
SECRET_KEY=generate-a-random-stringTroubleshooting CI/CD
Webhook not triggering?
- Check webhook URL is correct in Git provider
- Verify webhook secret matches
- Look at webhook delivery logs in GitHub/GitLab
- Check Dokploy logs:
docker logs dokploy
Build succeeds but deploy fails?
- Check health check endpoint exists and returns 200
- Verify container starts correctly:
docker logs <container-id> - Check port configuration matches
Slow builds?
- Review Dockerfile layer ordering
- Add
.dockerignore - Use multi-stage builds
- Enable BuildKit cache mounts
Wrong branch deploying?
- Verify branch setting in Dokploy application
- Check webhook is configured for correct events
- Look for branch filters in CI config
What's Next
Your deployments are automated and recoverable. Part 5 adds visibility:
Monitoring & Observability
Integrate Prometheus and Grafana for metrics, Loki for logs, set up health checks and alerting so you know when things break before your users do.
