Run deploy-phase deployment tasks in the cluster rather than on the Dokku host
app.json deployment tasks run in ephemeral Docker containers on the Dokku host via executeScript (plugins/app-json/functions.go:140). For schedulers where the workload does not live on that host, notably k3s, this is the wrong execution context.
The scope is narrower than it first appears. predeploy, the Procfile release command, and Heroku's scripts.postdeploy all fire from the release phase (pre-release-builder / post-release-builder), which by design requires a local image: release_and_deploy gates on fn-verify-app-image (plugins/common/functions:677), and predeploy commits its container back into the image tag (plugins/app-json/functions.go:284-315), which has no clean Kubernetes Job equivalent. Those can stay on the host.
The one deploy-phase task is scripts.dokku.postdeploy, fired from the post-deploy trigger (plugins/app-json/triggers.go:189). On k3s it runs on the build host while the app it just deployed runs in the cluster. Consequences:
- It needs the image present locally, which conflicts with the registry plugin's own image reaping (
plugins/registry/functions.go:230-247). - It executes with the host's view of the world rather than the cluster's. A postdeploy migration may not be able to reach an in-cluster database, and it does not see the app's Kubernetes Secret, service discovery, or network policies.
- The app's resource limits, node selection, and security context do not apply.
Proposal: have app-json dispatch postdeploy through the scheduler instead of calling docker directly. scheduler-run already exists, and TriggerSchedulerRun (plugins/scheduler-k3s/triggers.go:915) already runs one-off commands as in-cluster Jobs with the right secrets, pull secrets, and security context, so the k3s side is largely in place. docker-local would keep today's behavior behind the same trigger.
Source: dokku/dokku