0.38.0 Migration Guide¶
Changes¶
- Dokku now generates a minimal nginx configuration for apps without running
webprocesses (undeployed apps, apps with nowebprocess type, or apps with stopped web processes). This configuration returns502 Bad Gatewayresponses, ensuring the app's domain resolves and monitoring tools can detect non-200 status codes. The configuration is automatically replaced with the full proxy configuration once the app is deployed with runningwebprocesses. See the nginx documentation for more details. -
Users with custom
nginx.conf.sigiltemplates that referenceDOKKU_APP_WEB_LISTENERSshould be aware that this variable may now be empty when the template is rendered for apps without running web processes. Custom templates should handle this case gracefully, for example by using a conditional to serve an error page instead of proxying: -
The path on disk to both the global
ENVfile and appENVfiles have been moved. Users should reference environment variables via the provided plugin triggers rather than directly sourcing the ENV files. Existing ENV files are left untouched and will be removed on the subsequent Dokku install. - During a fresh apt install, the upstream nginx default vhost files (
/etc/nginx/sites-enabled/default,/etc/nginx/sites-available/default, and/etc/nginx/conf.d/default.conf) are renamed to${path}.dokku-disabled(not deleted) to avoid aduplicate default server for 0.0.0.0:80error. Operators with local customizations can recover them by inspecting the.dokku-disabledsiblings. Upgrade-in-place installs do not touch any existing nginx files. - Fresh apt installs now ship a catch-all default site at
/etc/nginx/conf.d/00-default-vhost.confthat rejects requests with unknown Host headers usingssl_reject_handshake on(HTTPS) andreturn 444(HTTP). This replaces the manual workaround previously documented in the nginx docs. The behavior can be opted out at install time via thedokku/install_default_sitedebconf prompt. See the Default site documentation. - The
docker-localscheduler now sendsSIGTERMto old containers immediately after a successful deploy, rather than waitingwait-to-retireseconds before signaling. This matches Heroku's graceful-shutdown contract and lets applications begin draining in-flight work as soon as proxy traffic switches. Thewait-to-retiregrace period andstop-timeout-secondshard-stop continue to apply as before. See the zero downtime deploys documentation for more details. - The
docker-localscheduler no longer queues an image for retirement when another running container of the same app still uses it. This fixes the case where aps:rebuildagainst an image-based deploy (git:from-image) produced an identical-SHA image and thedokku-retirecron timer would logImage ... has running containers, skipping rmon every run. Stuck entries from prior versions are pruned automatically on the nextps:retirerun. - All
:reportsubcommands now accept the--globalflag, which scopes the report to globally-configured properties. The flag composes with--format json, so a JSON report of global properties can be obtained via, for example,dokku scheduler:report --global --format json. Previously, combining--globalwith--format jsonwas rejected with an "info flag" error, and--globalon its own was treated as an unknown flag. - The
scheduler-k3splugin now manages env config and the dokku-generated image pull Secret as their own helm releases with stable names (config-{app}andpull-secret-{app}) rather than bundling them into the app helm chart with a per-deploy timestamp suffix (env-{app}.{ts}/ims-{app}.{ts}). This fixes two bugs: a helm rollback of the app chart no longer deletes Secrets that older ReplicaSets still reference, and the Deployment'simagePullSecretslist no longer accumulates references to nonexistent Secrets across deploys. The next deploy of an app switches the Deployment'senvFromandimagePullSecretsreferences to the stable names and prunes any leaked entries; existing live Deployments do not need to be patched manually. App rename now also uninstalls the oldtls-{app},config-{app}, andpull-secret-{app}releases under the previous app name; the new name's releases are recreated on the next deploy or certs sync. - The storage plugin now treats persistent volumes as named, scheduler-aware first-class resources via
storage:create,storage:mount,storage:set, andstorage:destroy. The legacystorage:mount <app> <host>:<container>colon form continues to work on docker-local apps but is deprecated; on k3s apps it is rejected. Existing colon-form mounts are migrated automatically the first time the new storage plugin runs (during the install trigger) - they appear aslegacy-<hash>entries instorage:list-entries. The migration is idempotent and tied to a per-app flag file at$DOKKU_LIB_ROOT/config/storage/.migrated/<app>; deleting that file forces a re-scan on the next install. Thestorage:ensure-directorycommand keeps working but now emits a deprecation warning - preferstorage:create <name> [<path>](the path defaults to the same$DOKKU_LIB_ROOT/data/storage/<name>location). Storage entry names must now be DNS-1123 labels of 45 characters or less so they can be used verbatim as Helm release and Kubernetes resource names; underscores and uppercase characters that the olderensure-directoryvalidator accepted are rejected for new names. The migration synthesizer always uses lowercase hex hashes so existing data is never locked out.
TLS handshake behavior change¶
With the new catch-all installed, an HTTPS request to a hostname that matches a configured dokku app but where the app has no TLS certificate configured will have its TLS handshake rejected by the catch-all (via ssl_reject_handshake on). Previously, nginx fell through to the lexicographically first port-443 server block and presented that block's certificate, producing a cert-mismatch error on the client. The new behavior is a correctness improvement, but operators who deliberately relied on the old fall-through certificate (for monitoring probes, for example) need to either configure a certificate for the target app or remove the catch-all on that host. Existing apps that already have certificates configured are unaffected: nginx selects the right server block via SNI before TLS completion, so the catch-all is never consulted for legitimate requests.
Environment variables migrated to plugin properties¶
A number of DOKKU_* config environment variables have been replaced with properly-namespaced plugin properties. Existing values are migrated automatically the first time dokku runs after the upgrade, and the original config variable is unset. No manual action is required.
Going forward, configure these settings using the property commands listed below. Setting the deprecated env vars via dokku config:set will no longer have any effect.
| Deprecated Env Var | Replacement Command |
|---|---|
DOKKU_APP_PROXY_TYPE |
dokku proxy:set <app> type <value> |
DOKKU_APP_RESTORE |
dokku ps:set <app> restore <true\|false> |
DOKKU_APP_SHELL |
dokku scheduler:set <app> shell <value> |
DOKKU_CHECKS_DISABLED |
dokku checks:disable <app> [proctypes] |
DOKKU_CHECKS_ENABLED |
dokku checks:enable <app> [proctypes] |
DOKKU_CHECKS_SKIPPED |
dokku checks:skip <app> [proctypes] |
DOKKU_CHECKS_WAIT |
dokku checks:set <app> wait <value> |
DOKKU_CHECKS_TIMEOUT |
dokku checks:set <app> timeout <value> |
DOKKU_CHECKS_ATTEMPTS |
dokku checks:set <app> attempts <value> |
DOKKU_DEFAULT_CHECKS_WAIT |
dokku checks:set --global default-wait <value> |
DOKKU_DISABLE_APP_AUTOCREATION |
dokku apps:set --global disable-autocreation <true\|false> |
DOKKU_DISABLE_PROXY |
dokku proxy:disable <app> / dokku proxy:enable <app> |
DOKKU_DOCKERFILE_START_CMD |
dokku ps:set <app> dockerfile-start-cmd <value> |
DOKKU_PROXY_PORT |
dokku proxy:set <app> proxy-port <value> |
DOKKU_PROXY_SSL_PORT |
dokku proxy:set <app> proxy-ssl-port <value> |
DOKKU_SKIP_ALL_CHECKS |
dokku checks:disable <app> |
DOKKU_SKIP_CLEANUP |
dokku builder:set <app> skip-cleanup <true\|false> |
DOKKU_SKIP_DEFAULT_CHECKS |
dokku checks:skip <app> |
DOKKU_SKIP_DEPLOY |
dokku ps:set <app> skip-deploy <true\|false> |
DOKKU_START_CMD |
dokku ps:set <app> start-cmd <value> |
DOKKU_PARALLEL_ARGUMENTS is removed entirely; it has no replacement.
DOKKU_SKIP_CLEANUP continues to be honored when set in /etc/environment or ~dokku/.dokkurc/* so that bootstrap-time configuration keeps working, but the builder skip-cleanup property is the canonical interface and takes precedence when set.