App
Use an app unit when you need to build a container and run a long-lived service.
type: appimage: python:3.13-slim
builds: - files: ["requirements.txt"] script: | pip install --no-cache-dir -r requirements.txt
- files: ["*"] script: | python manage.py collectstatic --noinput
runtime: port: 8000 env: ALLOWED_HOSTS: "*" DB_NAME: ${app-db:name} DB_USER: ${app-db:user} DB_PASSWORD: ${app-db:password} DB_HOST: ${app-db:host} DB_PORT: ${app-db:port} API_TOKEN: ${secret:api-token} init: | python manage.py migrate --noinput cmd: "gunicorn app.wsgi:application --bind 0.0.0.0:8000"
exports: - source: /app/staticfiles path: /static
timers: - name: cleanup schedule: "0 3 * * *" script: | python manage.py cleanupFields
Section titled “Fields”| Field | Required | Purpose |
|---|---|---|
image | Yes | Base image used for the build. |
builds | Yes | Ordered build layers. |
runtime | No | Service command, port, init script, and environment. |
volumes | No | Persistent mounts for runtime containers. |
exports | No | Static files copied from the built image. |
timers | No | Cron scripts run inside the running app container. |
Build layers
Section titled “Build layers”Each build layer can copy files and run a script.
builds: - description: Install Python packages files: ["requirements.txt"] script: | pip install --no-cache-dir -r requirements.txt
- description: Copy app source files: ["*"] script: | python manage.py collectstatic --noinputfiles lists paths from the deploy archive. Use "*" to copy all files.
Use env when a build step needs values from secrets or other units:
env: NPM_TOKEN: ${secret:npm-token} DB_URL: ${app-db:url}Runtime
Section titled “Runtime”runtime starts the service after deploy.
runtime: port: 3000 env: NODE_ENV: production init: | npm run migrate cmd: node server.jsport is used for app health checks and app references in domain config:
${myapp:url}becomeshttp://dpl--myapp:<port>${myapp:socket}becomesdpl--myapp:<port>
Use init for short setup work such as database migrations. Use cmd for the long-running process.
Volumes
Section titled “Volumes”Use volumes for data that must survive redeploys.
volumes: - description: Uploaded files source: myapp-uploads path: /app/uploadssource can be a Podman volume name or a full host path. path must be an absolute container path and cannot be /.
Exports
Section titled “Exports”Use exports for static files that nginx should serve.
exports: - source: /app/staticfiles path: /staticsource must be an absolute path inside the image and cannot be /.
A domain unit can serve the files with ${myapp:export}.
Timers
Section titled “Timers”Timers run scripts inside the app container.
timers: - name: add-time schedule: "* * * * *" script: | python manage.py add_time --seconds 60The schedule uses standard 5-field cron syntax:
- Minute:
10 * * * *- runs at minute 10 of every hour. - Minute (step):
*/5 * * * *- runs every 5 minutes. - Hour:
0 14 * * *- runs at 14:00 every day. - Day of the month:
0 0 15 * *- runs at midnight on the 15th of every month. - Month:
0 0 1 1 *- runs at midnight on January 1st. - Day of the week:
0 0 * * 5- runs at midnight every Friday. - Multiple days:
0 8 * * 1-5- runs at 08:00, Monday through Friday.
Set disabled: true to keep a timer in config but stop dpl from running it.
Timer output is written to:
<base>/state/<unit>/log/timers.log