Compare commits
251 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
983c462904 | ||
|
|
368a6999c9 | ||
|
|
2d9521a855 | ||
|
|
0429ecfd98 | ||
|
|
c676a09bd5 | ||
|
|
dc6a3690d9 | ||
|
|
c2c02e174c | ||
|
|
d4ce0b987b | ||
|
|
097b3c5449 | ||
|
|
494c42428f | ||
|
|
5e092caef3 | ||
|
|
d573054731 | ||
|
|
f8813232d8 | ||
|
|
824aed042f | ||
|
|
5d7c683daa | ||
|
|
91e40634f4 | ||
|
|
aea322be6f | ||
|
|
d268074189 | ||
|
|
f0a4a7fc29 | ||
|
|
473bcce688 | ||
|
|
49dc1c1e64 | ||
|
|
964c0fc4e9 | ||
|
|
ec8fd0994b | ||
|
|
1e04955c4d | ||
|
|
eaaed79b39 | ||
|
|
31ce5a7c48 | ||
|
|
ef959160bd | ||
|
|
179d09fdd5 | ||
|
|
cdfcd4d2c8 | ||
|
|
ea807bb46e | ||
|
|
2c3ed3ad14 | ||
|
|
4f0a7e63f3 | ||
|
|
4dbd2e5bba | ||
|
|
9671cbd78e | ||
|
|
641f1e3374 | ||
|
|
b4c1eb246d | ||
|
|
9e9f374050 | ||
|
|
75d42dfa38 | ||
|
|
d3f977f953 | ||
|
|
e76785e629 | ||
|
|
8497a1cc52 | ||
|
|
6b03e2ed88 | ||
|
|
3bf2478393 | ||
|
|
edceed1524 | ||
|
|
60fe2400a9 | ||
|
|
e8d8b0683a | ||
|
|
53ef8c7780 | ||
|
|
8f8a23aac3 | ||
|
|
dc5b9cc883 | ||
|
|
8d3506a09c | ||
|
|
554fee91de | ||
|
|
4c8bdef06d | ||
|
|
cb0f729299 | ||
|
|
ae3d63668d | ||
|
|
465de6cc71 | ||
|
|
823b37e383 | ||
|
|
63f0aaa0cf | ||
|
|
7dfe8dd336 | ||
|
|
c95c9f8518 | ||
|
|
c0794abc30 | ||
|
|
f020b76e11 | ||
|
|
0a857b7966 | ||
|
|
1a6f01a1eb | ||
|
|
8de073c960 | ||
|
|
7cd4493cc7 | ||
|
|
2210307e42 | ||
|
|
4d5a16b714 | ||
|
|
f0d088bc1d | ||
|
|
ea25c5b6e2 | ||
|
|
ae61547505 | ||
|
|
67e4cf04ab | ||
|
|
e9a53ac82d | ||
|
|
cdbc91048a | ||
|
|
58042b9330 | ||
|
|
d75228f165 | ||
|
|
3b3bc3dd39 | ||
|
|
6a5d568944 | ||
|
|
89afd09087 | ||
|
|
b601a626f5 | ||
|
|
1ca961251d | ||
|
|
cfb7da8ec0 | ||
|
|
e1b6bdb1d4 | ||
|
|
8a46d89181 | ||
|
|
4e87d1f447 | ||
|
|
aa72794711 | ||
|
|
7d00e2c422 | ||
|
|
99855ae9f8 | ||
|
|
0c08aefc54 | ||
|
|
4257c17eab | ||
|
|
3a6ae559c4 | ||
|
|
507df612e8 | ||
|
|
55d7487d66 | ||
|
|
7ba453e588 | ||
|
|
ef9bdc0379 | ||
|
|
f06048a266 | ||
|
|
579481e76b | ||
|
|
2f1268172b | ||
|
|
abb7faa503 | ||
|
|
1a45fef839 | ||
|
|
0f78f81d71 | ||
|
|
b28e4e552b | ||
|
|
8282981361 | ||
|
|
ec70e10c5d | ||
|
|
63958b99ef | ||
|
|
3267cb2ac8 | ||
|
|
cf5807c157 | ||
|
|
73238b7c97 | ||
|
|
ab804c678a | ||
|
|
40b8b25ad4 | ||
|
|
7791a26e98 | ||
|
|
f4a1559edc | ||
|
|
3a7d74cdaa | ||
|
|
effa9d37cf | ||
|
|
d88e8f137f | ||
|
|
ec7841a07b | ||
|
|
63b809f64c | ||
|
|
1812cfbdeb | ||
|
|
9b6c32f39c | ||
|
|
132f724841 | ||
|
|
9a795fcf91 | ||
|
|
d1213c14a8 | ||
|
|
d51726b7cb | ||
|
|
177eac4ef1 | ||
|
|
f728fc8cd7 | ||
|
|
8a6c853ccd | ||
|
|
97b86707e7 | ||
|
|
c424cb06c2 | ||
|
|
32c997e4a7 | ||
|
|
1161dda05e | ||
|
|
9c8d5f54fb | ||
|
|
c0f23528af | ||
|
|
f19227dcd9 | ||
|
|
9767f996c6 | ||
|
|
acf841606c | ||
|
|
8e7d158ac2 | ||
|
|
5dcefe7ffa | ||
|
|
87dd39e0b3 | ||
|
|
b397cf1bd7 | ||
|
|
eaaf0e41c2 | ||
|
|
af6267f3b5 | ||
|
|
b2ea5406fe | ||
|
|
d7c88ae298 | ||
|
|
a4f26a356a | ||
|
|
099c358a1e | ||
|
|
e4a8cfc74f | ||
|
|
4eb42f1b82 | ||
|
|
d356ee6847 | ||
|
|
da13367ca8 | ||
|
|
db1308a2ab | ||
|
|
b92310c4c8 | ||
|
|
b17eaedbec | ||
|
|
bc603d7b9c | ||
|
|
4927ca092d | ||
|
|
e54fcc4035 | ||
|
|
c2a07c3f1c | ||
|
|
8847fcb6b0 | ||
|
|
d1554461ab | ||
|
|
d24ab6ffdf | ||
|
|
aa45f748b1 | ||
|
|
c3db713c27 | ||
|
|
17c549ee63 | ||
|
|
d846324fd5 | ||
|
|
bc4d3a76b9 | ||
|
|
30e4123949 | ||
|
|
81e6cdf5a5 | ||
|
|
f2f6e0b473 | ||
|
|
38c6b180af | ||
|
|
b8accfd463 | ||
|
|
365e300eb6 | ||
|
|
8ea9dd28ff | ||
|
|
769d029b0d | ||
|
|
66c4b3b30e | ||
|
|
65bdbefbea | ||
|
|
3ba51725be | ||
|
|
34c336c668 | ||
|
|
ad00918891 | ||
|
|
ef51f1f942 | ||
|
|
68dd1b83a2 | ||
|
|
76f3c3ec12 | ||
|
|
b8e5c3251c | ||
|
|
de0e743880 | ||
|
|
cef1e7aff5 | ||
|
|
052b342c65 | ||
|
|
f5cbc51fec | ||
|
|
ef430e815b | ||
|
|
ed2fbf3d44 | ||
|
|
207a32e6ae | ||
|
|
973f6ffb2c | ||
|
|
bc3b166ce7 | ||
|
|
4af68e75c5 | ||
|
|
807ddf29a7 | ||
|
|
1158db380a | ||
|
|
0a6eb14dd1 | ||
|
|
f30da59b84 | ||
|
|
9324ccf5b9 | ||
|
|
c7afc0523d | ||
|
|
915172c0c5 | ||
|
|
24f460f5d3 | ||
|
|
1308e21947 | ||
|
|
2745e46054 | ||
|
|
f3e29c7c94 | ||
|
|
ddf470282e | ||
|
|
dcce09f19f | ||
|
|
fc7ddf34ba | ||
|
|
7529d8cb08 | ||
|
|
20f2100d46 | ||
|
|
5bf82d2585 | ||
|
|
2993fa800c | ||
|
|
71ec612fbd | ||
|
|
914be7276f | ||
|
|
ae5cbe1e98 | ||
|
|
ce45b8fca3 | ||
|
|
8cebe9270a | ||
|
|
6ad2e13f32 | ||
|
|
8721db17c2 | ||
|
|
9087d8d5d5 | ||
|
|
3e417a15df | ||
|
|
66373a4ce8 | ||
|
|
c3a5e59045 | ||
|
|
1024d65d8c | ||
|
|
80d2ed5aa3 | ||
|
|
f13501ae3e | ||
|
|
621a9a218d | ||
|
|
d487b595d4 | ||
|
|
338bceb20e | ||
|
|
107b5f5f0a | ||
|
|
fe3d5c25dd | ||
|
|
351ca493d3 | ||
|
|
424ecb96dc | ||
|
|
5f99b683ee | ||
|
|
387bbf4c8a | ||
|
|
0caab03276 | ||
|
|
9dbaf34f99 | ||
|
|
0ee28bf4c7 | ||
|
|
d91ed9f683 | ||
|
|
197dc69056 | ||
|
|
08596c9648 | ||
|
|
b0b11bcf26 | ||
|
|
44dbbe6a34 | ||
|
|
5a787af3ae | ||
|
|
996d882310 | ||
|
|
b686a8f8a4 | ||
|
|
6806b1c17b | ||
|
|
cacafbc181 | ||
|
|
71db1e24ec | ||
|
|
2acfdbd7d4 | ||
|
|
fd6c2c5f62 | ||
|
|
d1aeb04797 | ||
|
|
5923689e32 | ||
|
|
2b0f96dc1a | ||
|
|
8240096dda |
66
.github/dependabot.yml
vendored
66
.github/dependabot.yml
vendored
@@ -189,140 +189,140 @@ updates:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: bundler
|
||||
directory: "/tests/apps/multi"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/checks-root"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/config"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/dockerfile-app-json-formations"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/dockerfile-noexpose"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/dockerfile-procfile-bad"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/dockerfile-procfile"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/dockerfile"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/gitsubmodules"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: gomod
|
||||
directory: "/tests/apps/gogrpc"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: pip
|
||||
directory: "/tests/apps/multi"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: maven
|
||||
directory: "/tests/apps/java"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/multi"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/nodejs-express"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/nodejs-worker"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/nodejs-express-noappjson"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: npm
|
||||
directory: "/tests/apps/nodejs-express-noprocfile"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: composer
|
||||
directory: "/tests/apps/php"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: pip
|
||||
directory: "/tests/apps/python-flask"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -343,91 +343,91 @@ updates:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile-procfile"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile-entrypoint"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile-procfile-bad"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/go-fail-predeploy"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/zombies-dockerfile-no-tini"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile-release"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: pip
|
||||
directory: "/tests/apps/dockerfile-release"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/dockerfile-app-json-formations"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/gogrpc"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/zombies-dockerfile-tini"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/tests/apps/go-fail-postdeploy"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "type: dependencies"
|
||||
- "type: tests"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/docs/_build"
|
||||
schedule:
|
||||
|
||||
110
.github/workflows/dependency-updates.yml
vendored
Normal file
110
.github/workflows/dependency-updates.yml
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
---
|
||||
name: 'dependency-updates'
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 6 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: prepare
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Build dependency matrix
|
||||
id: matrix
|
||||
run: |
|
||||
matrix=$(jq -c '
|
||||
[
|
||||
(.dependencies[] | {section: "dependencies", name, version, url: .urls.amd64}),
|
||||
(.predependencies[] | {section: "predependencies", name, version, url: .urls.amd64}),
|
||||
(.recommendations[] | {section: "recommendations", name, version, url: .urls.amd64})
|
||||
]
|
||||
| map(. + {repo: (.url | capture("https://github.com/(?<r>[^/]+/[^/]+)/releases").r)})
|
||||
| map(del(.url))
|
||||
| {include: .}
|
||||
' contrib/dependencies.json)
|
||||
echo "matrix=${matrix}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
update:
|
||||
name: 'update / ${{ matrix.name }}'
|
||||
runs-on: ubuntu-24.04
|
||||
needs: prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
concurrency:
|
||||
group: dependency-updates-${{ matrix.name }}
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Resolve latest release
|
||||
id: latest
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
REPO: ${{ matrix.repo }}
|
||||
CURRENT: ${{ matrix.version }}
|
||||
run: |
|
||||
tag=$(gh release view --repo "$REPO" --json tagName -q .tagName)
|
||||
latest="${tag#v}"
|
||||
echo "latest=${latest}" >> "$GITHUB_OUTPUT"
|
||||
if dpkg --compare-versions "$latest" gt "$CURRENT"; then
|
||||
echo "outdated=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "outdated=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Bump dependency entry
|
||||
if: steps.latest.outputs.outdated == 'true'
|
||||
env:
|
||||
SECTION: ${{ matrix.section }}
|
||||
NAME: ${{ matrix.name }}
|
||||
OLD: ${{ matrix.version }}
|
||||
NEW: ${{ steps.latest.outputs.latest }}
|
||||
run: |
|
||||
tmp=$(mktemp)
|
||||
jq --arg section "$SECTION" \
|
||||
--arg name "$NAME" \
|
||||
--arg old "$OLD" \
|
||||
--arg new "$NEW" '
|
||||
($old) as $oldv |
|
||||
($new) as $newv |
|
||||
(.[$section]) |= map(
|
||||
if .name == $name then
|
||||
.version = $newv
|
||||
| .urls.amd64 |= (gsub("v" + $oldv; "v" + $newv) | gsub($oldv; $newv))
|
||||
| .urls.arm64 |= (gsub("v" + $oldv; "v" + $newv) | gsub($oldv; $newv))
|
||||
else . end
|
||||
)
|
||||
' contrib/dependencies.json > "$tmp"
|
||||
mv "$tmp" contrib/dependencies.json
|
||||
|
||||
- name: Open pull request
|
||||
if: steps.latest.outputs.outdated == 'true'
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
branch: chore/bump-${{ matrix.name }}-${{ steps.latest.outputs.latest }}
|
||||
base: ${{ github.ref_name }}
|
||||
delete-branch: true
|
||||
committer: 'Dokku Bot <no-reply@dokku.com>'
|
||||
author: 'Dokku Bot <no-reply@dokku.com>'
|
||||
commit-message: 'chore: bump ${{ matrix.name }} to ${{ steps.latest.outputs.latest }}'
|
||||
title: 'chore: bump ${{ matrix.name }} to ${{ steps.latest.outputs.latest }}'
|
||||
body: |
|
||||
Bumps `${{ matrix.name }}` from `${{ matrix.version }}` to `${{ steps.latest.outputs.latest }}`.
|
||||
|
||||
Release notes: https://github.com/${{ matrix.repo }}/releases/tag/v${{ steps.latest.outputs.latest }}
|
||||
labels: dependencies
|
||||
10
Dockerfile
10
Dockerfile
@@ -15,6 +15,7 @@ RUN addgroup --gid $DOKKU_GID dokku \
|
||||
|
||||
COPY ./tests/dhparam.pem /tmp/dhparam.pem
|
||||
COPY ./build/package/ /tmp
|
||||
COPY ./contrib/dependencies.json /tmp/dependencies.json
|
||||
|
||||
ENV DOKKU_INIT_SYSTEM=sv
|
||||
|
||||
@@ -22,12 +23,15 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
# hadolint ignore=DL3005,DL3008
|
||||
RUN mkdir -p /etc/apt/keyrings \
|
||||
&& mkdir -p /etc/apt/keyrings \
|
||||
&& apt-get remove -y systemd && apt-get autoremove -y && apt-get update && apt-get -y --no-install-recommends install gpg lsb-release openssl openssh-server rsync software-properties-common \
|
||||
&& apt-get remove -y systemd && apt-get autoremove -y && apt-get update && apt-get -y --no-install-recommends install gpg jq lsb-release openssl openssh-server rsync software-properties-common \
|
||||
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
|
||||
&& add-apt-repository ppa:cncf-buildpacks/pack-cli \
|
||||
&& apt-get update \
|
||||
&& apt-get -y --no-install-recommends install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin pack-cli \
|
||||
&& apt-get -y --no-install-recommends install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
|
||||
&& PACK_URL="$(jq -r --arg arch "$(dpkg --print-architecture)" '.dependencies[] | select(.name == "pack") | .urls[$arch]' /tmp/dependencies.json)" \
|
||||
&& curl -fsSL "$PACK_URL" | tar -C /usr/bin/ --no-same-owner -xzf - pack \
|
||||
&& chmod +x /usr/bin/pack \
|
||||
&& test -x /usr/bin/pack \
|
||||
&& curl -o /tmp/nixpacks.bash -sSL https://nixpacks.com/install.sh \
|
||||
&& chmod +x /tmp/nixpacks.bash \
|
||||
&& NIXPACKS_BIN_DIR=/usr/bin BIN_DIR=/usr/bin /tmp/nixpacks.bash \
|
||||
|
||||
157
HISTORY.md
157
HISTORY.md
@@ -1,5 +1,162 @@
|
||||
# History
|
||||
|
||||
## 0.38.1
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.1/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.1 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8563: @josegonzalez Source property-functions where fn-plugin-property-* helpers are used
|
||||
- #8559: @josegonzalez Install cnb pack from github releases instead of ppa
|
||||
- #8558: @josegonzalez Chown migrated legacy storage entries to dokku
|
||||
- #8545: @josegonzalez Deflake haproxy bats tests
|
||||
|
||||
### Refactors
|
||||
|
||||
- #8546: @josegonzalez Consolidate nginx.conf.sigil server blocks
|
||||
|
||||
### Documentation
|
||||
|
||||
- #8548: @josegonzalez Use explicit type property in proxy:set examples
|
||||
- #8547: @josegonzalez Document plugin properties migrated from env vars
|
||||
- #8544: @josegonzalez Fix reference to when the build plugin was introduced
|
||||
|
||||
### Tests
|
||||
|
||||
- #8565: @dependabot[bot] chore(deps): bump google.golang.org/grpc from 1.80.0 to 1.81.0 in /tests/apps/gogrpc
|
||||
- #8568: @dependabot[bot] chore(deps): bump gunicorn from 25.3.0 to 26.0.0 in /tests/apps/multi
|
||||
- #8572: @dependabot[bot] chore(deps): bump django from 5.2.13 to 5.2.14 in /tests/apps/dockerfile-release
|
||||
- #8570: @dependabot[bot] chore(deps): bump gunicorn from 25.3.0 to 26.0.0 in /tests/apps/dockerfile-release
|
||||
- #8567: @dependabot[bot] chore(deps): bump gunicorn from 25.3.0 to 26.0.0 in /tests/apps/python-flask
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8571: @dependabot[bot] chore(deps): bump traefik from v3.6.15 to v3.7.0 in /plugins/traefik-vhosts
|
||||
- #8569: @dependabot[bot] chore(deps): bump github.com/traefik/traefik/v2 from 2.11.44 to 2.11.45 in /plugins/scheduler-k3s
|
||||
- #8561: @dokku-bot chore: bump pack to 0.40.4
|
||||
- #8555: @dependabot[bot] chore(deps): bump github.com/mattn/go-isatty from 0.0.20 to 0.0.22 in /plugins/app-json
|
||||
- #8556: @dependabot[bot] chore(deps): bump github.com/Masterminds/semver/v3 from 3.4.0 to 3.5.0 in /plugins/scheduler-k3s
|
||||
- #8550: @dokku-bot chore: bump docker-container-healthchecker to 0.15.2
|
||||
- #8553: @dokku-bot chore: bump dokku-event-listener to 0.19.1
|
||||
- #8552: @dokku-bot chore: bump lambda-builder to 0.9.3
|
||||
- #8551: @dokku-bot chore: bump procfile-util to 0.20.7
|
||||
- #8554: @dependabot[bot] chore(deps): bump peter-evans/create-pull-request from 7 to 8
|
||||
|
||||
## 0.38.0
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.0/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.0 bash bootstrap.sh
|
||||
```
|
||||
|
||||
See the [0.38.0 migration guide](/docs/appendices/0.38.0-migration-guide.md) for more information on migrating to 0.38.0.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8533: @josegonzalez Split env config and image pull secret into separate helm releases
|
||||
- #8530: @josegonzalez Split multi-flag input in docker-options
|
||||
- #8528: @josegonzalez Skip retiring images still in use by app containers
|
||||
- #8525: @josegonzalez Add launcher entrypoint for CNB images on dokku run and cron:run
|
||||
- #8522: @josegonzalez Only emit keda fallback when a non-cpu/memory trigger exists
|
||||
- #8515: @josegonzalez Fix vector mount directory config
|
||||
- #8508: @josegonzalez Preserve all domains when renaming an app
|
||||
- #8507: @josegonzalez Retire orphaned containers when scaling down
|
||||
|
||||
### New Features
|
||||
|
||||
- #8538: @josegonzalez Add scheduler-aware named storage entries
|
||||
- #8527: @josegonzalez Accept --global on :report subcommands
|
||||
- #8524: @josegonzalez Pre-validate custom nginx.conf.sigil during core-post-extract
|
||||
- #8523: @josegonzalez Support resource limits on the build container
|
||||
- #8517: @josegonzalez Send SIGTERM to old containers immediately on deploy
|
||||
- #8516: @josegonzalez Scope docker-options to specific procfile processes
|
||||
- #8509: @josegonzalez Ship default catch-all site on fresh apt install
|
||||
- #8506: @josegonzalez Add --format json to git:report and nginx:report
|
||||
- #8505: @josegonzalez Add git:auth-status to check netrc match
|
||||
- #8493: @josegonzalez Generate 502 config for apps without web listeners
|
||||
- #8404: @josegonzalez Upgrade vector chart from 0.42.0 to 0.52.0
|
||||
- #8403: @josegonzalez Upgrade ingress-nginx chart from 4.10.0 to 4.15.1
|
||||
- #8402: @josegonzalez Upgrade keda to 2.19.0 and keda-add-ons-http to 0.12.2
|
||||
- #8259: @josegonzalez Add post-create support for env key in app.json
|
||||
- #8157: @josegonzalez Add support for specifying buildpacks via app.json
|
||||
- #8154: @josegonzalez Enable live-restore by default when installing Dokku
|
||||
- #3697: @josegonzalez Migrate builds plugin to go and track per-build records
|
||||
|
||||
### Refactors
|
||||
|
||||
- #8514: @josegonzalez Migrate docker-options subcommands to go
|
||||
- #6716: @josegonzalez Move app and global ENV files to consolidated config path
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8541: @dependabot[bot] chore(deps): bump traefik from v3.6.14 to v3.6.15 in /plugins/traefik-vhosts
|
||||
- #8537: @dependabot[bot] chore(deps): bump github.com/traefik/traefik/v2 from 2.11.43 to 2.11.44 in /plugins/scheduler-k3s
|
||||
- #8535: @dependabot[bot] chore(deps): bump github.com/onsi/gomega from 1.39.1 to 1.40.0 in /plugins/common
|
||||
- #8529: @josegonzalez chore: bump dokku/netrc to v0.11.0
|
||||
- #8520: @dependabot[bot] chore(deps): bump packaging from 26.1 to 26.2 in /docs/_build
|
||||
- #8510: @dependabot[bot] chore(deps): bump packaging from 26.1 to 26.2 in /docs/_build
|
||||
- #8503: @josegonzalez Bump dependency versions and add daily updater workflow
|
||||
- #8502: @josegonzalez Bump go version to 1.26.2
|
||||
- #8495: @dependabot[bot] chore(deps): bump k8s.io/apimachinery from 0.35.4 to 0.36.0 in /plugins/scheduler-k3s
|
||||
- #8494: @dependabot[bot] chore(deps): bump dokku/openresty-docker-proxy from 0.9.3 to 0.10.0 in /plugins/openresty-vhosts
|
||||
- #8490: @dependabot[bot] chore(deps): bump k8s.io/kubernetes from 1.35.4 to 1.36.0 in /plugins/scheduler-k3s
|
||||
|
||||
### Other
|
||||
|
||||
- #8498: @josegonzalez Migrate environment variables to plugin properties
|
||||
|
||||
## 0.37.10
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.37.10/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.10 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Tests
|
||||
|
||||
- #8491: @dependabot[bot] chore(deps-dev): bump heroku/heroku-buildpack-php from 285 to 287 in /tests/apps/php
|
||||
- #8478: @josegonzalez chore: label test app dependency updates as type: tests
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8486: @dependabot[bot] chore(deps): bump click from 8.3.2 to 8.3.3 in /docs/_build
|
||||
- #8492: @dependabot[bot] chore(deps): bump github.com/fluxcd/pkg/kustomize from 1.29.0 to 1.31.0 in /plugins/scheduler-k3s
|
||||
- #8489: @dependabot[bot] chore(deps): bump github.com/traefik/traefik/v2 from 2.11.42 to 2.11.43 in /plugins/scheduler-k3s
|
||||
- #8488: @dependabot[bot] chore(deps): bump timberio/vector from 0.54.0-debian to 0.55.0-debian in /plugins/logs
|
||||
- #8487: @dependabot[bot] chore(deps): bump traefik from v3.6.13 to v3.6.14 in /plugins/traefik-vhosts
|
||||
- #8483: @dependabot[bot] chore(deps): update markdown requirement from <3.11,>=3.2.1 to >=3.10.2,<3.11 in /docs/_build
|
||||
- #8485: @dependabot[bot] chore(deps): bump k8s.io/kubectl from 0.35.2 to 0.35.4 in /plugins/scheduler-k3s
|
||||
- #8484: @dependabot[bot] chore(deps): bump k8s.io/client-go from 0.35.2 to 0.35.4 in /plugins/scheduler-k3s
|
||||
- #8482: @dependabot[bot] chore(deps): bump ruby from 4.0.2 to 4.0.3 in /tests/apps/dockerfile-entrypoint
|
||||
- #8481: @dependabot[bot] chore(deps): bump psycopg2-binary from 2.9.11 to 2.9.12 in /tests/apps/dockerfile-release
|
||||
- #8479: @dependabot[bot] chore(deps): bump github.com/go-openapi/jsonpointer from 0.23.0 to 0.23.1 in /plugins/scheduler-k3s
|
||||
- #8480: @dependabot[bot] chore(deps): bump k8s.io/kubernetes from 1.35.3 to 1.35.4 in /plugins/scheduler-k3s
|
||||
|
||||
## 0.37.9
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.37.9/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.9 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8473: @dependabot[bot] chore(deps): bump k8s.io/api from 0.35.2 to 0.35.4 in /plugins/scheduler-k3s
|
||||
- #8474: @dependabot[bot] chore(deps): bump github.com/go-openapi/jsonpointer from 0.22.5 to 0.23.0 in /plugins/scheduler-k3s
|
||||
- #8476: @dependabot[bot] chore(deps): bump github.com/go-acme/lego/v4 from 4.25.2 to 4.34.0 in /plugins/scheduler-k3s
|
||||
- #8475: @dependabot[bot] chore(deps): bump github.com/moby/spdystream from 0.5.0 to 0.5.1 in /plugins/scheduler-k3s
|
||||
|
||||
## 0.37.8
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
@@ -85,8 +85,8 @@ Otherwise, you will need to import the keypair manually after installation using
|
||||
To install the latest stable release, run the following commands as a user who has access to `sudo`:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.37.8/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.8 bash bootstrap.sh
|
||||
wget -NP . https://dokku.com/install/v0.38.1/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.1 bash bootstrap.sh
|
||||
```
|
||||
|
||||
You can then proceed to configure your server domain (via `dokku domains:set-global`) and user access (via `dokku ssh-keys:add`) to complete the installation.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
GO_ARGS ?=
|
||||
GO_PLUGIN_MAKE_TARGET ?= build
|
||||
GO_REPO_ROOT := /go/src/github.com/dokku/dokku
|
||||
BUILD_IMAGE := golang:1.25.5
|
||||
BUILD_IMAGE := golang:1.26.2
|
||||
GO_BUILD_CACHE ?= /tmp/dokku-go-build-cache
|
||||
GO_MOD_CACHE ?= /tmp/dokku-go-mod-mod
|
||||
GO_ROOT_MOUNT ?= $$PWD/../..:$(GO_REPO_ROOT)
|
||||
|
||||
@@ -2,94 +2,102 @@
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "docker-container-healthchecker",
|
||||
"version": "0.14.0",
|
||||
"version": "0.15.2",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/docker-container-healthchecker/releases/download/v0.14.0/docker-container-healthchecker-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/docker-container-healthchecker/releases/download/v0.14.0/docker-container-healthchecker-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/docker-container-healthchecker/releases/download/v0.15.2/docker-container-healthchecker-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/docker-container-healthchecker/releases/download/v0.15.2/docker-container-healthchecker-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "docker-image-labeler",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.0",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/docker-image-labeler/releases/download/v0.8.1/docker-image-labeler-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/docker-image-labeler/releases/download/v0.8.1/docker-image-labeler-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/docker-image-labeler/releases/download/v0.9.0/docker-image-labeler-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/docker-image-labeler/releases/download/v0.9.0/docker-image-labeler-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lambda-builder",
|
||||
"version": "0.9.1",
|
||||
"version": "0.9.3",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/lambda-builder/releases/download/v0.9.1/lambda-builder-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/lambda-builder/releases/download/v0.9.1/lambda-builder-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/lambda-builder/releases/download/v0.9.3/lambda-builder-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/lambda-builder/releases/download/v0.9.3/lambda-builder-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "netrc",
|
||||
"version": "0.10.2",
|
||||
"version": "0.11.0",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/netrc/releases/download/v0.10.2/netrc-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/netrc/releases/download/v0.10.2/netrc-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/netrc/releases/download/v0.11.0/netrc-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/netrc/releases/download/v0.11.0/netrc-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pack",
|
||||
"version": "0.40.4",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/buildpacks/pack/releases/download/v0.40.4/pack-v0.40.4-linux.tgz",
|
||||
"arm64": "https://github.com/buildpacks/pack/releases/download/v0.40.4/pack-v0.40.4-linux-arm64.tgz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "procfile-util",
|
||||
"version": "0.20.3",
|
||||
"version": "0.20.7",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/procfile-util/releases/download/v0.20.3/procfile-util-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/procfile-util/releases/download/v0.20.3/procfile-util-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/procfile-util/releases/download/v0.20.7/procfile-util-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/procfile-util/releases/download/v0.20.7/procfile-util-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sshcommand",
|
||||
"version": "0.20.0",
|
||||
"version": "0.20.1",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/sshcommand/releases/download/v0.20.0/sshcommand",
|
||||
"arm64": "https://github.com/dokku/sshcommand/releases/download/v0.20.0/sshcommand"
|
||||
"amd64": "https://github.com/dokku/sshcommand/releases/download/v0.20.1/sshcommand",
|
||||
"arm64": "https://github.com/dokku/sshcommand/releases/download/v0.20.1/sshcommand"
|
||||
}
|
||||
}
|
||||
],
|
||||
"predependencies": [
|
||||
{
|
||||
"name": "gliderlabs-sigil",
|
||||
"version": "0.11.4",
|
||||
"version": "0.12.0",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/gliderlabs/sigil/releases/download/v0.11.4/sigil-linux-amd64",
|
||||
"arm64": "https://github.com/gliderlabs/sigil/releases/download/v0.11.4/sigil-linux-arm64"
|
||||
"amd64": "https://github.com/gliderlabs/sigil/releases/download/v0.12.0/sigil-linux-amd64",
|
||||
"arm64": "https://github.com/gliderlabs/sigil/releases/download/v0.12.0/sigil-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "plugn",
|
||||
"version": "0.16.0",
|
||||
"version": "0.17.0",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/plugn/releases/download/v0.16.0/plugn-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/plugn/releases/download/v0.16.0/plugn-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/plugn/releases/download/v0.17.0/plugn-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/plugn/releases/download/v0.17.0/plugn-linux-arm64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"recommendations": [
|
||||
{
|
||||
"name": "dokku-event-listener",
|
||||
"version": "0.17.2",
|
||||
"version": "0.19.1",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/dokku-event-listener/releases/download/v0.17.2/dokku-event-listener-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/dokku-event-listener/releases/download/v0.17.2/dokku-event-listener-linux-arm64"
|
||||
"amd64": "https://github.com/dokku/dokku-event-listener/releases/download/v0.19.1/dokku-event-listener-linux-amd64",
|
||||
"arm64": "https://github.com/dokku/dokku-event-listener/releases/download/v0.19.1/dokku-event-listener-linux-arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dokku-update",
|
||||
"version": "0.9.6",
|
||||
"version": "0.9.8",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/dokku/dokku-update/releases/download/v0.9.6/dokku-update",
|
||||
"arm64": "https://github.com/dokku/dokku-update/releases/download/v0.9.6/dokku-update"
|
||||
"amd64": "https://github.com/dokku/dokku-update/releases/download/v0.9.8/dokku-update",
|
||||
"arm64": "https://github.com/dokku/dokku-update/releases/download/v0.9.8/dokku-update"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "herokuish",
|
||||
"version": "0.11.8",
|
||||
"version": "0.11.11",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/gliderlabs/herokuish/releases/download/v0.11.8/herokuish_0.11.8_linux_x86_64.tgz",
|
||||
"arm64": "https://github.com/gliderlabs/herokuish/releases/download/v0.11.8/herokuish_0.11.8_linux_x86_64.tgz"
|
||||
"amd64": "https://github.com/gliderlabs/herokuish/releases/download/v0.11.11/herokuish_0.11.11_linux_x86_64.tgz",
|
||||
"arm64": "https://github.com/gliderlabs/herokuish/releases/download/v0.11.11/herokuish_0.11.11_linux_x86_64.tgz"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import re
|
||||
|
||||
|
||||
def main():
|
||||
@@ -18,11 +19,9 @@ def main():
|
||||
for dependency in deps[key]:
|
||||
name = dependency["name"]
|
||||
version = dependency["version"]
|
||||
pattern = re.compile(rf"(?<![\w-]){re.escape(name)}(?![\w-])")
|
||||
for i, line in enumerate(control_lines):
|
||||
if name in line:
|
||||
control_lines[i] = control_lines[i].replace(
|
||||
name, f"{name} (>= {version})"
|
||||
)
|
||||
control_lines[i] = pattern.sub(f"{name} (>= {version})", line)
|
||||
|
||||
with open("debian/control", mode="w", encoding="utf-8") as handle:
|
||||
handle.writelines(control_lines)
|
||||
|
||||
1
debian/config
vendored
1
debian/config
vendored
@@ -14,5 +14,6 @@ db_input "high" "dokku/hostname" || true
|
||||
db_input "high" "dokku/vhost_enable" || true
|
||||
if [ "$ACTION" != "reconfigure" ]; then
|
||||
db_input "high" "dokku/key_file" || true
|
||||
db_input "high" "dokku/install_default_site" || true
|
||||
fi
|
||||
db_go || true
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -1,5 +1,5 @@
|
||||
Package: dokku
|
||||
Version: 0.37.8
|
||||
Version: 0.38.1
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
|
||||
62
debian/postinst
vendored
62
debian/postinst
vendored
@@ -135,6 +135,65 @@ setup-sshcommand() {
|
||||
fi
|
||||
}
|
||||
|
||||
disable-default-vhost-path() {
|
||||
local path="$1"
|
||||
local backup_path="${path}.dokku-disabled"
|
||||
|
||||
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -e "$backup_path" ] || [ -L "$backup_path" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
case "$path" in
|
||||
/etc/nginx/sites-enabled/*)
|
||||
rm -f "$path"
|
||||
echo "Removed conflicting nginx default at $path" 1>&2
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -L "$path" ]; then
|
||||
rm -f "$path"
|
||||
echo "Removed conflicting nginx default symlink at $path" 1>&2
|
||||
return
|
||||
fi
|
||||
|
||||
mv -n "$path" "$backup_path"
|
||||
echo "Disabled $path (renamed to $backup_path)" 1>&2
|
||||
}
|
||||
|
||||
setup-default-site() {
|
||||
db_get "dokku/install_default_site"
|
||||
if [ "$RET" != "true" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local default_vhost_target="/etc/nginx/conf.d/00-default-vhost.conf"
|
||||
local default_vhost_source="${DOKKU_LIB_ROOT}/core-plugins/available/nginx-vhosts/templates/default-site.conf"
|
||||
|
||||
if [ -e "$default_vhost_target" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$default_vhost_source" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
for path in /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default /etc/nginx/conf.d/default.conf; do
|
||||
disable-default-vhost-path "$path"
|
||||
done
|
||||
|
||||
echo "Installing nginx default catch-all site at $default_vhost_target"
|
||||
install -m 0644 -o root -g root "$default_vhost_source" "$default_vhost_target"
|
||||
|
||||
if command -v dokku &>/dev/null; then
|
||||
dokku nginx:reload || true
|
||||
fi
|
||||
}
|
||||
|
||||
dpkg-handling() {
|
||||
if [ -f "${DOKKU_ROOT}/VHOST" ]; then
|
||||
echo "VHOST file detected, skipping modification"
|
||||
@@ -170,6 +229,9 @@ case "$1" in
|
||||
setup-plugins
|
||||
setup-sshcommand
|
||||
setup-docker-live-restore
|
||||
if [ -z "$2" ]; then
|
||||
setup-default-site
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
5
debian/templates
vendored
5
debian/templates
vendored
@@ -22,3 +22,8 @@ Template: dokku/nginx_enable
|
||||
Description: Enable nginx-vhosts plugin?
|
||||
Type: boolean
|
||||
Default: true
|
||||
|
||||
Template: dokku/install_default_site
|
||||
Description: Install a catch-all nginx default site on fresh install?
|
||||
Type: boolean
|
||||
Default: true
|
||||
|
||||
@@ -96,6 +96,7 @@ This documentation covers the installation, configuration, and usage of Dokku -
|
||||
- [Plugin Management](advanced-usage/plugin-management.md) - Install and manage plugins
|
||||
- [Registry Management](advanced-usage/registry-management.md) - Docker registry integration
|
||||
- [Repository Management](advanced-usage/repository-management.md) - Git repository settings
|
||||
- [Build Tracking](advanced-usage/builds.md) - Inspect, cancel, and manage builds
|
||||
- [Deployment Tasks](advanced-usage/deployment-tasks.md) - Pre/post deploy hooks
|
||||
- [Event Logs](advanced-usage/event-logs.md) - Dokku event history
|
||||
- [Backup and Recovery](advanced-usage/backup-recovery.md) - Data backup strategies
|
||||
@@ -121,6 +122,7 @@ This documentation covers the installation, configuration, and usage of Dokku -
|
||||
|
||||
### Migration Guides
|
||||
|
||||
- [0.38.0](appendices/0.38.0-migration-guide.md)
|
||||
- [0.37.0](appendices/0.37.0-migration-guide.md)
|
||||
- [0.36.0](appendices/0.36.0-migration-guide.md)
|
||||
- [0.35.0](appendices/0.35.0-migration-guide.md)
|
||||
|
||||
6
docs/_build/requirements.txt
vendored
6
docs/_build/requirements.txt
vendored
@@ -1,16 +1,16 @@
|
||||
beautifulsoup4==4.14.3
|
||||
click==8.3.2
|
||||
click==8.3.3
|
||||
ghp-import==2.1.0
|
||||
importlib-metadata==9.0.0
|
||||
Jinja2==3.1.6
|
||||
Markdown>=3.2.1,<3.11
|
||||
Markdown>=3.10.2,<3.11
|
||||
MarkupSafe==3.0.3
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.6.1
|
||||
mkdocs-exclude==1.0.2
|
||||
mkdocs-material==9.7.6
|
||||
mkdocs-material-extensions==1.3.1
|
||||
packaging==26.1
|
||||
packaging==26.2
|
||||
Pygments==2.20.0
|
||||
pymdown-extensions==10.21.2
|
||||
pyparsing==3.3.2
|
||||
|
||||
171
docs/advanced-usage/builds.md
Normal file
171
docs/advanced-usage/builds.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# Build Tracking
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
Every deploy that flows through Dokku - whether triggered by `git push`, `ps:rebuild`, `ps:restart`, `config:set`, or `git:from-archive` / `git:from-image` / `git:sync` / `git:load-image` - is recorded as a structured build record on disk. The `builds` plugin lets operators inspect what is currently deploying, look up the result of an old deploy, and stream the captured build log without depending on `journalctl`.
|
||||
|
||||
```
|
||||
builds:cancel <app> # Cancel a running build for an app
|
||||
builds:info <app> <build-id> [--format json] # Show details for a single build
|
||||
builds:list [<app>] [--format json] [--kind ...] [--status ...]
|
||||
# List builds (running across all apps, or running + history for one)
|
||||
builds:output <app> [<build-id>|current] # Show build output (tail for live, cat for finished)
|
||||
builds:prune <app> [--all-apps] # Reap abandoned records and apply retention
|
||||
builds:report [<app>] [<flag>] # Display a build report
|
||||
builds:set [--global|<app>] <key> [<value>] # Set or clear a builds property
|
||||
```
|
||||
|
||||
## Build records
|
||||
|
||||
Every build is identified by a sortable base36 ULID-style id (`DOKKU_BUILD_ID`) generated at deploy start. For each build, Dokku writes:
|
||||
|
||||
- `$DOKKU_LIB_ROOT/data/builds/<app>/<build-id>.json` - the structured record
|
||||
- `$DOKKU_LIB_ROOT/data/builds/<app>/<build-id>.log` - the captured stdout/stderr of the deploy
|
||||
|
||||
Output is also tagged into syslog as `dokku-<build-id>` so `journalctl -t dokku-<build-id>` continues to work. The on-disk log file is the durable source of truth and is read for `builds:output` even when journald has rotated old entries away.
|
||||
|
||||
### Record schema
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "01j8c4xv7bk5w3",
|
||||
"app": "myapp",
|
||||
"kind": "build",
|
||||
"pid": 12345,
|
||||
"started_at": "2026-04-30T13:50:00Z",
|
||||
"finished_at": "2026-04-30T13:51:14Z",
|
||||
"status": "succeeded",
|
||||
"source": "git-hook",
|
||||
"exit_code": 0
|
||||
}
|
||||
```
|
||||
|
||||
- **kind** - `build` for paths that produce a new image (`git push`, `git:*`, `ps:rebuild`); `deploy` for paths that re-deploy an existing image (`ps:restart`, `ps:start`, `dokku deploy`, `config:set`).
|
||||
- **status** - on-disk values are `running | succeeded | failed | canceled`. `abandoned` is a fifth display-only value computed at read time for `running` records whose PID is no longer alive; it is never persisted to the record.
|
||||
- **source** - the user-typed command that originated the deploy (e.g. `git-hook`, `ps:restart`, `config-redeploy`, `git:sync`).
|
||||
|
||||
## Listing builds
|
||||
|
||||
Without an app argument, `builds:list` shows currently-running builds across every app on the host:
|
||||
|
||||
```shell
|
||||
dokku builds:list
|
||||
```
|
||||
|
||||
```
|
||||
=====> Currently running builds
|
||||
App Build ID Kind PID Source Started
|
||||
myapp 01j8c4xv7bk5w3 build 12345 git-hook 2026-04-30T13:50:00Z
|
||||
```
|
||||
|
||||
With an app, `builds:list` returns running builds plus the most recent finalized records up to the configured retention:
|
||||
|
||||
```shell
|
||||
dokku builds:list myapp
|
||||
```
|
||||
|
||||
Filter by kind or status:
|
||||
|
||||
```shell
|
||||
dokku builds:list myapp --kind build
|
||||
dokku builds:list myapp --status running
|
||||
dokku builds:list --format json
|
||||
```
|
||||
|
||||
## Inspecting a single build
|
||||
|
||||
```shell
|
||||
dokku builds:info myapp 01j8c4xv7bk5w3
|
||||
```
|
||||
|
||||
```
|
||||
=====> Build 01j8c4xv7bk5w3
|
||||
Build ID: 01j8c4xv7bk5w3
|
||||
App: myapp
|
||||
Kind: build
|
||||
Status: succeeded
|
||||
PID: 12345
|
||||
Source: git-hook
|
||||
Started: 2026-04-30T13:50:00Z
|
||||
Finished: 2026-04-30T13:51:14Z
|
||||
Duration: 1m14s
|
||||
Exit Code: 0
|
||||
Log: /var/lib/dokku/data/builds/myapp/01j8c4xv7bk5w3.log
|
||||
```
|
||||
|
||||
JSON output includes the same fields plus a computed `log_path`:
|
||||
|
||||
```shell
|
||||
dokku builds:info myapp 01j8c4xv7bk5w3 --format json | jq .
|
||||
```
|
||||
|
||||
## Streaming build output
|
||||
|
||||
```shell
|
||||
# tail -f the live build, or cat the log for a finished one
|
||||
dokku builds:output myapp 01j8c4xv7bk5w3
|
||||
|
||||
# resolve "current" from the in-flight deploy
|
||||
dokku builds:output myapp current
|
||||
```
|
||||
|
||||
If the on-disk log file is missing (for example, a build from before this plugin was installed), `builds:output` falls back to `journalctl -t dokku-<build-id>`.
|
||||
|
||||
## Cancelling a build
|
||||
|
||||
`builds:cancel` reads the active `.deploy.lock` for an app, looks up the matching build record, and sends `SIGQUIT` to the deploy's process group. The record is finalized as `canceled` (or `failed` if the process had already exited without finalizing - in that case Dokku marks the record so it doesn't sit in `running` forever).
|
||||
|
||||
```shell
|
||||
dokku builds:cancel myapp
|
||||
```
|
||||
|
||||
If the record is already finalized when cancel runs, no signal is sent and the record is left untouched.
|
||||
|
||||
## Retention
|
||||
|
||||
Build records are pruned by count, not by age. The default retention is **20** records per app. Live in-flight deploys are never pruned regardless of count.
|
||||
|
||||
Set a per-app retention:
|
||||
|
||||
```shell
|
||||
dokku builds:set myapp retention 50
|
||||
```
|
||||
|
||||
Set the global default:
|
||||
|
||||
```shell
|
||||
dokku builds:set --global retention 10
|
||||
```
|
||||
|
||||
Clear an override (falls back to the global value, then the default):
|
||||
|
||||
```shell
|
||||
dokku builds:set myapp retention
|
||||
```
|
||||
|
||||
## Manual pruning
|
||||
|
||||
`builds:prune` invokes the same logic that runs at the end of every deploy - it reaps abandoned records (status=running with a dead PID, finalized as `failed`) and trims the directory to the configured retention. Useful after lowering retention via `builds:set` or to clean up after a host reboot:
|
||||
|
||||
```shell
|
||||
dokku builds:prune myapp
|
||||
dokku builds:prune --all-apps
|
||||
```
|
||||
|
||||
## Reports
|
||||
|
||||
```shell
|
||||
dokku builds:report
|
||||
dokku builds:report myapp
|
||||
dokku builds:report myapp --build-status
|
||||
```
|
||||
|
||||
Available flags:
|
||||
|
||||
- `--build-id`, `--build-kind`, `--build-status`, `--build-pid`, `--build-source`, `--build-started-at`, `--build-finished-at`, `--build-exit-code`: details of the most recent build for the app
|
||||
- `--builds-retention`: per-app retention override (empty if none)
|
||||
- `--builds-global-retention`: global retention override (empty if none)
|
||||
- `--builds-computed-retention`: the resolved retention applied to this app
|
||||
|
||||
`--build-status` returns the **display** status, so an abandoned in-flight build shows `abandoned` rather than `running`. The raw on-disk status is only visible by reading the JSON record directly.
|
||||
@@ -4,10 +4,11 @@
|
||||
> New as of 0.3.17
|
||||
|
||||
```
|
||||
docker-options:add <app> <phase(s)> OPTION # Add Docker option to app for phase (comma-separated phase list)
|
||||
docker-options:clear <app> [<phase(s)>...] # Clear a docker options from app
|
||||
docker-options:remove <app> <phase(s)> OPTION # Remove Docker option from app for phase (comma-separated phase list)
|
||||
docker-options:report [<app>] [<flag>] # Displays a docker options report for one or more apps
|
||||
docker-options:add [--process PROC...] <app> <phase(s)> OPTION # Add Docker option to app for phase
|
||||
docker-options:clear [--process PROC...] <app> [<phase(s)>...] # Clear docker options from app
|
||||
docker-options:list <app> [--process PROC] --phase PHASE # List docker options for one process+phase pair
|
||||
docker-options:remove [--process PROC...] <app> <phase(s)> OPTION # Remove Docker option from app for phase
|
||||
docker-options:report [<app>] [<flag>] [--format json|stdout] # Displays a docker options report for one or more apps
|
||||
```
|
||||
|
||||
The `docker-options` plugin allows users to specify custom [container options](https://docs.docker.com/engine/reference/run/) for containers created by Dokku at various phases.
|
||||
@@ -57,11 +58,17 @@ Multiple phases can be specified by using a comma when specifying phases:
|
||||
dokku docker-options:add node-js-app deploy,run "--ulimit nofile=12"
|
||||
```
|
||||
|
||||
The `docker-options:add` does not support setting multiple options in a single call. To specify multiple options, call `docker-options:add` multiple times.
|
||||
Multiple docker options can also be specified in a single call. Each `--flag [value]` group is detected on flag boundaries, shell-tokenized for quoting safety, and stored as its own entry so it round-trips through `docker-options:report` and `docker-options:list`:
|
||||
|
||||
```shell
|
||||
dokku docker-options:add node-js-app deploy "--ulimit nofile=12"
|
||||
dokku docker-options:add node-js-app deploy "--shm-size 256m"
|
||||
dokku docker-options:add node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"
|
||||
```
|
||||
|
||||
A misplaced `--process PROC` (i.e. one specified after the app name instead of before it) is honored as a subcommand flag rather than stored as a docker option, so the example above and the equivalent process-scoped form below behave identically:
|
||||
|
||||
```shell
|
||||
dokku docker-options:add --process web node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"
|
||||
dokku docker-options:add node-js-app deploy "--ulimit nofile=12" "--shm-size 256m" --process web
|
||||
```
|
||||
|
||||
#### Remove a Docker option
|
||||
@@ -78,11 +85,10 @@ Multiple phases can be specified by using a comma when specifying phases:
|
||||
dokku docker-options:remove node-js-app deploy,run "--ulimit nofile=12"
|
||||
```
|
||||
|
||||
The `docker-options:remove` does not support setting multiple options in a single call. To specify multiple options, call `docker-options:remove` multiple times.
|
||||
Multiple docker options can also be removed in a single call, mirroring the splitting that `docker-options:add` performs:
|
||||
|
||||
```shell
|
||||
dokku docker-options:remove node-js-app deploy "--ulimit nofile=12"
|
||||
dokku docker-options:remove node-js-app deploy "--shm-size 256m"
|
||||
dokku docker-options:remove node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"
|
||||
```
|
||||
|
||||
#### Clear all Docker options for an app
|
||||
@@ -160,3 +166,67 @@ You can pass flags which will output only the value of the specific information
|
||||
```shell
|
||||
dokku docker-options:report node-js-app --docker-options-build
|
||||
```
|
||||
|
||||
When process-specific options are configured (see below), the report exposes one additional dynamic flag per configured `process.deploy` pair, named `--docker-options-deploy.<process>`:
|
||||
|
||||
```shell
|
||||
dokku docker-options:report node-js-app --docker-options-deploy.web
|
||||
```
|
||||
|
||||
A machine-readable JSON view is available via `--format json`:
|
||||
|
||||
```shell
|
||||
dokku docker-options:report node-js-app --format json
|
||||
```
|
||||
|
||||
### Process-Specific Options
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
Docker options can be scoped to specific process types declared in the app's `Procfile` by passing one or more `--process` flags. This is useful when a deploy-phase option (for example a port mapping) makes sense for one process type but would conflict with another - the canonical case being a `web` process that needs `-p 6789:5000` published while the `worker` process must not bind that port.
|
||||
|
||||
Process scoping is supported only for the `deploy` phase. The `build` phase runs once per app and the `run` phase covers ad-hoc commands and cron tasks where no Procfile process type is in play; both reject `--process`.
|
||||
|
||||
There is no `--global` flag. Omitting `--process` keeps the historical behavior of applying the option to every container in the app. Avoiding a `--global` flag here is intentional: elsewhere in Dokku `--global` means "across all apps" (e.g. `dokku config:set --global`), which would be misleading in this plugin where the scope is always one app.
|
||||
|
||||
#### Setting process-specific options
|
||||
|
||||
```shell
|
||||
# Add a port mapping only to the web process
|
||||
dokku docker-options:add --process web node-js-app deploy "-p 6789:5000"
|
||||
|
||||
# Add a GPU mount only to the worker process
|
||||
dokku docker-options:add --process worker node-js-app deploy "--gpus all"
|
||||
```
|
||||
|
||||
Multiple `--process` flags can be combined to apply the same option to several process types in one call:
|
||||
|
||||
```shell
|
||||
dokku docker-options:add --process web --process api node-js-app deploy "-v /shared:/shared"
|
||||
```
|
||||
|
||||
If `--process` names a process type that is not currently declared in the app's `Procfile`, the command succeeds but emits a warning. This allows configuring options ahead of a deploy that adds the new process type.
|
||||
|
||||
The `_default_` value is reserved internally and cannot be passed to `--process`.
|
||||
|
||||
#### Removing and clearing process-specific options
|
||||
|
||||
```shell
|
||||
# Remove a single option from one process
|
||||
dokku docker-options:remove --process web node-js-app deploy "-p 6789:5000"
|
||||
|
||||
# Clear every option for a process+phase
|
||||
dokku docker-options:clear --process worker node-js-app deploy
|
||||
```
|
||||
|
||||
Without `--process`, `:remove` and `:clear` operate on the default scope only - per-process lists are left untouched.
|
||||
|
||||
#### Listing options for a process and phase
|
||||
|
||||
The `docker-options:list` command prints the options stored for a single process+phase pair, one option per line. Omitting `--process` lists the default scope.
|
||||
|
||||
```shell
|
||||
dokku docker-options:list node-js-app --process web --phase deploy
|
||||
dokku docker-options:list node-js-app --phase deploy
|
||||
```
|
||||
|
||||
@@ -1,24 +1,37 @@
|
||||
# Persistent Storage
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.5.0
|
||||
> New as of 0.5.0. Named storage entries new as of 0.38.0.
|
||||
|
||||
The preferred method to mount external containers to a Dokku managed container, is to use the Dokku storage plugin.
|
||||
The preferred method to attach persistent storage to a Dokku-managed container is the Dokku storage plugin.
|
||||
|
||||
```
|
||||
storage:ensure-directory [--chown option] <directory> # Creates a persistent storage directory in the recommended storage path
|
||||
storage:list <app> [--format text|json] # List bind mounts for app's container(s) (host:container)
|
||||
storage:mount <app> <host-dir:container-dir> # Create a new bind mount
|
||||
storage:report [<app>] [<flag>] # Displays a checks report for one or more apps
|
||||
storage:unmount <app> <host-dir:container-dir> # Remove an existing bind mount
|
||||
storage:create <name> [<path>] [flags] # Register a named storage entry
|
||||
storage:destroy <name> # Remove a named storage entry (must be unmounted from every app first)
|
||||
storage:ensure-directory [--chown option] <directory> # [DEPRECATED] use storage:create instead
|
||||
storage:exec <name> [-- <cmd>...] # Run a command (or shell) in a temporary container that mounts the entry
|
||||
storage:info <name> [--format text|json] # Show details for one storage entry
|
||||
storage:list <app> [--format text|json] # List bind mounts for an app's container(s) (legacy host:container view)
|
||||
storage:list-entries [--scheduler s] [--format text|json] # List registered storage entries
|
||||
storage:mount <app> <name> --container-dir <path> [flags] # Mount a named entry into an app
|
||||
storage:mount <app> <host-dir:container-dir> # [LEGACY] colon-form mount, docker-local only
|
||||
storage:report [<app>] [<flag>] # Display a storage report for one or more apps
|
||||
storage:report --global # Display a cluster-wide entry inventory
|
||||
storage:set <name> [flags] # Update a storage entry in place
|
||||
storage:unmount <app> <name> [--container-dir <path>] # Remove an attachment
|
||||
storage:wait <name> # Block until a k3s entry's PVC is bound
|
||||
```
|
||||
|
||||
> The storage plugin is compatible with storage mounts created with the docker-options. The storage plugin will only list mounts from the deploy/run phase.
|
||||
A storage entry is the source of truth for the underlying volume - a host directory on docker-local, or a PersistentVolumeClaim on k3s. Multiple apps can mount the same entry, and an attachment carries the per-app details (container path, phases, subpath, readonly, process type). Names are globally unique across the install and must be DNS-1123 labels (lowercase letters, digits, dashes) of 45 characters or less so they can be used verbatim as Helm release and PVC names.
|
||||
|
||||
The legacy `storage:mount <app> <host>:<container>` form continues to work on docker-local. On a k3s app it is rejected; create a named entry with `storage:create --scheduler k3s` and mount it instead. Existing colon-form mounts are migrated automatically the first time the new code runs - they show up as `legacy-<hash>` entries in `storage:list-entries`.
|
||||
|
||||
The storage plugin supports the following mount points:
|
||||
|
||||
- explicit paths that exist on the host
|
||||
- docker volumes
|
||||
- explicit paths that exist on the host (docker-local)
|
||||
- docker volumes (docker-local)
|
||||
- PersistentVolumeClaims provisioned via a StorageClass (k3s)
|
||||
- hostPath-backed PVs (k3s)
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -36,35 +36,35 @@ dokku plugin:list
|
||||
|
||||
```
|
||||
plugn: dev
|
||||
00_dokku-standard 0.37.8 enabled dokku core standard plugin
|
||||
20_events 0.37.8 enabled dokku core events logging plugin
|
||||
app-json 0.37.8 enabled dokku core app-json plugin
|
||||
apps 0.37.8 enabled dokku core apps plugin
|
||||
build-env 0.37.8 enabled dokku core build-env plugin
|
||||
buildpacks 0.37.8 enabled dokku core buildpacks plugin
|
||||
certs 0.37.8 enabled dokku core certificate management plugin
|
||||
checks 0.37.8 enabled dokku core checks plugin
|
||||
common 0.37.8 enabled dokku core common plugin
|
||||
config 0.37.8 enabled dokku core config plugin
|
||||
docker-options 0.37.8 enabled dokku core docker-options plugin
|
||||
domains 0.37.8 enabled dokku core domains plugin
|
||||
enter 0.37.8 enabled dokku core enter plugin
|
||||
git 0.37.8 enabled dokku core git plugin
|
||||
logs 0.37.8 enabled dokku core logs plugin
|
||||
network 0.37.8 enabled dokku core network plugin
|
||||
nginx-vhosts 0.37.8 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.37.8 enabled dokku core plugin plugin
|
||||
proxy 0.37.8 enabled dokku core proxy plugin
|
||||
ps 0.37.8 enabled dokku core ps plugin
|
||||
repo 0.37.8 enabled dokku core repo plugin
|
||||
resource 0.37.8 enabled dokku core resource plugin
|
||||
scheduler-docker-local 0.37.8 enabled dokku core scheduler-docker-local plugin
|
||||
shell 0.37.8 enabled dokku core shell plugin
|
||||
ssh-keys 0.37.8 enabled dokku core ssh-keys plugin
|
||||
storage 0.37.8 enabled dokku core storage plugin
|
||||
tags 0.37.8 enabled dokku core tags plugin
|
||||
tar 0.37.8 enabled dokku core tar plugin
|
||||
trace 0.37.8 enabled dokku core trace plugin
|
||||
00_dokku-standard 0.38.1 enabled dokku core standard plugin
|
||||
20_events 0.38.1 enabled dokku core events logging plugin
|
||||
app-json 0.38.1 enabled dokku core app-json plugin
|
||||
apps 0.38.1 enabled dokku core apps plugin
|
||||
build-env 0.38.1 enabled dokku core build-env plugin
|
||||
buildpacks 0.38.1 enabled dokku core buildpacks plugin
|
||||
certs 0.38.1 enabled dokku core certificate management plugin
|
||||
checks 0.38.1 enabled dokku core checks plugin
|
||||
common 0.38.1 enabled dokku core common plugin
|
||||
config 0.38.1 enabled dokku core config plugin
|
||||
docker-options 0.38.1 enabled dokku core docker-options plugin
|
||||
domains 0.38.1 enabled dokku core domains plugin
|
||||
enter 0.38.1 enabled dokku core enter plugin
|
||||
git 0.38.1 enabled dokku core git plugin
|
||||
logs 0.38.1 enabled dokku core logs plugin
|
||||
network 0.38.1 enabled dokku core network plugin
|
||||
nginx-vhosts 0.38.1 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.38.1 enabled dokku core plugin plugin
|
||||
proxy 0.38.1 enabled dokku core proxy plugin
|
||||
ps 0.38.1 enabled dokku core ps plugin
|
||||
repo 0.38.1 enabled dokku core repo plugin
|
||||
resource 0.38.1 enabled dokku core resource plugin
|
||||
scheduler-docker-local 0.38.1 enabled dokku core scheduler-docker-local plugin
|
||||
shell 0.38.1 enabled dokku core shell plugin
|
||||
ssh-keys 0.38.1 enabled dokku core ssh-keys plugin
|
||||
storage 0.38.1 enabled dokku core storage plugin
|
||||
tags 0.38.1 enabled dokku core tags plugin
|
||||
tar 0.38.1 enabled dokku core tar plugin
|
||||
trace 0.38.1 enabled dokku core trace plugin
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
|
||||
@@ -32,7 +32,7 @@ Valid resource options include:
|
||||
|
||||
See the [Supported Resource Management Properties](/docs/deployment/schedulers/docker-local.md#supported-resource-management-properties) section of the docker local scheduler documentation for more information on how each resource limit maps to Docker.
|
||||
|
||||
Resource limits and reservations are applied only during the `run` and `deploy` phases of an application, and will not impact the `build` phase of an application.
|
||||
Resource reservations are applied only during the `run` and `deploy` phases of an application. Resource limits also apply during the `build` phase when explicitly configured against the `build` process type - see [Build-time Resource Limits](#build-time-resource-limits) below.
|
||||
|
||||
### Resource Limits
|
||||
|
||||
@@ -120,6 +120,40 @@ dokku resource:limit --process-type web node-js-app
|
||||
nvidia-gpu:
|
||||
```
|
||||
|
||||
#### Build-time Resource Limits
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
Resource limits may be applied to the build container by using the special `build` process type. This allows constraining memory and CPU usage during the `build` phase, which is otherwise unconstrained.
|
||||
|
||||
```shell
|
||||
dokku resource:limit --memory 4g --process-type build node-js-app
|
||||
```
|
||||
|
||||
```
|
||||
=====> Setting resource limits for node-js-app (build)
|
||||
memory: 4g
|
||||
```
|
||||
|
||||
Build-time limits are applied via the `docker-args-process-build` plugin trigger. They do not inherit from default (`_default_`) limits - only limits explicitly set against the `build` process type are applied at build time. This is intentional: build phases often require more memory than the runtime process, and silently inheriting a small runtime limit would cause confusing OOM failures.
|
||||
|
||||
> [!WARNING]
|
||||
> Do not use `build` as a runtime process type in your `Procfile`. The `build` name is reserved by the resource plugin to scope limits to the build container, and using it as a Procfile entry will cause those limits to be applied to that runtime container as well.
|
||||
|
||||
Supported limits per builder:
|
||||
|
||||
| Builder | `--cpu` | `--memory` | `--memory-swap` | `--nvidia-gpu` |
|
||||
|------------|---------|------------|-----------------|----------------|
|
||||
| herokuish | yes | yes | yes | yes |
|
||||
| dockerfile | no | yes | yes | no |
|
||||
| pack | no | no | no | no |
|
||||
| nixpacks | no | no | no | no |
|
||||
| railpack | no | no | no | no |
|
||||
| lambda | no | no | no | no |
|
||||
|
||||
Resource keys outside the supported set for a builder are silently ignored. Reservations (`resource:reserve`) are never applied at build time - only limits.
|
||||
|
||||
#### Clearing Resource Limits
|
||||
|
||||
In cases where the values are incorrect - or there is no desire to limit resources - resource limits may be cleared using the `resource:limit-clear` command.
|
||||
|
||||
62
docs/appendices/0.38.0-migration-guide.md
Normal file
62
docs/appendices/0.38.0-migration-guide.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 0.38.0 Migration Guide
|
||||
|
||||
## Changes
|
||||
|
||||
- Dokku now generates a minimal nginx configuration for apps without running `web` processes (undeployed apps, apps with no `web` process type, or apps with stopped web processes). This configuration returns `502 Bad Gateway` responses, 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 running `web` processes. See the [nginx documentation](/docs/networking/proxies/nginx.md#nginx-configuration-for-undeployed-apps) for more details.
|
||||
- Users with custom `nginx.conf.sigil` templates that reference `DOKKU_APP_WEB_LISTENERS` should 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:
|
||||
|
||||
```
|
||||
location / {
|
||||
{{ if $.DOKKU_APP_WEB_LISTENERS }}
|
||||
proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
|
||||
{{ else }}
|
||||
return 502;
|
||||
{{ end }}
|
||||
}
|
||||
```
|
||||
|
||||
- The path on disk to both the global `ENV` file and app `ENV` files 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 a `duplicate default server for 0.0.0.0:80` error. Operators with local customizations can recover them by inspecting the `.dokku-disabled` siblings. 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.conf` that rejects requests with unknown Host headers using `ssl_reject_handshake on` (HTTPS) and `return 444` (HTTP). This replaces the manual workaround previously documented in the nginx docs. The behavior can be opted out at install time via the `dokku/install_default_site` debconf prompt. See the [Default site documentation](/docs/networking/proxies/nginx.md#default-site).
|
||||
- The `docker-local` scheduler now sends `SIGTERM` to old containers immediately after a successful deploy, rather than waiting `wait-to-retire` seconds before signaling. This matches Heroku's graceful-shutdown contract and lets applications begin draining in-flight work as soon as proxy traffic switches. The `wait-to-retire` grace period and `stop-timeout-seconds` hard-stop continue to apply as before. See the [zero downtime deploys documentation](/docs/deployment/zero-downtime-deploys.md#wait-to-retire) for more details.
|
||||
- The `docker-local` scheduler no longer queues an image for retirement when another running container of the same app still uses it. This fixes the case where a `ps:rebuild` against an image-based deploy (`git:from-image`) produced an identical-SHA image and the `dokku-retire` cron timer would log `Image ... has running containers, skipping rm` on every run. Stuck entries from prior versions are pruned automatically on the next `ps:retire` run.
|
||||
- All `:report` subcommands now accept the `--global` flag, 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 `--global` with `--format json` was rejected with an "info flag" error, and `--global` on its own was treated as an unknown flag.
|
||||
- The `scheduler-k3s` plugin now manages env config and the dokku-generated image pull Secret as their own helm releases with stable names (`config-{app}` and `pull-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's `imagePullSecrets` list no longer accumulates references to nonexistent Secrets across deploys. The next deploy of an app switches the Deployment's `envFrom` and `imagePullSecrets` references 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 old `tls-{app}`, `config-{app}`, and `pull-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`, and `storage:destroy`. The legacy `storage: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 as `legacy-<hash>` entries in `storage: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. The `storage:ensure-directory` command keeps working but now emits a deprecation warning - prefer `storage: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 older `ensure-directory` validator 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.
|
||||
@@ -5,6 +5,25 @@
|
||||
> [!IMPORTANT]
|
||||
> While the `app.json` format used by Dokku is based on the one [supported by Heroku](https://devcenter.heroku.com/articles/app-json-schema), not all Heroku functionality is supported by Dokku.
|
||||
|
||||
## Buildpacks
|
||||
|
||||
```json
|
||||
{
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "heroku/python"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-nodejs.git"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
(list, optional) A list of buildpacks to use when deploying the app. Each entry is an object with a `url` property. Buildpacks specified via the `buildpacks:add` or `buildpacks:set` commands take precedence over those specified in `app.json`. Buildpack URLs may use the shorthand format (e.g., `heroku/python`) which will be expanded to the full GitHub URL.
|
||||
|
||||
- `url`: (string, required) The URL or shorthand reference of the buildpack.
|
||||
|
||||
## Cron
|
||||
|
||||
```json
|
||||
@@ -25,6 +44,103 @@
|
||||
- `schedule`: (string, required)
|
||||
- `concurrency_policy`: (string, optional, default: `allow`, options: `allow`, `forbid`, `replace`)
|
||||
|
||||
## Env
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"SIMPLE_VAR": "default_value",
|
||||
"SECRET_KEY": {
|
||||
"description": "A secret key for signing tokens",
|
||||
"generator": "secret"
|
||||
},
|
||||
"DATABASE_URL": {
|
||||
"description": "PostgreSQL connection string",
|
||||
"required": true
|
||||
},
|
||||
"OPTIONAL_VAR": {
|
||||
"description": "An optional configuration value",
|
||||
"value": "default",
|
||||
"required": false
|
||||
},
|
||||
"SYNC_VAR": {
|
||||
"description": "A variable that updates on every deploy",
|
||||
"value": "synced_value",
|
||||
"sync": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
(object, optional) A key-value object for environment variable configuration. Keys are the variable names. Values can be either a string (used as the default value) or an object with the following properties:
|
||||
|
||||
- `description`: (string, optional) Human-readable explanation of the variable's purpose
|
||||
- `value`: (string, optional) Default value for the variable
|
||||
- `required`: (boolean, optional, default: `true`) Whether the variable must have a value
|
||||
- `generator`: (string, optional) Function to generate the value. Currently only `"secret"` is supported, which generates a 64-character cryptographically secure hex string
|
||||
- `sync`: (boolean, optional, default: `false`) If `true`, the value will be set on every deploy, overwriting any existing value
|
||||
|
||||
### Behavior
|
||||
|
||||
Environment variables from `app.json` are processed during the first deploy, before the predeploy script runs. The behavior depends on the variable configuration:
|
||||
|
||||
1. **Variables with `value` or simple string**: The default value is set if the variable doesn't already exist
|
||||
2. **Variables with `generator: "secret"`**: A random 64-character hex string is generated if the variable doesn't exist
|
||||
3. **Required variables without a value or generator**: If a TTY is available, the user is prompted for a value. Otherwise, the deploy fails with an error
|
||||
4. **Optional variables without a value**: Skipped silently if no TTY is available
|
||||
|
||||
On subsequent deploys:
|
||||
- Variables are NOT re-set unless `sync: true` is specified
|
||||
- Variables with `sync: true` are always set to their configured value, overwriting any manual changes
|
||||
- Variables that already have values are not modified
|
||||
|
||||
### Examples
|
||||
|
||||
**Simple default value:**
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"WEB_CONCURRENCY": "5"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Generated secret (recommended for API keys, tokens, etc.):**
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"SECRET_KEY_BASE": {
|
||||
"description": "Base secret for session encryption",
|
||||
"generator": "secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Required variable that must be provided:**
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"DATABASE_URL": {
|
||||
"description": "PostgreSQL connection URL",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variable that stays in sync with app.json:**
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"FEATURE_FLAGS": {
|
||||
"value": "new_ui,dark_mode",
|
||||
"sync": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Formation
|
||||
|
||||
```json
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
# nginx.conf.sigil
|
||||
|
||||
The `nginx.conf.sigil` file is used to configure the nginx server for an application. The default template can be found [here](https://github.com/dokku/dokku/blob/master/plugins/nginx-vhosts/templates/nginx.conf.sigil). Dokku uses a tool named [sigil](https://github.com/gliderlabs/sigil) to generate the nginx configuration based on the template provided.
|
||||
|
||||
## Validation
|
||||
|
||||
A custom `nginx.conf.sigil` is pre-validated at the start of every deploy, immediately after it is extracted from the source tree and before the build phase runs. Pre-validation renders the template via sigil with the same parameters used at deploy time, wraps the rendered config in a minimal `events`/`http` scaffold, and runs `nginx -t` against the result. The deploy is aborted if either the sigil render or the `nginx -t` check fails, so build work is not wasted on a syntactically invalid template. When no app listeners exist yet (typical for first deploys), pre-validation injects a placeholder `127.0.0.1:5000` listener for `DOKKU_APP_WEB_LISTENERS` so that the rendered upstream block has a static server entry and `nginx -t` does not bail out on "host not found in upstream".
|
||||
|
||||
Pre-validation is skipped when the proxy type is not `nginx` or when `disable-custom-config` is set to `true` for the app.
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-310x150.png"/>
|
||||
<square70x70logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-310x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
|
||||
@@ -2,37 +2,37 @@
|
||||
"name": "Dokku",
|
||||
"icons": [
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.8\/docs\/assets\/favicons\/android-chrome-192x192.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.1\/docs\/assets\/favicons\/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
/* Avatar section darkmode fade */
|
||||
--avatar-before-gradient: rgba(0, 0, 0, 0) linear-gradient(90deg, white 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
--avatar-darkmode-before-gradient: rgba(0, 0, 0, 0) linear-gradient(90deg, #0.37.8 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
--avatar-darkmode-before-gradient: rgba(0, 0, 0, 0) linear-gradient(90deg, #0.38.1 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
--avatar-after-gradient: rgba(0, 0, 0, 0) linear-gradient(270deg, white 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
--avatar-darkmode-after-gradient: rgba(0, 0, 0, 0) linear-gradient(270deg, #0.37.8 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
--avatar-darkmode-after-gradient: rgba(0, 0, 0, 0) linear-gradient(270deg, #0.38.1 2.52%, rgba(255, 255, 255, 0) 100%) repeat scroll 0% 0%;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -1191,15 +1191,15 @@ ul.fas li .fa-large:before {
|
||||
|
||||
.getting-started::after {
|
||||
background: linear-gradient(0deg, rgba(52, 52, 87, 0.2) -40.97%, rgba(0, 0, 0, 0) 103.19%),
|
||||
#0.37.8;
|
||||
#0.38.1;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
background: #0.37.8;
|
||||
background: #0.38.1;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
background: #0.37.8;
|
||||
background: #0.38.1;
|
||||
}
|
||||
|
||||
.powered-by_brands {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"0.34.9",
|
||||
"0.35.20",
|
||||
"0.36.11",
|
||||
"0.37.8"
|
||||
"0.37.10",
|
||||
"0.38.1"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ Vhosts can also be disabled for all apps:
|
||||
dokku domains:disable --all
|
||||
```
|
||||
|
||||
On subsequent deploys, the nginx virtualhost will be discarded. This is useful when deploying internal-facing services that should not be publicly routeable. As of 0.4.0, nginx will still be configured to proxy your app on some random high port. This allows internal services to maintain the same port between deployments. You may change this port by setting `DOKKU_PROXY_PORT` and/or `DOKKU_PROXY_SSL_PORT` (for services configured to use SSL.)
|
||||
On subsequent deploys, the nginx virtualhost will be discarded. This is useful when deploying internal-facing services that should not be publicly routeable. As of 0.4.0, nginx will still be configured to proxy your app on some random high port. This allows internal services to maintain the same port between deployments. The non-SSL and SSL ports used can be customized via `dokku proxy:set <app> proxy-port <value>` and `dokku proxy:set <app> proxy-ssl-port <value>` - see the [proxy management documentation](/docs/networking/proxy-management.md#setting-proxy-ports) for details.
|
||||
|
||||
To re-enable, run the `domains:enable` subcommand:
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@ Environment variables are available both at run time and during the application
|
||||
For buildpack deploys, Dokku will create a `/app/.env` file that can be used for legacy buildpacks. Note that this is _not_ updated when `config:set` or `config:unset` is called, and is only written during a `deploy` or `ps:rebuild`. Developers are encouraged to instead read from the application environment directly, as the proper values will be available then.
|
||||
|
||||
> [!NOTE]
|
||||
> Global `ENV` files are sourced before app-specific `ENV` files. This means that app-specific variables will take precedence over global variables. Configuring your global `ENV` file is manual, and should be considered potentially dangerous as configuration applies to all applications.
|
||||
> Global environment variables are sourced before app-specific environment variables. This means that app-specific variables will take precedence over global variables. Configuring global environment variables should be considered potentially dangerous as configuration applies to all applications.
|
||||
|
||||
You can set multiple environment variables at once:
|
||||
|
||||
```shell
|
||||
dokku config:set node-js-app ENV=prod COMPILE_ASSETS=1
|
||||
dokku config:set node-js-app APP_ENV=prod COMPILE_ASSETS=1
|
||||
```
|
||||
|
||||
Whitespace and special characters get tricky. If you are using dokku locally you don't need to do any special escaping. If you are using dokku over ssh you will need to backslash-escape spaces:
|
||||
@@ -45,7 +45,7 @@ dokku config:set --encoded node-js-app KEY="$(base64 -w 0 ~/.ssh/id_rsa)"
|
||||
When setting or unsetting environment variables, you may wish to avoid an application restart. This is useful when developing plugins or when setting multiple environment variables in a scripted manner. To do so, use the `--no-restart` flag:
|
||||
|
||||
```shell
|
||||
dokku config:set --no-restart node-js-app ENV=prod
|
||||
dokku config:set --no-restart node-js-app APP_ENV=prod
|
||||
```
|
||||
|
||||
If you wish to have the variables output in an `eval`-compatible form, you can use the `config:export` command
|
||||
@@ -54,7 +54,7 @@ If you wish to have the variables output in an `eval`-compatible form, you can u
|
||||
dokku config:export node-js-app
|
||||
# outputs variables in the form:
|
||||
#
|
||||
# export ENV='prod'
|
||||
# export APP_ENV='prod'
|
||||
# export COMPILE_ASSETS='1'
|
||||
|
||||
# source in all the node-js-app app environment variables
|
||||
@@ -68,9 +68,38 @@ dokku config:export --format shell node-js-app
|
||||
|
||||
# outputs variables in the form:
|
||||
#
|
||||
# ENV='prod' COMPILE_ASSETS='1'
|
||||
# APP_ENV='prod' COMPILE_ASSETS='1'
|
||||
```
|
||||
|
||||
## Setting Environment Variables via app.json
|
||||
|
||||
Environment variables can also be declared in an `app.json` file in your repository root. This is useful for setting default values, generating secrets, or requiring certain variables to be set before deployment.
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"SIMPLE_VAR": "default_value",
|
||||
"SECRET_KEY": {
|
||||
"description": "A secret key for signing tokens",
|
||||
"generator": "secret"
|
||||
},
|
||||
"DATABASE_URL": {
|
||||
"description": "PostgreSQL connection string",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Environment variables from `app.json` are processed during the first deploy, before the predeploy script runs. Variables can be configured as:
|
||||
|
||||
- **Simple string values**: Set as defaults if not already configured
|
||||
- **Generated secrets**: Use `"generator": "secret"` to auto-generate a 64-character hex string
|
||||
- **Required variables**: Use `"required": true` to prompt for or require a value
|
||||
- **Synced variables**: Use `"sync": true` to update the value on every deploy
|
||||
|
||||
For full details on the `env` schema and behavior, see the [app.json documentation](/docs/appendices/file-formats/app-json.md#env).
|
||||
|
||||
## Special Config Variables
|
||||
|
||||
The following config variables have special meanings and can be set in a variety of ways. Unless specified via global app config, the values may not be passed into applications. Usage of these values within applications should be considered unsafe, as they are an internal configuration values that may be moved to the internal properties system in the future.
|
||||
@@ -98,26 +127,5 @@ The following config variables have special meanings and can be set in a variety
|
||||
| `DOKKU_QUIET_OUTPUT` | none | `--quiet` flag | Silences certain header output for `dokku` commands. |
|
||||
| `DOKKU_RM_CONTAINER` | none | `dokku config:set` <br /> | Deprecated: Whether to keep `dokku run` containers around or not. |
|
||||
| `DOKKU_TRACE` | none | `dokku trace:on` <br /> `dokku trace:off` <br /> `--trace` flag | Turn on very verbose debugging. |
|
||||
| `DOKKU_APP_PROXY_TYPE` | `nginx` | `dokku proxy:set` | |
|
||||
| `DOKKU_APP_RESTORE` | `1` | `dokku config:set` <br /> `dokku ps:stop` | |
|
||||
| `DOKKU_APP_SHELL` | `/bin/bash` | `dokku config:set` | Allows users to change the default shell used by Dokku for `dokku enter` and execution of deployment tasks. |
|
||||
| `DOKKU_CHECKS_DISABLED` | none | `dokku checks:disable` | |
|
||||
| `DOKKU_CHECKS_ENABLED` | none | `dokku checks:enable` | |
|
||||
| `DOKKU_CHECKS_SKIPPED` | none | `dokku checks:skip` | |
|
||||
| `DOKKU_CHECKS_WAIT` | `5` | `dokku config:set` | Wait this many seconds for the container to start before running checks.
|
||||
| `DOKKU_CHECKS_TIMEOUT` | `30` | `dokku config:set` | Wait this many seconds for each response before marking it as a failure.
|
||||
| `DOKKU_CHECKS_ATTEMPTS` | `5` | `dokku config:set` | Number of retries for to run for a specific check before marking it as a failure
|
||||
| `DOKKU_DEFAULT_CHECKS_WAIT` | `10` | `dokku config:set` | If no user-defined checks are specified - or if the process being checked is not a `web` process - this is the period of time Dokku will wait before checking that a container is still running. |
|
||||
| `DOKKU_DISABLE_PROXY` | none | `dokku proxy:disable` <br /> `dokku proxy:enable` | Disables the proxy in front of your application, resulting in publicly routing the docker container. |
|
||||
| `DOKKU_DISABLE_APP_AUTOCREATION` | none | `dokku config:set` | Disables automatic creation of a non-existent app on deploy. |
|
||||
| `DOKKU_DOCKERFILE_START_CMD` | none | `dokku config:set` | |
|
||||
| `DOKKU_PARALLEL_ARGUMENTS`. | none | `dokku config:set` | Allows passing custom arguments to parallel for `ps:*all` commands |
|
||||
| `DOKKU_PROXY_PORT` | automatically assigned | `/etc/environment` <br /> `~dokku/.dokkurc` <br /> `~dokku/.dokkurc/*` <br /> `dokku config:set` | |
|
||||
| `DOKKU_PROXY_SSL_PORT` | automatically assigned | `/etc/environment` <br /> `~dokku/.dokkurc` <br /> `~dokku/.dokkurc/*` <br /> `dokku config:set` | |
|
||||
| `DOKKU_SKIP_ALL_CHECKS` | none | `dokku config:set` | |
|
||||
| `DOKKU_SKIP_CLEANUP` | | `/etc/environment` <br /> `~dokku/.dokkurc` <br /> `~dokku/.dokkurc/*` | When a deploy is triggered, if this is set to a non-empty value, then old docker containers and images will not be removed. |
|
||||
| `DOKKU_SKIP_DEFAULT_CHECKS` | | `dokku config:set` | |
|
||||
| `DOKKU_SKIP_DEPLOY` | | `dokku config:set` | |
|
||||
| `DOKKU_START_CMD` | none | `dokku config:set` | Command to run instead of `/start $PROC_TYPE` |
|
||||
| `DOKKU_SYSTEM_GROUP` | `dokku` | `/etc/environment` <br /> `~dokku/.dokkurc` <br /> `~dokku/.dokkurc/*` | System group to chown files as. |
|
||||
| `DOKKU_SYSTEM_USER` | `dokku` | `/etc/environment` <br /> `~dokku/.dokkurc` <br /> `~dokku/.dokkurc/*` | System user to chown files as. |
|
||||
|
||||
@@ -143,11 +143,11 @@ dokku letsencrypt:cron-job --add
|
||||
|
||||
### Skipping deployment
|
||||
|
||||
If you only want to rebuild and tag a container, you can skip the deployment phase by setting `$DOKKU_SKIP_DEPLOY` to `true` by running:
|
||||
If you only want to rebuild and tag a container, you can skip the deployment phase by setting the `skip-deploy` property to `true`:
|
||||
|
||||
``` shell
|
||||
# on the Dokku host
|
||||
dokku config:set ruby-getting-started DOKKU_SKIP_DEPLOY=true
|
||||
dokku ps:set ruby-getting-started skip-deploy true
|
||||
```
|
||||
|
||||
### Redeploying or restarting
|
||||
|
||||
@@ -13,6 +13,7 @@ apps:lock <app> # Locks an app for deployment
|
||||
apps:locked <app> # Checks if an app is locked for deployment
|
||||
apps:rename <old-app> <new-app> # Rename an app
|
||||
apps:report [<app>] [<flag>] # Display report about an app
|
||||
apps:set [--global] <app> <key> (<value>) # Set or clear an apps property for an app
|
||||
apps:unlock <app> # Unlocks an app for deployment
|
||||
```
|
||||
|
||||
@@ -78,6 +79,20 @@ Once created, you can configure the application as normal, and deploy the applic
|
||||
- Create and link datastores.
|
||||
- Set environment variables.
|
||||
|
||||
### Disabling automatic app creation
|
||||
|
||||
By default, pushing to a git remote for an app that does not yet exist on the Dokku host will cause the app to be created automatically. On shared or production hosts this may be undesirable - operators may prefer that an explicit `apps:create` is required first. The `disable-autocreation` global property controls this behavior:
|
||||
|
||||
```shell
|
||||
dokku apps:set --global disable-autocreation true
|
||||
```
|
||||
|
||||
While set, pushes targeting an app that does not exist will be rejected. The default behavior may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku apps:set --global disable-autocreation
|
||||
```
|
||||
|
||||
### Removing a deployed app
|
||||
|
||||
In some cases, you may need to destroy an application, whether it is because the application is temporary or because it was misconfigured. In these cases, you can use the `apps:destroy` command. Performing any destructive actions in Dokku requires confirmation, and this command will ask for the name of the application being deleted before doing so.
|
||||
|
||||
@@ -82,6 +82,28 @@ The default value may be set by passing an empty value for the option.
|
||||
dokku builder:set --global build-dir
|
||||
```
|
||||
|
||||
#### Skipping container and image cleanup
|
||||
|
||||
After a successful deploy, Dokku removes old containers and images that are no longer referenced by the app. On hosts where image rebuilds are expensive or where operators want to retain prior images for manual rollback, this cleanup can be disabled per-app or globally via the `skip-cleanup` property:
|
||||
|
||||
```shell
|
||||
dokku builder:set node-js-app skip-cleanup true
|
||||
```
|
||||
|
||||
The property can also be set globally:
|
||||
|
||||
```shell
|
||||
dokku builder:set --global skip-cleanup true
|
||||
```
|
||||
|
||||
The default behavior (cleanup enabled) may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku builder:set node-js-app skip-cleanup
|
||||
```
|
||||
|
||||
For backwards compatibility with bootstrap-time configuration, the `DOKKU_SKIP_CLEANUP` environment variable in `/etc/environment` or `~dokku/.dokkurc/*` is still honored when the `skip-cleanup` property is unset. The property is the canonical interface and takes precedence when set.
|
||||
|
||||
### Displaying builder reports for an app
|
||||
|
||||
You can get a report about the app's builder status using the `builder:report` command:
|
||||
|
||||
@@ -130,6 +130,24 @@ This will use the latest commit on the `master` branch of the specified buildpac
|
||||
dokku buildpacks:set node-js-app https://github.com/heroku/heroku-buildpack-nodejs#v87
|
||||
```
|
||||
|
||||
### Specifying buildpacks via app.json
|
||||
|
||||
Buildpacks can also be specified in the `app.json` file at the root of your repository:
|
||||
|
||||
```json
|
||||
{
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "heroku/python"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Buildpacks configured via `buildpacks:add` or `buildpacks:set` commands take precedence over those specified in `app.json`. If no buildpacks are configured via commands and `app.json` contains a `buildpacks` entry, those buildpacks will be used.
|
||||
|
||||
Shorthand buildpack references (e.g., `heroku/python`) are expanded to full GitHub URLs automatically.
|
||||
|
||||
### Displaying buildpack reports for an app
|
||||
|
||||
You can get a report about the app's buildpacks status using the `buildpacks:report` command:
|
||||
|
||||
@@ -185,7 +185,7 @@ You would adjust the cache directory for whatever application cache you have, e.
|
||||
|
||||
### Customizing the run command
|
||||
|
||||
By default no arguments are passed to `docker run` when deploying the container and the `CMD` or `ENTRYPOINT` defined in the `Dockerfile` are executed. You can take advantage of docker ability of overriding the `CMD` or passing parameters to your `ENTRYPOINT` setting `$DOKKU_DOCKERFILE_START_CMD`. Let's say for example you are deploying a base Node.js image, with the following `ENTRYPOINT`:
|
||||
By default no arguments are passed to `docker run` when deploying the container and the `CMD` or `ENTRYPOINT` defined in the `Dockerfile` are executed. You can take advantage of docker's ability to override the `CMD` or pass parameters to your `ENTRYPOINT` by setting the `dockerfile-start-cmd` property on the `ps` plugin. Let's say for example you are deploying a base Node.js image, with the following `ENTRYPOINT`:
|
||||
|
||||
```Dockerfile
|
||||
ENTRYPOINT ["node"]
|
||||
@@ -194,10 +194,14 @@ ENTRYPOINT ["node"]
|
||||
You can do:
|
||||
|
||||
```shell
|
||||
dokku config:set node-js-app DOKKU_DOCKERFILE_START_CMD="--harmony server.js"
|
||||
dokku ps:set node-js-app dockerfile-start-cmd "--harmony server.js"
|
||||
```
|
||||
|
||||
To tell Docker what to run.
|
||||
To tell Docker what to run. Pass an empty value to clear the override:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app dockerfile-start-cmd
|
||||
```
|
||||
|
||||
### Procfiles and multiple processes
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
```
|
||||
git:allow-host <host> # Adds a host to known_hosts
|
||||
git:auth <host> [<username> <password>] # Configures netrc authentication for a given git server
|
||||
git:auth-status <host> [<username> <password>] # Reports whether the netrc entry matches the requested state
|
||||
git:from-archive [--archive-type ARCHIVE_TYPE] <app> <archive-url> [<git-username> <git-email>] # Updates an app's git repository with a given archive file
|
||||
git:from-image [--build-dir DIRECTORY] <app> <docker-image> [<git-username> <git-email>] # Updates an app's git repository with a given docker image
|
||||
git:generate-deploy-key # Generates a deploy ssh key
|
||||
@@ -13,7 +14,7 @@ git:load-image [--build-dir DIRECTORY] <app> <docker-image> [<git-username> <git
|
||||
git:sync [--build|--build-if-changes] [--skip-deploy-branch] <app> <repository> [<git-ref>] # Clone or fetch an app from remote git repo
|
||||
git:initialize <app> # Initialize a git repository for an app
|
||||
git:public-key # Outputs the dokku public deploy key
|
||||
git:report [<app>] [<flag>] # Displays a git report for one or more apps
|
||||
git:report [<app>] [<flag>|--format json] # Displays a git report for one or more apps
|
||||
git:set <app> <key> (<value>) # Set or clear a git property for an app
|
||||
git:status <app> # Show the working tree status for an app
|
||||
```
|
||||
@@ -191,6 +192,34 @@ dokku git:auth github.com
|
||||
|
||||
For syncing to a private repository stored on a remote Git product such as GitHub or GitLab, Dokku's recommendation is to use a personal access token on a bot user where possible. Please see your service's documentation for information regarding the recommended best practices.
|
||||
|
||||
The password for `git:auth` may also be provided over `STDIN` to avoid placing it on the command line:
|
||||
|
||||
```shell
|
||||
# pipe the password into git:auth
|
||||
echo "personal-access-token" | dokku git:auth github.com username
|
||||
```
|
||||
|
||||
#### Checking the configured auth state
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
The `git:auth-status` command reports whether the configured `netrc` entry matches a desired state without exposing the underlying file. It exits `0` when the configured state matches and `1` otherwise. This allows external tooling such as configuration management systems to perform idempotent updates without reading `$DOKKU_ROOT/.netrc` directly.
|
||||
|
||||
```shell
|
||||
# check whether github.com is configured with the expected credentials
|
||||
dokku git:auth-status github.com username personal-access-token
|
||||
|
||||
# check whether no credentials are configured for github.com
|
||||
dokku git:auth-status github.com
|
||||
```
|
||||
|
||||
As with `git:auth`, the password may be provided via `STDIN`:
|
||||
|
||||
```shell
|
||||
echo "personal-access-token" | dokku git:auth-status github.com username
|
||||
```
|
||||
|
||||
### Allowing remote repository hosts
|
||||
|
||||
By default, the Dokku host may not have access to a server containing the remote repository. This can be initialized via the `git:allow-host` command.
|
||||
@@ -241,3 +270,42 @@ dokku git:public-key
|
||||
```
|
||||
|
||||
If there is no key, an error message is shown that displays the command that can be run on the Dokku server to generate a new public/private ssh key pair.
|
||||
|
||||
### Displaying git reports for an app
|
||||
|
||||
You can get a report about the app's git configuration using the `git:report` command:
|
||||
|
||||
```shell
|
||||
dokku git:report
|
||||
```
|
||||
|
||||
```
|
||||
=====> node-js-app git information
|
||||
Git deploy branch: master
|
||||
Git global deploy branch: master
|
||||
Git keep git dir: false
|
||||
Git rev env var: GIT_REV
|
||||
Git sha: a1b2c3d
|
||||
Git source image:
|
||||
Git last updated at: 1700000000
|
||||
```
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
dokku git:report node-js-app
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku git:report node-js-app --git-deploy-branch
|
||||
```
|
||||
|
||||
The `git:report` command also takes a `--format` flag, with the valid options including `stdout` (default) and `json`. The `json` output format can be used for automation purposes:
|
||||
|
||||
```shell
|
||||
dokku git:report node-js-app --format json
|
||||
```
|
||||
|
||||
The `--format` flag cannot be combined with an info flag.
|
||||
|
||||
@@ -444,7 +444,7 @@ To enable autoscaling, use the `app.json` `formation.$PROCESS_TYPE.autoscaling`
|
||||
- `cooldown_seconds`: (default: 300) The number of seconds to wait in between each scaling event
|
||||
- `triggers`: A list of autoscaling triggers.
|
||||
|
||||
Autoscaling triggers are passed as is to Keda, and should match the configuration keda uses for a given [scaler](https://keda.sh/docs/2.13/scalers/). Below is an example for [datadog](https://keda.sh/docs/2.13/scalers/datadog/#example-2---driving-scale-directly):
|
||||
Autoscaling triggers are passed as is to Keda, and should match the configuration keda uses for a given [scaler](https://keda.sh/docs/2.19/scalers/). Below is an example for [datadog](https://keda.sh/docs/2.19/scalers/datadog/#example-2---driving-scale-directly):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -476,6 +476,8 @@ Each value in the `metadata` stanza can use the following interpolated strings:
|
||||
- `DOKKU_PROCESS_TYPE`: The name of the process being scaled
|
||||
- `DOKKU_APP_NAME`: The name of the app being scaled
|
||||
|
||||
Dokku configures a Keda `fallback` (with a failure threshold of `3` and the configured replica count) on the generated `ScaledObject` so that scaling falls back to the configured replica count when a scaler's metric source becomes unavailable. Keda only allows `fallback` when at least one trigger is something other than `cpu` or `memory`, so Dokku omits the `fallback` block when every configured trigger is a `cpu` or `memory` scaler.
|
||||
|
||||
##### HTTP Autoscaling
|
||||
|
||||
In addition to the built-in scalers that Keda provides, Dokku also supports Keda's HTTP Add On. This requires that the addon be properly installed and configured. For existing k3s clusters, this can be performed by the `scheduler-k3s:ensure-charts` command:
|
||||
@@ -683,6 +685,35 @@ Alternatively, a comma separated list of chart names can be specified to only fo
|
||||
dokku scheduler-k3s:ensure-charts --charts cert-manager
|
||||
```
|
||||
|
||||
### Persistent storage
|
||||
|
||||
K3s apps mount persistent volumes through the Dokku storage plugin. A `storage:create --scheduler k3s` call provisions a PersistentVolumeClaim through a small per-entry helm release; `storage:mount <app> <name> --container-dir <path>` then attaches it to an app. Because storage entries are global, the same PVC can be mounted into multiple apps (for `ReadWriteMany` workloads) or into the same app at multiple subpaths.
|
||||
|
||||
```shell
|
||||
# dynamically-provisioned PVC backed by Longhorn
|
||||
dokku storage:create demo-data \
|
||||
--scheduler k3s \
|
||||
--size 2Gi \
|
||||
--access-mode ReadWriteOnce \
|
||||
--storage-class-name longhorn
|
||||
|
||||
dokku storage:mount demo demo-data --container-dir /data
|
||||
dokku storage:wait demo-data
|
||||
git push dokku master
|
||||
```
|
||||
|
||||
For a hostPath-backed PV (no StorageClass), pass `<path>` as the second positional argument and omit `--storage-class-name`. The plugin renders both the PV and the PVC into the entry's helm release. The `--reclaim-policy` flag (`Retain` or `Delete`) controls whether the underlying PV survives `storage:destroy`. Annotations and labels on `storage:create` / `storage:set` propagate to both the PVC and the PV so backup tools (Velero, Longhorn snapshots) can find them.
|
||||
|
||||
The legacy `storage:mount <app> <host>:<container>` colon form is rejected on k3s apps; create a named entry instead. See [Persistent Storage](/docs/advanced-usage/persistent-storage.md) for the full command reference.
|
||||
|
||||
### Chart upgrade callbacks
|
||||
|
||||
Some chart version transitions require side-effects that a plain `helm upgrade` cannot perform. For example, the upgrade of `keda-add-ons-http` to `0.12.2` introduces breaking changes to deployment selectors, which are immutable in Kubernetes; the chart-managed deployments must be deleted before the upgrade can proceed.
|
||||
|
||||
Dokku handles these cases internally by registering version-targeted pre-upgrade and post-upgrade callbacks against affected charts. When `scheduler-k3s:ensure-charts` runs, the installed chart version is compared against the registered callbacks: any whose target version is greater than the currently installed version and at most the configured chart version are executed in ascending semver order, each bracketed around an upgrade to that intermediate version. A final upgrade to the configured chart version then completes the run.
|
||||
|
||||
These callbacks are not user-configurable. Failures during a callback or its surrounding upgrade abort the run, and a subsequent `scheduler-k3s:ensure-charts` resumes from the current state.
|
||||
|
||||
## Scheduler Interface
|
||||
|
||||
The following sections describe implemented and unimplemented scheduler functionality for the `k3s` scheduler.
|
||||
@@ -742,6 +773,7 @@ Next, run the `scheduler-k3s:ensure-charts` command with the `vector` chart to f
|
||||
```shell
|
||||
dokku scheduler-k3s:ensure-charts --charts vector
|
||||
```
|
||||
|
||||
Please see the [vector logs documentation](/docs/deployment/logs.md#configuring-a-log-sink) for more information on specifying vector sinks.
|
||||
|
||||
### Supported Resource Management Properties
|
||||
|
||||
@@ -45,6 +45,26 @@ The default value may be set by passing an empty value for the option.
|
||||
dokku scheduler:set --global selected
|
||||
```
|
||||
|
||||
### Setting the app shell
|
||||
|
||||
The shell used for `dokku run` and `dokku enter` invocations against an app can be customized via the `shell` property. This is useful for images that ship with a non-default shell - for example, alpine-based images that only have `/bin/sh`.
|
||||
|
||||
```shell
|
||||
dokku scheduler:set node-js-app shell sh
|
||||
```
|
||||
|
||||
The `shell` property can also be set globally:
|
||||
|
||||
```shell
|
||||
dokku scheduler:set --global shell sh
|
||||
```
|
||||
|
||||
The default value (an empty string, which lets the scheduler pick its own default) may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku scheduler:set node-js-app shell
|
||||
```
|
||||
|
||||
### Displaying scheduler reports for an app
|
||||
|
||||
You can get a report about the app's scheduler status using the `scheduler:report` command:
|
||||
|
||||
@@ -28,7 +28,9 @@ You may both create user-defined checks for web processes using the `healthcheck
|
||||
|
||||
### wait-to-retire
|
||||
|
||||
After a successful deploy, the grace period given to old containers before they are stopped/terminated is determined by the value of `wait-to-retire`. This is useful for ensuring completion of long-running HTTP connections.
|
||||
After a successful deploy, Dokku immediately sends `SIGTERM` to old containers so the application can begin a graceful shutdown (draining in-flight connections, flushing buffers, and so on) the moment proxy traffic switches to the new containers. The old containers are then left running for the `wait-to-retire` grace period before being stopped, which sends `SIGTERM` again and ultimately `SIGKILL` after `stop-timeout-seconds`. This mirrors Heroku's [dyno shutdown behavior](https://devcenter.heroku.com/articles/dyno-shutdown-behavior).
|
||||
|
||||
The `wait-to-retire` value controls the grace period and is useful for ensuring completion of long-running HTTP connections.
|
||||
|
||||
```shell
|
||||
dokku checks:set node-js-app wait-to-retire 30
|
||||
@@ -40,17 +42,17 @@ Defaults to `60`.
|
||||
|
||||
You can set the `stop-timeout-seconds` property on the `ps` plugin to change this value (default: `30`). See the [process management documentation](/docs/processes/process-management.md#changing-process-management-settings) for more information.
|
||||
|
||||
## Configuring check settings using the `config` plugin
|
||||
## Configuring check settings
|
||||
|
||||
There are certain settings that can be configured via environment variables:
|
||||
There are certain settings that can be configured via the `checks` plugin properties:
|
||||
|
||||
- `DOKKU_DEFAULT_CHECKS_WAIT`: (default: `10`) If no user-defined checks are specified - or if the process being checked is not a `web` process - this is the period of time Dokku will wait before checking that a container is still running.
|
||||
- `default-wait`: (default: `10`) If no user-defined checks are specified - or if the process being checked is not a `web` process - this is the period of time Dokku will wait before checking that a container is still running. Set globally via `dokku checks:set --global default-wait <value>`.
|
||||
|
||||
The following settings may also be specified in the `app.json` file, though are available as environment variables in order to ease application reuse.
|
||||
The following settings may also be specified in the `app.json` file, though are available as properties in order to ease application reuse.
|
||||
|
||||
- `DOKKU_CHECKS_WAIT`: (default: `5`) Wait this many seconds for the container to start before running checks.
|
||||
- `DOKKU_CHECKS_TIMEOUT`: (default: `30`) Wait this many seconds for each response before marking it as a failure.
|
||||
- `DOKKU_CHECKS_ATTEMPTS`: (default: `5`) Number of retries for to run for a specific check before marking it as a failure
|
||||
- `wait`: (default: `5`) Wait this many seconds for the container to start before running checks. Set via `dokku checks:set <app> wait <value>`.
|
||||
- `timeout`: (default: `30`) Wait this many seconds for each response before marking it as a failure. Set via `dokku checks:set <app> timeout <value>`.
|
||||
- `attempts`: (default: `5`) Number of retries for to run for a specific check before marking it as a failure. Set via `dokku checks:set <app> attempts <value>`.
|
||||
|
||||
## Skipping and Disabling Checks
|
||||
|
||||
@@ -65,10 +67,6 @@ dokku checks:skip node-js-app worker,web
|
||||
|
||||
```
|
||||
-----> Skipping zero downtime for app's (node-js-app) proctypes (worker,web)
|
||||
-----> Unsetting node-js-app
|
||||
-----> Unsetting DOKKU_CHECKS_DISABLED
|
||||
-----> Setting config vars
|
||||
DOKKU_CHECKS_SKIPPED: worker,web
|
||||
```
|
||||
|
||||
Zero downtime checks can also be disabled completely. This will stop old containers *before* new ones start, which may result in broken connections and downtime if your application fails to boot properly.
|
||||
@@ -79,10 +77,6 @@ dokku checks:disable node-js-app worker
|
||||
|
||||
```
|
||||
-----> Disabling zero downtime for app's (node-js-app) proctypes (worker)
|
||||
-----> Setting config vars
|
||||
DOKKU_CHECKS_DISABLED: worker
|
||||
-----> Setting config vars
|
||||
DOKKU_CHECKS_SKIPPED: web
|
||||
```
|
||||
|
||||
### Displaying checks reports for an app
|
||||
|
||||
@@ -545,6 +545,21 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `config-set`
|
||||
|
||||
- Description: Sets one or more config values for an app without restarting (when --no-restart flag is specified)
|
||||
- Invoked by: app-json plugin
|
||||
- Arguments: `[--no-restart] $APP $KEY1=VALUE1 [$KEY2=VALUE2 ...]`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `core-post-deploy`
|
||||
|
||||
> To avoid issues with community plugins, this plugin trigger should be used _only_ for core plugins. Please avoid using this trigger in your own plugins.
|
||||
@@ -794,7 +809,7 @@ APP="$1"; IMAGE_SOURCE_TYPE="$2"
|
||||
|
||||
### `docker-args-process-deploy`
|
||||
|
||||
- Description: `$PROC_TYPE` may be set to magic `_all_` process type to signify global docker deploy options.
|
||||
- Description: emits docker arguments scoped to a specific Procfile process type. The `docker-options` plugin implements this trigger to surface options registered via `docker-options:add --process <PROC>`. `$PROC_TYPE` may be empty (or set to the magic `_default_` value) to signify default-scope docker deploy options.
|
||||
- Invoked by: `dokku deploy`
|
||||
- Arguments: `$APP $IMAGE_SOURCE_TYPE $IMAGE_TAG [$PROC_TYPE $CONTAINER_INDEX]`
|
||||
- Example:
|
||||
@@ -2889,21 +2904,52 @@ DOKKU_SCHEDULER="$1"; APP="$2"; REMOVE_CONTAINERS="$3";
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `storage-list`
|
||||
### `storage-list` (deprecated)
|
||||
|
||||
- Description: Returns a list of storage mounts
|
||||
- Invoked by: `dokku storage:list` and `dokku deploy`
|
||||
> [!WARNING]
|
||||
> Deprecated as of 0.38.0. The trigger handler still functions for back-compat
|
||||
> with external plugins but emits a deprecation warning on every invocation.
|
||||
> In-process callers should use the `storage-app-mounts` trigger instead, or
|
||||
> the `storage` Go package directly.
|
||||
|
||||
- Description: Returns a list of storage mounts for an app
|
||||
- Invoked by: external plugins (the core `storage:list` subcommand no longer uses it)
|
||||
- Arguments: `$APP $PHASE $FORMAT`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
### `storage-app-mounts`
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
APP="$1"
|
||||
- Description: Returns the (entry, attachment) pairs an app has for the given phase, in JSON. Schedulers consume this to render volume mounts.
|
||||
- Invoked by: scheduler plugins during deploy
|
||||
- Arguments: `$APP $PHASE`
|
||||
- Output: a JSON array of objects shaped `{"entry": Entry, "attachment": Attachment}`
|
||||
|
||||
# TODO
|
||||
```
|
||||
### `storage-create`
|
||||
|
||||
- Description: Provisions or updates the underlying volume for a k3s storage entry. Called when `storage:create` or `storage:set` runs against a k3s entry. Receives the JSON-encoded entry on stdin.
|
||||
- Invoked by: `dokku storage:create`, `dokku storage:set`
|
||||
- Arguments: `$ENTRY_NAME`
|
||||
- Stdin: JSON-encoded `Entry` payload
|
||||
|
||||
### `storage-destroy`
|
||||
|
||||
- Description: Releases the underlying volume for a k3s storage entry. Called when `storage:destroy` runs against a k3s entry. Receives the JSON-encoded entry on stdin.
|
||||
- Invoked by: `dokku storage:destroy`
|
||||
- Arguments: `$ENTRY_NAME`
|
||||
- Stdin: JSON-encoded `Entry` payload
|
||||
|
||||
### `storage-status`
|
||||
|
||||
- Description: Returns the current status of a storage entry's underlying volume. Used by `storage:wait` to poll the cluster. The handler should print one line: `Bound`, `Pending`, or `Lost` for k3s entries.
|
||||
- Invoked by: `dokku storage:wait`
|
||||
- Arguments: `$ENTRY_NAME`
|
||||
- Stdin: JSON-encoded `Entry` payload
|
||||
|
||||
### `scheduler-storage-exec`
|
||||
|
||||
- Description: Runs an interactive or non-interactive command against a storage entry. The storage plugin fires this with `<scheduler>` as the first arg; each scheduler plugin's handler matches against its own scheduler name and either handles or no-ops, mirroring `scheduler-deploy` / `scheduler-app-status`. Plugn forwards stdin/stdout/stderr to the handler subprocess so an interactive shell streams cleanly. The handler exits with the underlying tool's status code so `dokku storage:exec` propagates exit codes verbatim.
|
||||
- Invoked by: `dokku storage:exec`
|
||||
- Arguments: `$SCHEDULER $ENTRY_NAME $IMAGE [-- $cmd...]`
|
||||
- Flags: `--interactive` (stdin is open), `--tty` (stdin is a terminal), `--as-user <uid>` (override `entry.Chown`).
|
||||
|
||||
### `traefik-template-source`
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ The workflow looks like this:
|
||||
```shell
|
||||
# having dokku-arch in ../dokku-arch
|
||||
vagrant up build-arch
|
||||
# wait for "==> build-arch: ==> Finished making: dokku 0.37.8-2 (Mon Feb 22 23:20:37 CET 2016)"
|
||||
# wait for "==> build-arch: ==> Finished making: dokku 0.38.1-2 (Mon Feb 22 23:20:37 CET 2016)"
|
||||
cd ../dokku-arch
|
||||
git add PKGBUILD .SRCINFO
|
||||
git commit -m 'Update to dokku 0.9.9'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Pull the dokku/dokku image:
|
||||
|
||||
```shell
|
||||
docker pull dokku/dokku:0.37.8
|
||||
docker pull dokku/dokku:0.38.1
|
||||
```
|
||||
|
||||
Next, run the image.
|
||||
@@ -19,7 +19,7 @@ docker container run -d \
|
||||
--publish 8443:443 \
|
||||
--volume /var/lib/dokku:/mnt/dokku \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
dokku/dokku:0.37.8
|
||||
dokku/dokku:0.38.1
|
||||
```
|
||||
|
||||
Alternatively, you can use `docker-compose.yml`:
|
||||
@@ -27,7 +27,7 @@ Alternatively, you can use `docker-compose.yml`:
|
||||
```yaml
|
||||
services:
|
||||
dokku:
|
||||
image: dokku/dokku:0.37.8
|
||||
image: dokku/dokku:0.38.1
|
||||
container_name: dokku
|
||||
network_mode: bridge
|
||||
ports:
|
||||
@@ -83,7 +83,7 @@ redis: https://github.com/dokku/dokku-redis.git
|
||||
The alternative is to build a custom docker image via a custom Dockerfile. This Dockerfile can run any `plugin:install` command, though the `install` trigger must be skipped via the `--skip-install-trigger`. The version installed at that time will be the one that persists. Below is an example Dockerfile showing this method.
|
||||
|
||||
```Dockerfile
|
||||
FROM dokku/dokku:0.37.8
|
||||
FROM dokku/dokku:0.38.1
|
||||
RUN dokku plugin:install https://github.com/dokku/dokku-postgres.git --skip-install-trigger
|
||||
RUN dokku plugin:install https://github.com/dokku/dokku-redis.git --skip-install-trigger
|
||||
```
|
||||
|
||||
@@ -31,8 +31,8 @@ To install the latest stable version of Dokku, you can run the following shell c
|
||||
|
||||
```shell
|
||||
# for debian systems, installs Dokku via apt-get
|
||||
wget -NP . https://dokku.com/install/v0.37.8/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.8 bash bootstrap.sh
|
||||
wget -NP . https://dokku.com/install/v0.38.1/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.1 bash bootstrap.sh
|
||||
```
|
||||
|
||||
The installation process takes about 5-10 minutes, depending upon internet connection speed.
|
||||
|
||||
@@ -18,6 +18,7 @@ Docker releases updates periodically to their engine. We recommend reading their
|
||||
|
||||
Before upgrading, check the migration guides to get comfortable with new features and prepare your deployment to be upgraded.
|
||||
|
||||
- [Upgrading to 0.38](/docs/appendices/0.38.0-migration-guide.md)
|
||||
- [Upgrading to 0.37](/docs/appendices/0.37.0-migration-guide.md)
|
||||
- [Upgrading to 0.36](/docs/appendices/0.36.0-migration-guide.md)
|
||||
- [Upgrading to 0.35](/docs/appendices/0.35.0-migration-guide.md)
|
||||
@@ -152,4 +153,3 @@ new buildpacks that were released:
|
||||
```shell
|
||||
dokku ps:rebuild --all
|
||||
```
|
||||
|
||||
|
||||
@@ -10,26 +10,26 @@
|
||||
<meta name="author" content="">
|
||||
<title>Dokku - The smallest PaaS implementation you've ever seen</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Dokku">
|
||||
<meta name="application-name" content="Dokku">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
|
||||
@@ -38,7 +38,7 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/style.css" rel="stylesheet">
|
||||
<!-- <link href="./assets/style.css" rel="stylesheet"> -->
|
||||
</head>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<main class="container px-4 px-lg-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-7">
|
||||
<a class="badge-link" href="https://github.com/dokku/dokku/releases"><span class="badge py-2 d-flex fit-content"><div class="circle align-self-center me-2"></div>Latest release <span id="releaseVersion" class="ms-1">v0.37.8</span></span></a>
|
||||
<a class="badge-link" href="https://github.com/dokku/dokku/releases"><span class="badge py-2 d-flex fit-content"><div class="circle align-self-center me-2"></div>Latest release <span id="releaseVersion" class="ms-1">v0.38.1</span></span></a>
|
||||
<h1 class="text-white hero-heading mt-5">An open source PAAS alternative to Heroku.</h1>
|
||||
<h4 class="text-white mt-5">Dokku helps you build and manage the lifecycle of applications from building to scaling.</h4>
|
||||
<div class="d-flex mt-5">
|
||||
@@ -125,7 +125,7 @@
|
||||
</p>
|
||||
<p class="line">
|
||||
<span class="prompt">$</span>
|
||||
<span class="command">sudo DOKKU_TAG=v0.37.8 bash bootstrap.sh</span>
|
||||
<span class="command">sudo DOKKU_TAG=v0.38.1 bash bootstrap.sh</span>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ To change the proxy implementation in use for an application, use the `proxy:set
|
||||
```shell
|
||||
# no validation will be performed against
|
||||
# the specified proxy implementation
|
||||
dokku proxy:set node-js-app nginx
|
||||
dokku proxy:set node-js-app type nginx
|
||||
```
|
||||
|
||||
### Listing port mappings
|
||||
|
||||
@@ -39,7 +39,7 @@ The Caddy plugin has specific rules for routing requests:
|
||||
To use the Caddy plugin, use the `proxy:set` command for the app in question:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app caddy
|
||||
dokku proxy:set node-js-app type caddy
|
||||
```
|
||||
|
||||
This will enable the docker label-based Caddy integration. All future deploys will inject the correct labels for Caddy to read and route requests to containers. Due to the docker label-based integration used by Caddy, a single deploy or rebuild will be required before requests will route successfully.
|
||||
|
||||
@@ -35,7 +35,7 @@ The Haproxy plugin has specific rules for routing requests:
|
||||
To use the Haproxy plugin, use the `proxy:set` command for the app in question:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app haproxy
|
||||
dokku proxy:set node-js-app type haproxy
|
||||
```
|
||||
|
||||
This will enable the docker label-based Haproxy integration. All future deploys will inject the correct labels for Haproxy to read and route requests to containers. Due to the docker label-based integration used by Haproxy, a single deploy or rebuild will be required before requests will route successfully.
|
||||
@@ -113,6 +113,16 @@ dokku haproxy:set --global log-level DEBUG
|
||||
|
||||
After modifying, the Haproxy container will need to be restarted.
|
||||
|
||||
### Changing the Haproxy refresh interval
|
||||
|
||||
Haproxy polls the Docker API for label changes every `10` seconds by default. The interval may be changed by setting the `refresh-conf` property with the `--global` flag:
|
||||
|
||||
```shell
|
||||
dokku haproxy:set --global refresh-conf 5
|
||||
```
|
||||
|
||||
The `refresh-conf` property is global-only and cannot be set on a per-app basis. Setting an empty value will reset it to the default. After modifying, the Haproxy container will need to be restarted.
|
||||
|
||||
### Label Management
|
||||
|
||||
The Haproxy plugin allows you to add custom container labels to apps. These labels are injected into containers during deployment and can be used to configure Haproxy behavior beyond what the plugin provides by default.
|
||||
|
||||
@@ -5,7 +5,8 @@ Dokku uses nginx as its server for routing requests to specific applications. By
|
||||
```
|
||||
nginx:access-logs <app> [-t] # Show the nginx access logs for an application (-t follows)
|
||||
nginx:error-logs <app> [-t] # Show the nginx error logs for an application (-t follows)
|
||||
nginx:report [<app>] [<flag>] # Displays a nginx report for one or more apps
|
||||
nginx:reload # Reloads the nginx server config
|
||||
nginx:report [<app>] [<flag>|--format json] # Displays a nginx report for one or more apps
|
||||
nginx:set <app> <property> (<value>) # Set or clear an nginx property for an app
|
||||
nginx:show-config <app> # Display app nginx config
|
||||
nginx:start # Starts the nginx server
|
||||
@@ -27,6 +28,21 @@ Nginx will proxy the requests in a [round-robin balancing fashion](http://nginx.
|
||||
> [!NOTE]
|
||||
> Due to how the plugin is implemented, if an app successfully starts up `web` containers but fails to deploy some other containers, nginx may eventually stop routing requests. Users should revert their code in these cases, or manually trigger `dokku proxy:build-config $APP` in order to ensure requests route to the new web containers.
|
||||
|
||||
### Nginx Configuration for Undeployed Apps
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
When an app is created but not yet deployed, has no `web` process type, or has no running web processes, Dokku generates a minimal nginx configuration that returns `502 Bad Gateway` responses. This ensures that:
|
||||
|
||||
- The app's domain resolves and returns a non-200 status code, allowing monitoring tools to detect the issue.
|
||||
- SSL certificate provisioning tools such as letsencrypt can function, as an nginx server is listening on the domain.
|
||||
- The `nginx.conf.d/` include directory is available for plugin customization.
|
||||
|
||||
The 502 error page includes auto-retry JavaScript that will automatically reload the page when the application becomes available.
|
||||
|
||||
Once the app is deployed with running `web` processes, the placeholder configuration is automatically replaced with the full proxy configuration.
|
||||
|
||||
### Starting nginx
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -49,6 +65,19 @@ The nginx server can be stopped via `nginx:stop`.
|
||||
dokku nginx:stop
|
||||
```
|
||||
|
||||
### Reloading nginx
|
||||
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
The nginx server can be reloaded via `nginx:reload`. This validates the current nginx configuration and, if valid, signals nginx to reload without restarting the running process. This is the preferred command after editing files in `/etc/nginx/conf.d/` directly.
|
||||
|
||||
```shell
|
||||
dokku nginx:reload
|
||||
```
|
||||
|
||||
If the configuration is invalid, the command exits non-zero and prints the validation error without reloading.
|
||||
|
||||
### Checking access logs
|
||||
|
||||
> [!NOTE]
|
||||
@@ -90,7 +119,9 @@ dokku nginx:show-config node-js-app
|
||||
|
||||
### Validating nginx configs
|
||||
|
||||
It may be desired to validate an nginx config outside of the deployment process. To do so, run the `nginx:validate-config` command. With no arguments, this will validate all app nginx configs, one at a time. A minimal wrapper nginx config is generated for each app's nginx config, upon which `nginx -t` will be run.
|
||||
App-supplied `nginx.conf.sigil` files are pre-validated automatically at the start of every deploy, immediately after the template is extracted from the source tree and before the build phase runs. The template is rendered with sigil and run through `nginx -t` against a minimal wrapper config; if validation fails, the deploy is aborted before any build work begins. To bypass this behavior, set `disable-custom-config` to `true` (see "Disabling custom nginx config" below).
|
||||
|
||||
It may also be desired to validate an nginx config outside of the deployment process. To do so, run the `nginx:validate-config` command. With no arguments, this will validate all app nginx configs, one at a time. A minimal wrapper nginx config is generated for each app's nginx config, upon which `nginx -t` will be run.
|
||||
|
||||
```shell
|
||||
dokku nginx:validate-config
|
||||
@@ -113,6 +144,34 @@ The `--clean` flag may also be specified for a given app:
|
||||
dokku nginx:validate-config node-js-app --clean
|
||||
```
|
||||
|
||||
### Displaying nginx reports for an app
|
||||
|
||||
You can get a report about the app's nginx configuration using the `nginx:report` command:
|
||||
|
||||
```shell
|
||||
dokku nginx:report
|
||||
```
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
dokku nginx:report node-js-app
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku nginx:report node-js-app --nginx-bind-address-ipv4
|
||||
```
|
||||
|
||||
The `nginx:report` command also takes a `--format` flag, with the valid options including `stdout` (default) and `json`. The `json` output format can be used for automation purposes:
|
||||
|
||||
```shell
|
||||
dokku nginx:report node-js-app --format json
|
||||
```
|
||||
|
||||
The `--format` flag cannot be combined with an info flag.
|
||||
|
||||
### Custom Error Pages
|
||||
|
||||
By default, Dokku provides custom error pages for the following three categories of errors:
|
||||
@@ -125,52 +184,91 @@ These are provided as an alternative to the generic Nginx error page, are shared
|
||||
|
||||
### Default site
|
||||
|
||||
By default, Dokku will route any received request with an unknown HOST header value to the lexicographically first site in the nginx config stack. This means that accessing the dokku server via its IP address or a bogus domain name may return a seemingly random website.
|
||||
> [!IMPORTANT]
|
||||
> New as of 0.38.0
|
||||
|
||||
> [!WARNING]
|
||||
> Some versions of Nginx may create a default site when installed. This site is simply a static page which says "Welcome to Nginx", and if this default site is enabled, Nginx will not route any requests with an unknown HOST header to Dokku. If you want Dokku to receive all requests, run the following commands:
|
||||
>
|
||||
> ```
|
||||
> rm /etc/nginx/sites-enabled/default
|
||||
> dokku nginx:stop
|
||||
> dokku nginx:start
|
||||
> ```
|
||||
On fresh apt installs, Dokku ships a catch-all default site at `/etc/nginx/conf.d/00-default-vhost.conf` that rejects requests whose Host header (or TLS SNI) does not match any deployed app. The catch-all uses [`ssl_reject_handshake on`](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_reject_handshake) for HTTPS and [`return 444`](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return) for HTTP. Both close the connection without sending a response.
|
||||
|
||||
If services should only be accessed via their domain name, you may want to disable the default site by adding the following configuration to the global nginx configuration.
|
||||
|
||||
Create the file at `/etc/nginx/conf.d/00-default-vhost.conf`:
|
||||
The shipped file looks like:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
# If services hosted by dokku are available via HTTPS, it is recommended
|
||||
# to also uncomment the following section.
|
||||
#
|
||||
# Please note that in order to let this work, you need an SSL certificate. However
|
||||
# it does not need to be valid. Users of Debian-based distributions can install the
|
||||
# `ssl-cert` package with `sudo apt install ssl-cert` to automatically generate
|
||||
# a self-signed certificate that is stored at `/etc/ssl/certs/ssl-cert-snakeoil.pem`.
|
||||
#
|
||||
#listen 443 ssl;
|
||||
#listen [::]:443 ssl;
|
||||
#ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
|
||||
#ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
listen 443 ssl default_server;
|
||||
listen [::]:443 ssl default_server;
|
||||
|
||||
server_name _;
|
||||
access_log off;
|
||||
access_log off;
|
||||
|
||||
ssl_reject_handshake on;
|
||||
return 444;
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to reload nginx after creating this file by running `systemctl reload nginx.service`.
|
||||
The `00-` prefix forces nginx to load this file before `/etc/nginx/conf.d/dokku.conf`, so its `default_server` markers establish the default for each port before any per-app server blocks are loaded.
|
||||
|
||||
This will catch all unknown HOST header values and close the connection without responding. You can replace the `return 444;` with `return 410;` which will cause nginx to respond with an error page.
|
||||
#### TLS handshake behavior
|
||||
|
||||
The configuration file must be loaded before `/etc/nginx/conf.d/dokku.conf`, so it can not be arranged as a vhost in `/etc/nginx/sites-enabled` that is only processed afterwards.
|
||||
The catch-all does not affect TLS handshakes for legitimate apps. nginx selects the matching server block via SNI before completing the handshake; only requests that have no matching app fall through to the catch-all.
|
||||
|
||||
Alternatively, you may push an app to your Dokku host with a name like "00-default". As long as it lists first in `ls /home/dokku/*/nginx.conf | head`, it will be used as the default nginx vhost.
|
||||
| Request | Result |
|
||||
| --- | --- |
|
||||
| HTTPS to a configured app's hostname (with matching SNI) and the app has a cert | Handshake completes with the app's cert. Catch-all not consulted. |
|
||||
| HTTPS to a configured app's hostname when the app has no cert configured | Handshake rejected by the catch-all. (Previously: nginx fell through to the lexicographically first port-443 server block and presented its cert, producing a confusing cert-mismatch error.) |
|
||||
| HTTPS to the server's IP with no SNI, or with an SNI matching no app | Handshake rejected. |
|
||||
| HTTP to a configured app's hostname | Routed normally to that app. Catch-all not consulted. |
|
||||
| HTTP to a hostname matching no app | Catch-all `return 444`. |
|
||||
|
||||
#### Conflicting upstream nginx default vhost
|
||||
|
||||
A fresh nginx install ships its own default vhost that also claims port 80 with `default_server`, which would cause `nginx -t` to fail with `a duplicate default server for 0.0.0.0:80` once the dokku catch-all is in place. To avoid this, the dokku postinst renames any of the following files in place to `${path}.dokku-disabled` instead of deleting them, preserving any local customizations:
|
||||
|
||||
- `/etc/nginx/sites-enabled/default`
|
||||
- `/etc/nginx/sites-available/default`
|
||||
- `/etc/nginx/conf.d/default.conf`
|
||||
|
||||
To recover an original file, inspect the `.dokku-disabled` sibling.
|
||||
|
||||
#### Disabling the catch-all on first install
|
||||
|
||||
Select "No" at the `dokku/install_default_site` debconf prompt, or pre-seed the answer before installing:
|
||||
|
||||
```shell
|
||||
echo 'dokku dokku/install_default_site boolean false' | debconf-set-selections
|
||||
```
|
||||
|
||||
#### Customizing or removing the catch-all after install
|
||||
|
||||
To customize the reject behavior, edit `/etc/nginx/conf.d/00-default-vhost.conf` and reload:
|
||||
|
||||
```shell
|
||||
dokku nginx:reload
|
||||
```
|
||||
|
||||
For example, replace `return 444;` with `return 410;` to respond with an HTTP 410 Gone error page instead of dropping the connection.
|
||||
|
||||
To disable the catch-all without uninstalling dokku:
|
||||
|
||||
```shell
|
||||
mv /etc/nginx/conf.d/00-default-vhost.conf{,.disabled}
|
||||
dokku nginx:reload
|
||||
```
|
||||
|
||||
#### Installing the catch-all on upgraded or non-apt installs
|
||||
|
||||
Existing dokku installs upgraded from earlier versions do not get the catch-all installed automatically; the upgrade leaves their nginx configuration untouched. To install it manually, copy the shipped template into place and reload nginx:
|
||||
|
||||
```shell
|
||||
cp /var/lib/dokku/core-plugins/available/nginx-vhosts/templates/default-site.conf /etc/nginx/conf.d/00-default-vhost.conf
|
||||
dokku nginx:reload
|
||||
```
|
||||
|
||||
If the upstream nginx default vhost is also active, disable it first (e.g. `mv /etc/nginx/sites-enabled/default{,.disabled}`) to avoid a duplicate-default-server error.
|
||||
|
||||
#### App-name based alternative
|
||||
|
||||
As an alternative to the catch-all file, you may push an app to your Dokku host with a name like `00-default`. As long as it lists first in `ls /home/dokku/*/nginx.conf | head`, it will be used as the default nginx vhost.
|
||||
|
||||
### Customizing the nginx configuration
|
||||
|
||||
@@ -235,8 +333,8 @@ Unsetting this value is the same as enabling custom nginx config usage.
|
||||
{{ .APP }} Application name
|
||||
{{ .APP_SSL_PATH }} Path to SSL certificate and key
|
||||
{{ .DOKKU_ROOT }} Global Dokku root directory (ex: app dir would be `{{ .DOKKU_ROOT }}/{{ .APP }}`)
|
||||
{{ .PROXY_PORT }} Non-SSL nginx listener port (same as `DOKKU_PROXY_PORT` config var)
|
||||
{{ .PROXY_SSL_PORT }} SSL nginx listener port (same as `DOKKU_PROXY_SSL_PORT` config var)
|
||||
{{ .PROXY_PORT }} Non-SSL nginx listener port (same as the `proxy-port` property)
|
||||
{{ .PROXY_SSL_PORT }} SSL nginx listener port (same as the `proxy-ssl-port` property)
|
||||
{{ .NOSSL_SERVER_NAME }} List of non-SSL VHOSTS
|
||||
{{ .PROXY_PORT_MAP }} List of port mappings (same as the `map` ports property)
|
||||
{{ .PROXY_UPSTREAM_PORTS }} List of configured upstream ports (derived from the `map` ports property)
|
||||
|
||||
@@ -35,7 +35,7 @@ The OpenResty plugin has specific rules for routing requests:
|
||||
To use the OpenResty plugin, use the `proxy:set` command for the app in question:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app openresty
|
||||
dokku proxy:set node-js-app type openresty
|
||||
```
|
||||
|
||||
This will enable the docker label-based OpenResty integration. All future deploys will inject the correct labels for OpenResty to read and route requests to containers. Due to the docker label-based integration used by OpenResty, a single deploy or rebuild will be required before requests will route successfully.
|
||||
|
||||
@@ -74,7 +74,7 @@ Example `app.json` configuration:
|
||||
To use the Traefik plugin, use the `proxy:set` command for the app in question:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app traefik
|
||||
dokku proxy:set node-js-app type traefik
|
||||
```
|
||||
|
||||
This will enable the docker label-based Traefik integration. All future deploys will inject the correct labels for Traefik to read and route requests to containers. Due to the docker label-based integration used by Traefik, a single deploy or rebuild will be required before requests will route successfully.
|
||||
|
||||
@@ -9,7 +9,7 @@ proxy:clear-config [--all|<app>] # Clears config for given app
|
||||
proxy:disable [--parallel count] [--all|<app>] # Disable proxy for app
|
||||
proxy:enable [--parallel count] [--all|<app>] # Enable proxy for app
|
||||
proxy:report [<app>] [<flag>] # Displays a proxy report for one or more apps
|
||||
proxy:set [<app>|--global] <proxy-type> # Set proxy type for app
|
||||
proxy:set [<app>|--global] <key> (<value>) # Set or clear a proxy property for an app
|
||||
```
|
||||
|
||||
In Dokku 0.5.0, port proxying was decoupled from the `nginx-vhosts` plugin into the proxy plugin. Dokku 0.6.0 introduced the ability to map host ports to specific container ports. This allows other proxy software - such as HAProxy or Caddy - to be used in place of nginx.
|
||||
@@ -21,27 +21,69 @@ In Dokku 0.5.0, port proxying was decoupled from the `nginx-vhosts` plugin into
|
||||
The default proxy shipped with Dokku is `nginx`. It can be changed via the `proxy:set` command.
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app caddy
|
||||
dokku proxy:set node-js-app type caddy
|
||||
```
|
||||
|
||||
```
|
||||
-----> Setting config vars
|
||||
DOKKU_APP_PROXY_TYPE: caddy
|
||||
=====> Setting type to caddy
|
||||
```
|
||||
|
||||
The proxy may also be set on a global basis. This is usually preferred as running multiple proxy implementations may cause port collision issues.
|
||||
|
||||
```shell
|
||||
dokku proxy:set --global caddy
|
||||
dokku proxy:set --global type caddy
|
||||
```
|
||||
|
||||
```
|
||||
-----> Setting config vars
|
||||
DOKKU_PROXY_TYPE: caddy
|
||||
=====> Setting type to caddy
|
||||
```
|
||||
|
||||
Changing the proxy does not stop or start any given proxy implementation. Please see the documentation for your proxy implementation for details on how to perform a change.
|
||||
|
||||
### Disabling and enabling the proxy
|
||||
|
||||
The proxy can be disabled on a per-app basis via the `proxy:disable` command. While disabled, no proxy configuration will be generated for the app and incoming requests will not be routed through the configured proxy.
|
||||
|
||||
```shell
|
||||
dokku proxy:disable node-js-app
|
||||
```
|
||||
|
||||
```
|
||||
-----> Disabling proxy for app
|
||||
```
|
||||
|
||||
The proxy can be re-enabled with the `proxy:enable` command:
|
||||
|
||||
```shell
|
||||
dokku proxy:enable node-js-app
|
||||
```
|
||||
|
||||
```
|
||||
-----> Enabling proxy for app
|
||||
```
|
||||
|
||||
### Setting proxy ports
|
||||
|
||||
When an app's domains are disabled (see [domains documentation](/docs/configuration/domains.md)), Dokku still exposes the app on a high port so that internal services can reach it at a stable port across deploys. The non-SSL and SSL ports used for this can be configured via the `proxy:set` command:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app proxy-port 5000
|
||||
dokku proxy:set node-js-app proxy-ssl-port 5443
|
||||
```
|
||||
|
||||
Either property may also be set globally. Per-app values take precedence over the global value.
|
||||
|
||||
```shell
|
||||
dokku proxy:set --global proxy-port 5000
|
||||
dokku proxy:set --global proxy-ssl-port 5443
|
||||
```
|
||||
|
||||
The default value for either property may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku proxy:set node-js-app proxy-port
|
||||
```
|
||||
|
||||
### Regenerating proxy config
|
||||
|
||||
In certain cases, your app proxy configs may drift from the correct config for your app. You may regenerate the config at any point via the `proxy:build-config` command. This command will trigger a rebuild for the configured proxy implementation (default: nginx) for a given app. The command may fail if there are no current web listeners for your app.
|
||||
|
||||
@@ -315,6 +315,28 @@ Finally, the number of parallel workers may be automatically set to the number o
|
||||
dokku ps:start --all --parallel -1
|
||||
```
|
||||
|
||||
### Customizing the start command
|
||||
|
||||
The command used to start an app's containers can be customized via two `ps` properties, depending on which builder is in use.
|
||||
|
||||
For buildpack-built apps (where the start command normally comes from the `Procfile`), set `start-cmd`:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app start-cmd "node server.js"
|
||||
```
|
||||
|
||||
For Dockerfile-built apps, set `dockerfile-start-cmd`. This value is passed as arguments to `docker run` and overrides or supplements the image's `CMD` / `ENTRYPOINT`. See the [Dockerfile builder documentation](/docs/deployment/builders/dockerfiles.md#customizing-the-run-command) for context.
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app dockerfile-start-cmd "--harmony server.js"
|
||||
```
|
||||
|
||||
Either property can be cleared by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app start-cmd
|
||||
```
|
||||
|
||||
### Restart policies
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -429,3 +451,15 @@ When a server reboots or Docker is restarted/upgraded, Docker may or may not sta
|
||||
- If any of the app containers are missing, the entire app will be rebuilt.
|
||||
|
||||
During this time, requests may route to the incorrect app if the assigned IPs correspond to those for other apps. While dokku makes all efforts to avoid this, there may be a few minutes where urls may route to the wrong app. To avoid this, either use a custom proxy plugin or wait a few minutes until the restoration process is complete.
|
||||
|
||||
Per-app restore behavior can be controlled via the `restore` property. When set to `false`, `ps:restore` will skip the app on reboot:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app restore false
|
||||
```
|
||||
|
||||
The default value (`true`) may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app restore
|
||||
```
|
||||
|
||||
@@ -9,26 +9,26 @@
|
||||
<meta name="author" content="">
|
||||
<title>Dokku - {{DOC_TITLE}}</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Dokku">
|
||||
<meta name="application-name" content="Dokku">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<script>
|
||||
@@ -48,7 +48,7 @@
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap" rel="stylesheet">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.8/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.1/docs/assets/style.css" rel="stylesheet">
|
||||
<!-- <link href="./assets/style.css" rel="stylesheet"> -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
</head>
|
||||
@@ -188,6 +188,7 @@
|
||||
<a href="#" class="list-group-item disabled">Advanced Usage</a>
|
||||
|
||||
<a href="/{{NAME}}/advanced-usage/backup-recovery/" class="list-group-item">Backup and Recovery</a>
|
||||
<a href="/{{NAME}}/advanced-usage/builds/" class="list-group-item">Build Tracking</a>
|
||||
<a href="/{{NAME}}/advanced-usage/deployment-tasks/" class="list-group-item">Deployment Tasks</a>
|
||||
<a href="/{{NAME}}/advanced-usage/docker-options/" class="list-group-item">Docker Container Options</a>
|
||||
<a href="/{{NAME}}/advanced-usage/registry-management/" class="list-group-item">Docker Registry Management</a>
|
||||
@@ -222,6 +223,17 @@
|
||||
<a href="#" class="list-group-item disabled">Community Contributions</a>
|
||||
<a href="/{{NAME}}/community/clients/" class="list-group-item">Clients</a>
|
||||
<a href="/{{NAME}}/community/plugins/" class="list-group-item">Plugins</a>
|
||||
|
||||
<a href="#" class="list-group-item disabled">File Formats</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/app-json/" class="list-group-item">app.json</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/buildpack-file/" class="list-group-item">.buildpack</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/dockerfile/" class="list-group-item">Dockerfile</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/lambda-yml/" class="list-group-item">lambda.yml</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/nginx-conf-sigil/" class="list-group-item">nginx.conf.sigil</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/nixpacks-toml/" class="list-group-item">nixpacks.toml</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/procfile/" class="list-group-item">Procfile</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/project-toml/" class="list-group-item">project.toml</a>
|
||||
<a href="/{{NAME}}/appendices/file-formats/railpack-json/" class="list-group-item">railpack.json</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 col-md-9 markdown-body" style="padding-top:16px">
|
||||
|
||||
4
dokku
4
dokku
@@ -188,6 +188,10 @@ execute_dokku_cmd() {
|
||||
set -- "$PLUGIN_CMD" "$@"
|
||||
fi
|
||||
|
||||
if [[ "$PLUGIN_NAME" == "git-hook" ]] || [[ "$PLUGIN_NAME" == "ps:rebuild" ]] || [[ "$PLUGIN_NAME" == "ps:restart" ]]; then
|
||||
dokku_setup_build_capture "$2" "$PLUGIN_NAME"
|
||||
fi
|
||||
|
||||
if [[ -x $PLUGIN_ENABLED_PATH/$PLUGIN_NAME/subcommands/default ]]; then
|
||||
"$PLUGIN_ENABLED_PATH/$PLUGIN_NAME/subcommands/default" "$@"
|
||||
implemented=1
|
||||
|
||||
3
go.work
3
go.work
@@ -1,4 +1,4 @@
|
||||
go 1.25.5
|
||||
go 1.26.2
|
||||
|
||||
use (
|
||||
./plugins/app-json
|
||||
@@ -21,4 +21,5 @@ use (
|
||||
./plugins/scheduler
|
||||
./plugins/scheduler-docker-local
|
||||
./plugins/scheduler-k3s
|
||||
./plugins/storage
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core standard plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core events logging plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -24,11 +24,56 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// EnvVarValue represents an environment variable definition in app.json
|
||||
// It supports both simple string values and complex object definitions
|
||||
type EnvVarValue struct {
|
||||
// Description provides context for the env var (used in prompts)
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Value is the default value for the env var
|
||||
Value string `json:"value,omitempty"`
|
||||
|
||||
// Required indicates if the env var must have a value (defaults to true per Heroku spec)
|
||||
Required *bool `json:"required,omitempty"`
|
||||
|
||||
// Generator specifies how to auto-generate a value (currently only "secret" is supported)
|
||||
Generator string `json:"generator,omitempty"`
|
||||
|
||||
// Sync indicates if the value should be set on every deploy, not just first
|
||||
Sync bool `json:"sync,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON handles both string and object formats for env vars
|
||||
func (e *EnvVarValue) UnmarshalJSON(data []byte) error {
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err == nil {
|
||||
e.Value = str
|
||||
return nil
|
||||
}
|
||||
|
||||
type envVarAlias EnvVarValue
|
||||
return json.Unmarshal(data, (*envVarAlias)(e))
|
||||
}
|
||||
|
||||
// IsRequired returns true if the env var is required (defaults to true per Heroku spec)
|
||||
func (e *EnvVarValue) IsRequired() bool {
|
||||
if e.Required == nil {
|
||||
return true
|
||||
}
|
||||
return *e.Required
|
||||
}
|
||||
|
||||
// AppJSON is a struct that represents an app.json file as understood by Dokku
|
||||
type AppJSON struct {
|
||||
// Buildpacks is a list of buildpacks to use for the app
|
||||
Buildpacks []Buildpack `json:"buildpacks"`
|
||||
|
||||
// Cron is a list of cron tasks to execute
|
||||
Cron []CronTask `json:"cron"`
|
||||
|
||||
// Env is a map of environment variables to set
|
||||
Env map[string]EnvVarValue `json:"env,omitempty"`
|
||||
|
||||
// Formation is a map of process types to scale
|
||||
Formation map[string]Formation `json:"formation"`
|
||||
|
||||
@@ -51,6 +96,12 @@ type AppJSON struct {
|
||||
} `json:"scripts"`
|
||||
}
|
||||
|
||||
// Buildpack is a struct that represents a single buildpack
|
||||
type Buildpack struct {
|
||||
// URL is the URL of the buildpack
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// CronTask is a struct that represents a single cron task from an app.json file
|
||||
type CronTask struct {
|
||||
// Command is the command to execute
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package appjson
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
shellquote "github.com/kballard/go-shellquote"
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
func constructScript(command string, shell string, isHerokuishImage bool, isCnbImage bool, dockerfileEntrypoint string) []string {
|
||||
@@ -455,3 +460,199 @@ func setScale(appName string) error {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// generateSecret generates a cryptographically secure random hex string of specified length
|
||||
func generateSecret(length int) (string, error) {
|
||||
bytes := make([]byte, length/2)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
return "", fmt.Errorf("failed to generate secret: %w", err)
|
||||
}
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
// isInteractive returns true if stdin is a terminal (TTY available)
|
||||
func isInteractive() bool {
|
||||
return isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd())
|
||||
}
|
||||
|
||||
// promptForValue prompts the user for an environment variable value
|
||||
func promptForValue(varName string, envVar EnvVarValue) (string, error) {
|
||||
prompt := fmt.Sprintf("Enter value for %s", varName)
|
||||
if envVar.Description != "" {
|
||||
prompt = fmt.Sprintf("Enter value for %s (%s)", varName, envVar.Description)
|
||||
}
|
||||
|
||||
common.LogInfo1(prompt)
|
||||
fmt.Print("> ")
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
response, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(response), nil
|
||||
}
|
||||
|
||||
// getCurrentConfig retrieves the current config values for an app
|
||||
func getCurrentConfig(appName string) (map[string]string, error) {
|
||||
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-export",
|
||||
Args: []string{appName, "false", "true", "json"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get current config: %w", err)
|
||||
}
|
||||
|
||||
var currentConfig map[string]string
|
||||
if err := json.Unmarshal(results.StdoutBytes(), ¤tConfig); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse current config: %w", err)
|
||||
}
|
||||
|
||||
return currentConfig, nil
|
||||
}
|
||||
|
||||
// setConfigVars sets multiple config vars for an app without triggering restart
|
||||
func setConfigVars(appName string, vars map[string]string) error {
|
||||
if len(vars) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build arguments for config-set trigger: --no-restart flag, appName, key=value pairs
|
||||
args := []string{"--no-restart", appName}
|
||||
for key, value := range vars {
|
||||
args = append(args, fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-set",
|
||||
Args: args,
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set config vars: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processAppJSONEnv processes env vars from app.json and sets them as config
|
||||
func processAppJSONEnv(appName string) error {
|
||||
appJSON, err := GetAppJSON(appName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(appJSON.Env) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
common.LogInfo1("Processing app.json env vars")
|
||||
|
||||
isFirstDeploy := common.PropertyGet("common", appName, "deployed") != "true"
|
||||
|
||||
// Check if env vars have been processed for this deploy
|
||||
envProcessedProperty := "appjson-env-processed"
|
||||
alreadyProcessed := common.PropertyGet("app-json", appName, envProcessedProperty) == "executed"
|
||||
|
||||
// Get current config values
|
||||
currentConfig, err := getCurrentConfig(appName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
varsToSet := make(map[string]string)
|
||||
interactive := isInteractive()
|
||||
|
||||
// Sort keys for deterministic ordering
|
||||
var keys []string
|
||||
for k := range appJSON.Env {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, varName := range keys {
|
||||
envVar := appJSON.Env[varName]
|
||||
|
||||
// Determine if we should process this var
|
||||
shouldProcess := false
|
||||
if isFirstDeploy && !alreadyProcessed {
|
||||
// First deploy: process all vars
|
||||
shouldProcess = true
|
||||
} else if envVar.Sync {
|
||||
// Subsequent deploy with sync: always process sync vars
|
||||
shouldProcess = true
|
||||
}
|
||||
|
||||
if !shouldProcess {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if already set (for first deploy, skip if already has value and not sync)
|
||||
currentValue, hasValue := currentConfig[varName]
|
||||
if hasValue && currentValue != "" && !envVar.Sync {
|
||||
common.LogDebug(fmt.Sprintf("Skipping %s: already set", varName))
|
||||
continue
|
||||
}
|
||||
|
||||
// Determine the value
|
||||
var value string
|
||||
|
||||
// Handle generator
|
||||
if envVar.Generator == "secret" {
|
||||
if !hasValue || currentValue == "" || envVar.Sync {
|
||||
generated, err := generateSecret(64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate secret for %s: %w", varName, err)
|
||||
}
|
||||
value = generated
|
||||
common.LogDebug(fmt.Sprintf("Generated secret for %s", varName))
|
||||
} else {
|
||||
continue // Already has value, not sync
|
||||
}
|
||||
} else if envVar.Value != "" {
|
||||
// Use default value
|
||||
value = envVar.Value
|
||||
} else if interactive {
|
||||
// Prompt user
|
||||
prompted, err := promptForValue(varName, envVar)
|
||||
if err != nil {
|
||||
if envVar.IsRequired() {
|
||||
return fmt.Errorf("required env var %s has no value and prompt failed: %w", varName, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if prompted == "" && envVar.IsRequired() {
|
||||
return fmt.Errorf("required env var %s cannot be empty", varName)
|
||||
}
|
||||
value = prompted
|
||||
} else {
|
||||
// No TTY, no default, no generator
|
||||
if envVar.IsRequired() {
|
||||
return fmt.Errorf("required env var %s has no value, no default, and no TTY for prompt", varName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if value != "" {
|
||||
varsToSet[varName] = value
|
||||
}
|
||||
}
|
||||
|
||||
if len(varsToSet) == 0 {
|
||||
common.LogVerbose("No env vars to set from app.json")
|
||||
if !isFirstDeploy {
|
||||
return common.PropertyWrite("app-json", appName, envProcessedProperty, "executed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the config vars without restart (we're in middle of deploy)
|
||||
common.LogInfo1(fmt.Sprintf("Setting %d env var(s) from app.json", len(varsToSet)))
|
||||
if err := setConfigVars(appName, varsToSet); err != nil {
|
||||
return fmt.Errorf("failed to set env vars: %w", err)
|
||||
}
|
||||
|
||||
// Mark as processed
|
||||
return common.PropertyWrite("app-json", appName, envProcessedProperty, "executed")
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
module github.com/dokku/dokku/plugins/app-json
|
||||
|
||||
go 1.25.5
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/mattn/go-isatty v0.0.22
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/tailscale/hujson v0.0.0-20250605163823-992244df8c5a
|
||||
k8s.io/utils v0.0.0-20240102154912-e7106e64919e
|
||||
@@ -17,7 +18,6 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/melbahja/goph v1.5.0 // indirect
|
||||
github.com/otiai10/copy v1.14.1 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
|
||||
@@ -16,12 +16,12 @@ github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/melbahja/goph v1.5.0 h1:RQUBpLvfg3i7fjfG8rTcSWyMjVRfdhwrrfQhjYee4dQ=
|
||||
github.com/melbahja/goph v1.5.0/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
|
||||
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
|
||||
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
|
||||
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
@@ -48,7 +48,6 @@ golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core app-json plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -6,14 +6,23 @@ import (
|
||||
|
||||
// ReportSingleApp is an internal function that displays the builder report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--app-json-computed-selected": reportComputedAppjsonpath,
|
||||
"--app-json-global-selected": reportGlobalAppjsonpath,
|
||||
"--app-json-selected": reportAppjsonpath,
|
||||
var flags map[string]common.ReportFunc
|
||||
if appName == "--global" {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--app-json-global-selected": reportGlobalAppjsonpath,
|
||||
}
|
||||
} else {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--app-json-computed-selected": reportComputedAppjsonpath,
|
||||
"--app-json-global-selected": reportGlobalAppjsonpath,
|
||||
"--app-json-selected": reportAppjsonpath,
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
|
||||
@@ -21,11 +21,14 @@ func main() {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("app-json:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
osArgs, infoFlag, flagErr := common.ParseReportArgs("appjson", os.Args[2:])
|
||||
reportArgs, flagErr := common.ParseReportArgs("appjson", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(osArgs)
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
err = appjson.CommandReport(appName, *format, infoFlag)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = appjson.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
case "set":
|
||||
args := flag.NewFlagSet("app-json:set", flag.ExitOnError)
|
||||
|
||||
@@ -71,6 +71,11 @@ func TriggerCorePostDeploy(appName string) error {
|
||||
|
||||
// TriggerCorePostExtract ensures that the main app.json is the one specified by app-json-path
|
||||
func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
|
||||
// Clear the env-processed property on new source extraction to allow re-processing
|
||||
if err := common.PropertyDelete("app-json", appName, "appjson-env-processed"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
destination := common.GetAppDataDirectory("app-json", appName)
|
||||
appJSONPath := strings.Trim(reportComputedAppjsonpath(appName), "/")
|
||||
if appJSONPath == "" {
|
||||
@@ -190,7 +195,13 @@ func TriggerPostDeploy(appName string, imageTag string) error {
|
||||
return executeScript(appName, image, imageTag, "postdeploy")
|
||||
}
|
||||
|
||||
// TriggerPreReleaseBuilder processes app.json env vars and executes the predeploy task
|
||||
func TriggerPreReleaseBuilder(builderType string, appName string, image string) error {
|
||||
// Process app.json env vars before predeploy script
|
||||
if err := processAppJSONEnv(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parts := strings.Split(image, ":")
|
||||
imageTag := parts[len(parts)-1]
|
||||
return executeScript(appName, image, imageTag, "predeploy")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBCOMMANDS = subcommands/clone subcommands/create subcommands/destroy subcommands/exists subcommands/list subcommands/lock subcommands/locked subcommands/rename subcommands/report subcommands/unlock
|
||||
SUBCOMMANDS = subcommands/clone subcommands/create subcommands/destroy subcommands/exists subcommands/list subcommands/lock subcommands/locked subcommands/rename subcommands/report subcommands/set subcommands/unlock
|
||||
TRIGGERS = triggers/app-create triggers/app-destroy triggers/app-exists triggers/app-maybe-create triggers/deploy-source-set triggers/install triggers/post-app-clone-setup triggers/post-app-rename triggers/post-app-rename-setup triggers/post-create triggers/post-delete triggers/report
|
||||
BUILD = commands subcommands triggers
|
||||
PLUGIN_NAME = apps
|
||||
|
||||
@@ -5,11 +5,13 @@ var (
|
||||
DefaultProperties = map[string]string{
|
||||
"deploy-source": "",
|
||||
"deploy-source-metadata": "",
|
||||
"disable-autocreation": "",
|
||||
}
|
||||
|
||||
// GlobalProperties is a map of all valid global apps properties
|
||||
GlobalProperties = map[string]bool{
|
||||
"deploy-source": true,
|
||||
"deploy-source-metadata": true,
|
||||
"disable-autocreation": true,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -132,11 +132,7 @@ func maybeCreateApp(appName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get-global",
|
||||
Args: []string{"DOKKU_DISABLE_APP_AUTOCREATION"},
|
||||
})
|
||||
disableAutocreate := results.StdoutContents()
|
||||
disableAutocreate := common.PropertyGetDefault("apps", "--global", "disable-autocreation", "")
|
||||
if disableAutocreate == "true" {
|
||||
common.LogWarn("App auto-creation disabled.")
|
||||
return fmt.Errorf("Re-enable app auto-creation or create an app with 'dokku apps:create %s'", appName)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/dokku/dokku/plugins/apps
|
||||
|
||||
go 1.25.5
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
|
||||
@@ -18,8 +18,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.0 h1:RQUBpLvfg3i7fjfG8rTcSWyMjVRfdhwrrfQhjYee4dQ=
|
||||
github.com/melbahja/goph v1.5.0/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
|
||||
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
|
||||
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
|
||||
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core apps plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -9,16 +9,23 @@ import (
|
||||
|
||||
// ReportSingleApp is an internal function that displays the app report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--app-created-at": reportCreatedAt,
|
||||
"--app-deploy-source": reportDeploySource,
|
||||
"--app-deploy-source-metadata": reportDeploySourceMetadata,
|
||||
"--app-dir": reportDir,
|
||||
"--app-locked": reportLocked,
|
||||
var flags map[string]common.ReportFunc
|
||||
if appName == "--global" {
|
||||
flags = map[string]common.ReportFunc{}
|
||||
} else {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--app-created-at": reportCreatedAt,
|
||||
"--app-deploy-source": reportDeploySource,
|
||||
"--app-deploy-source-metadata": reportDeploySourceMetadata,
|
||||
"--app-dir": reportDir,
|
||||
"--app-locked": reportLocked,
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
|
||||
@@ -28,6 +28,7 @@ Additional commands:`
|
||||
apps:locked <app>, Checks if an app is locked for deployment
|
||||
apps:rename <old-app> <new-app>, Rename an app
|
||||
apps:report [<app>] [<flag>], Display report about an app
|
||||
apps:set <app>|--global <key> <value>, Set or clear an apps property
|
||||
apps:unlock <app>, Unlocks an app for deployment`
|
||||
)
|
||||
|
||||
|
||||
@@ -66,12 +66,28 @@ func main() {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("apps:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
osArgs, infoFlag, flagErr := common.ParseReportArgs("apps", os.Args[2:])
|
||||
reportArgs, flagErr := common.ParseReportArgs("apps", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(osArgs)
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
err = apps.CommandReport(appName, *format, infoFlag)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = apps.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
case "set":
|
||||
args := flag.NewFlagSet("apps:set", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: set a global property")
|
||||
args.Parse(os.Args[2:])
|
||||
appName := args.Arg(0)
|
||||
property := args.Arg(1)
|
||||
value := args.Arg(2)
|
||||
if *global {
|
||||
appName = "--global"
|
||||
property = args.Arg(0)
|
||||
value = args.Arg(1)
|
||||
}
|
||||
err = apps.CommandSet(appName, property, value)
|
||||
case "unlock":
|
||||
args := flag.NewFlagSet("apps:unlock", flag.ExitOnError)
|
||||
args.Parse(os.Args[2:])
|
||||
|
||||
@@ -226,6 +226,12 @@ func CommandReport(appName string, format string, infoFlag string) error {
|
||||
return ReportSingleApp(appName, format, infoFlag)
|
||||
}
|
||||
|
||||
// CommandSet set or clear an apps property for an app
|
||||
func CommandSet(appName string, property string, value string) error {
|
||||
common.CommandPropertySet("apps", appName, property, value, DefaultProperties, GlobalProperties)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommandUnlock unlocks an app for deployment
|
||||
func CommandUnlock(appName string) error {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
|
||||
@@ -53,6 +53,15 @@ func TriggerInstall() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := common.MigrateConfigToProperties("apps", []common.MigrateConfigEntry{
|
||||
{
|
||||
GlobalConfigVar: "DOKKU_DISABLE_APP_AUTOCREATION",
|
||||
Property: "disable-autocreation",
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// migrate all created-at values from app mod-time to property
|
||||
for _, appName := range apps {
|
||||
if common.PropertyExists("apps", appName, "created-at") {
|
||||
|
||||
@@ -141,6 +141,28 @@ trigger-builder-dockerfile-builder-build() {
|
||||
DOCKERFILE_ARGS+=("--label" "${1#--label=}")
|
||||
shift 1
|
||||
;;
|
||||
--memory | -m)
|
||||
DOCKERFILE_ARGS+=("--memory")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--memory=* | -m=*)
|
||||
if [[ "$1" == "--memory=*" ]]; then
|
||||
DOCKERFILE_ARGS+=("--memory" "${1#--memory=}")
|
||||
elif [[ "$1" == "-m=*" ]]; then
|
||||
DOCKERFILE_ARGS+=("--memory" "${1#-m=}")
|
||||
fi
|
||||
shift 1
|
||||
;;
|
||||
--memory-swap)
|
||||
DOCKERFILE_ARGS+=("--memory-swap")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--memory-swap=*)
|
||||
DOCKERFILE_ARGS+=("--memory-swap" "${1#--memory-swap=}")
|
||||
shift 1
|
||||
;;
|
||||
--network)
|
||||
DOCKERFILE_ARGS+=("--network")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
@@ -205,7 +227,7 @@ trigger-builder-dockerfile-builder-build() {
|
||||
shift 1
|
||||
;;
|
||||
--ssh)
|
||||
DOCKERFILE_ARGS+=("--platform")
|
||||
DOCKERFILE_ARGS+=("--ssh")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
@@ -213,6 +235,15 @@ trigger-builder-dockerfile-builder-build() {
|
||||
DOCKERFILE_ARGS+=("--ssh" "${1#--ssh=}")
|
||||
shift 1
|
||||
;;
|
||||
--tag)
|
||||
DOCKERFILE_ARGS+=("--tag")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--tag=*)
|
||||
DOCKERFILE_ARGS+=("--tag" "${1#--tag=}")
|
||||
shift 1
|
||||
;;
|
||||
--target)
|
||||
DOCKERFILE_ARGS+=("--target")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
@@ -223,12 +254,12 @@ trigger-builder-dockerfile-builder-build() {
|
||||
shift 1
|
||||
;;
|
||||
--ulimit)
|
||||
DOCKERFILE_ARGS+=("--tag")
|
||||
DOCKERFILE_ARGS+=("--ulimit")
|
||||
DOCKERFILE_ARGS+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--tag=*)
|
||||
DOCKERFILE_ARGS+=("--tag" "${1#--tag=}")
|
||||
--ulimit=*)
|
||||
DOCKERFILE_ARGS+=("--ulimit" "${1#--ulimit=}")
|
||||
shift 1
|
||||
;;
|
||||
--check | -D | --debug | --no-cache)
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-dockerfile-report() {
|
||||
declare desc="displays a builder-dockerfile report for one or more apps"
|
||||
declare cmd="builder-dockerfile:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-dockerfile-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-dockerfile-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-dockerfile-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-dockerfile-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-dockerfile-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-dockerfile-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-dockerfile-computed-dockerfile-path: $(fn-builder-dockerfile-computed-dockerfile-path "$APP")"
|
||||
"--builder-dockerfile-global-dockerfile-path: $(fn-builder-dockerfile-global-dockerfile-path "$APP")"
|
||||
"--builder-dockerfile-dockerfile-path: $(fn-builder-dockerfile-dockerfile-path "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-dockerfile-global-dockerfile-path: $(fn-builder-dockerfile-global-dockerfile-path "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-dockerfile-computed-dockerfile-path: $(fn-builder-dockerfile-computed-dockerfile-path "$APP")"
|
||||
"--builder-dockerfile-global-dockerfile-path: $(fn-builder-dockerfile-global-dockerfile-path "$APP")"
|
||||
"--builder-dockerfile-dockerfile-path: $(fn-builder-dockerfile-dockerfile-path "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-dockerfile"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-dockerfile information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-dockerfile information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-dockerfile information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-dockerfile plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -78,7 +78,7 @@ trigger-builder-herokuish-builder-build() {
|
||||
fn-builder-herokuish-ensure-cache "$APP"
|
||||
if ! CID=$("$DOCKER_BIN" container create "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -v "cache-$APP:/cache" --env=CACHE_PATH=/cache "${ARG_ARRAY[@]}" "$IMAGE" /build); then
|
||||
plugn trigger scheduler-register-retired "$APP" "$CID"
|
||||
dokku_log_warn "Failure during app build"
|
||||
dokku_log_warn "Failure creating container during app build"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -86,14 +86,14 @@ trigger-builder-herokuish-builder-build() {
|
||||
"$DOCKER_BIN" container start "$CID" >/dev/null || DOKKU_CONTAINER_EXIT_CODE=$?
|
||||
if ! "$DOCKER_BIN" container attach "$CID"; then
|
||||
plugn trigger scheduler-register-retired "$APP" "$CID"
|
||||
dokku_log_warn "Failure during app build"
|
||||
dokku_log_warn "Failure starting container during app build"
|
||||
return 1
|
||||
fi
|
||||
|
||||
DOKKU_CONTAINER_EXIT_CODE="$("$DOCKER_BIN" container wait "$CID" 2>/dev/null || echo "$DOKKU_CONTAINER_EXIT_CODE")"
|
||||
if [[ "$DOKKU_CONTAINER_EXIT_CODE" -ne 0 ]]; then
|
||||
plugn trigger scheduler-register-retired "$APP" "$CID"
|
||||
dokku_log_warn "Failure during app build"
|
||||
dokku_log_warn "Failure attaching to container during app build"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-herokuish-report() {
|
||||
declare desc="displays a builder-herokuish report for one or more apps"
|
||||
declare cmd="builder-herokuish:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-herokuish-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-herokuish-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-herokuish-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-herokuish-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-herokuish-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-herokuish-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-herokuish-computed-allowed: $(fn-builder-herokuish-computed-allowed "$APP")"
|
||||
"--builder-herokuish-global-allowed: $(fn-builder-herokuish-global-allowed)"
|
||||
"--builder-herokuish-allowed: $(fn-builder-herokuish-allowed "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-herokuish-global-allowed: $(fn-builder-herokuish-global-allowed)"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-herokuish-computed-allowed: $(fn-builder-herokuish-computed-allowed "$APP")"
|
||||
"--builder-herokuish-global-allowed: $(fn-builder-herokuish-global-allowed)"
|
||||
"--builder-herokuish-allowed: $(fn-builder-herokuish-allowed "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-herokuish"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-herokuish information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-herokuish information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-herokuish information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-herokuish plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-lambda-report() {
|
||||
declare desc="displays a builder-lambda report for one or more apps"
|
||||
declare cmd="builder-lambda:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-lambda-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-lambda-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-lambda-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-lambda-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-lambda-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-lambda-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-lambda-computed-lambdayml-path: $(fn-builder-lambda-computed-lambdayml-path "$APP")"
|
||||
"--builder-lambda-global-lambdayml-path: $(fn-builder-lambda-global-lambdayml-path "$APP")"
|
||||
"--builder-lambda-lambdayml-path: $(fn-builder-lambda-lambdayml-path "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-lambda-global-lambdayml-path: $(fn-builder-lambda-global-lambdayml-path "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-lambda-computed-lambdayml-path: $(fn-builder-lambda-computed-lambdayml-path "$APP")"
|
||||
"--builder-lambda-global-lambdayml-path: $(fn-builder-lambda-global-lambdayml-path "$APP")"
|
||||
"--builder-lambda-lambdayml-path: $(fn-builder-lambda-lambdayml-path "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-lambda"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-lambda information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-lambda information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-lambda information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-lambda plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-nixpacks-report() {
|
||||
declare desc="displays a builder-nixpacks report for one or more apps"
|
||||
declare cmd="builder-nixpacks:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-nixpacks-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-nixpacks-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-nixpacks-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-nixpacks-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-nixpacks-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-nixpacks-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-nixpacks-computed-nixpackstoml-path: $(fn-builder-nixpacks-computed-nixpackstoml-path "$APP")"
|
||||
"--builder-nixpacks-global-nixpackstoml-path: $(fn-builder-nixpacks-global-nixpackstoml-path "$APP")"
|
||||
"--builder-nixpacks-nixpackstoml-path: $(fn-builder-nixpacks-nixpackstoml-path "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-nixpacks-global-nixpackstoml-path: $(fn-builder-nixpacks-global-nixpackstoml-path "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-nixpacks-computed-nixpackstoml-path: $(fn-builder-nixpacks-computed-nixpackstoml-path "$APP")"
|
||||
"--builder-nixpacks-global-nixpackstoml-path: $(fn-builder-nixpacks-global-nixpackstoml-path "$APP")"
|
||||
"--builder-nixpacks-nixpackstoml-path: $(fn-builder-nixpacks-nixpackstoml-path "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-nixpacks"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-nixpacks information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-nixpacks information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-nixpacks information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-nixpacks plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-null plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -20,7 +20,7 @@ trigger-builder-pack-docker-args-process-deploy() {
|
||||
|
||||
if [[ "$inject_launcher" == "true" ]]; then
|
||||
# without this, the command and arguments are passed as args to the default process type
|
||||
output="--entrypoint launcher "
|
||||
output=" --entrypoint launcher"
|
||||
fi
|
||||
|
||||
echo -n "$STDIN$output"
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-pack-report() {
|
||||
declare desc="displays a builder-pack report for one or more apps"
|
||||
declare cmd="builder-pack:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-pack-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-pack-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-pack-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-pack-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-pack-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-pack-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-pack-computed-projecttoml-path: $(fn-builder-pack-computed-projecttoml-path "$APP")"
|
||||
"--builder-pack-global-projecttoml-path: $(fn-builder-pack-global-projecttoml-path "$APP")"
|
||||
"--builder-pack-projecttoml-path: $(fn-builder-pack-projecttoml-path "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-pack-global-projecttoml-path: $(fn-builder-pack-global-projecttoml-path "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-pack-computed-projecttoml-path: $(fn-builder-pack-computed-projecttoml-path "$APP")"
|
||||
"--builder-pack-global-projecttoml-path: $(fn-builder-pack-global-projecttoml-path "$APP")"
|
||||
"--builder-pack-projecttoml-path: $(fn-builder-pack-projecttoml-path "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-pack"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-pack information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-pack information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-pack information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-pack plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -8,40 +8,66 @@ cmd-builder-railpack-report() {
|
||||
declare desc="displays a builder-railpack report for one or more apps"
|
||||
declare cmd="builder-railpack:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-builder-railpack-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-builder-railpack-report-single "$app" "$INFO_FLAG" | tee || true
|
||||
cmd-builder-railpack-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-builder-railpack-report-single "$APP" "$INFO_FLAG"
|
||||
cmd-builder-railpack-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-builder-railpack-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2"
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
verify_app_name "$APP"
|
||||
local flag_map=(
|
||||
"--builder-railpack-computed-railpackjson-path: $(fn-builder-railpack-computed-railpackjson-path "$APP")"
|
||||
"--builder-railpack-global-railpackjson-path: $(fn-builder-railpack-global-railpackjson-path "$APP")"
|
||||
"--builder-railpack-railpackjson-path: $(fn-builder-railpack-railpackjson-path "$APP")"
|
||||
)
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--builder-railpack-global-railpackjson-path: $(fn-builder-railpack-global-railpackjson-path "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--builder-railpack-computed-railpackjson-path: $(fn-builder-railpack-computed-railpackjson-path "$APP")"
|
||||
"--builder-railpack-global-railpackjson-path: $(fn-builder-railpack-global-railpackjson-path "$APP")"
|
||||
"--builder-railpack-railpackjson-path: $(fn-builder-railpack-railpackjson-path "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "builder-railpack"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
dokku_log_info2_quiet "${APP} builder-railpack information"
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global builder-railpack information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} builder-railpack information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder-railpack plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -3,14 +3,16 @@ package builder
|
||||
var (
|
||||
// DefaultProperties is a map of all valid builder properties with corresponding default property values
|
||||
DefaultProperties = map[string]string{
|
||||
"selected": "",
|
||||
"detected": "",
|
||||
"build-dir": "",
|
||||
"build-dir": "",
|
||||
"detected": "",
|
||||
"selected": "",
|
||||
"skip-cleanup": "",
|
||||
}
|
||||
|
||||
// GlobalProperties is a map of all valid global builder properties
|
||||
GlobalProperties = map[string]bool{
|
||||
"selected": true,
|
||||
"build-dir": true,
|
||||
"build-dir": true,
|
||||
"selected": true,
|
||||
"skip-cleanup": true,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/dokku/dokku/plugins/builder
|
||||
|
||||
go 1.25.5
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
|
||||
@@ -18,8 +18,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.0 h1:RQUBpLvfg3i7fjfG8rTcSWyMjVRfdhwrrfQhjYee4dQ=
|
||||
github.com/melbahja/goph v1.5.0/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
|
||||
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
|
||||
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
|
||||
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core builder plugin"
|
||||
version = "0.37.8"
|
||||
version = "0.38.1"
|
||||
[plugin.config]
|
||||
|
||||
@@ -6,18 +6,28 @@ import (
|
||||
|
||||
// ReportSingleApp is an internal function that displays the builder report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--builder-computed-selected": reportComputedSelected,
|
||||
"--builder-global-selected": reportGlobalSelected,
|
||||
"--builder-selected": reportSelected,
|
||||
"--builder-detected": reportDetected,
|
||||
"--builder-computed-build-dir": reportComputedBuildDir,
|
||||
"--builder-global-build-dir": reportGlobalBuildDir,
|
||||
"--builder-build-dir": reportBuildDir,
|
||||
var flags map[string]common.ReportFunc
|
||||
if appName == "--global" {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--builder-global-selected": reportGlobalSelected,
|
||||
"--builder-global-build-dir": reportGlobalBuildDir,
|
||||
}
|
||||
} else {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--builder-computed-selected": reportComputedSelected,
|
||||
"--builder-global-selected": reportGlobalSelected,
|
||||
"--builder-selected": reportSelected,
|
||||
"--builder-detected": reportDetected,
|
||||
"--builder-computed-build-dir": reportComputedBuildDir,
|
||||
"--builder-global-build-dir": reportGlobalBuildDir,
|
||||
"--builder-build-dir": reportBuildDir,
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
|
||||
@@ -21,11 +21,14 @@ func main() {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("builder:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
osArgs, infoFlag, flagErr := common.ParseReportArgs("builder", os.Args[2:])
|
||||
reportArgs, flagErr := common.ParseReportArgs("builder", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(osArgs)
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
err = builder.CommandReport(appName, *format, infoFlag)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = builder.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
case "set":
|
||||
args := flag.NewFlagSet("builder:set", flag.ExitOnError)
|
||||
|
||||
@@ -108,30 +108,21 @@ func TriggerInstall() error {
|
||||
return fmt.Errorf("Unable to install the builder plugin: %s", err.Error())
|
||||
}
|
||||
|
||||
apps, err := common.UnfilteredDokkuApps()
|
||||
if err != nil && !errors.Is(err, common.NoAppsExist) {
|
||||
return nil
|
||||
if err := common.MigrateConfigToProperties("builder", []common.MigrateConfigEntry{
|
||||
{
|
||||
ConfigVar: "DOKKU_APP_TYPE",
|
||||
Property: "detected",
|
||||
},
|
||||
{
|
||||
ConfigVar: "DOKKU_SKIP_CLEANUP",
|
||||
GlobalConfigVar: "DOKKU_SKIP_CLEANUP",
|
||||
Property: "skip-cleanup",
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, appName := range apps {
|
||||
if common.PropertyExists("builder", appName, "detected") {
|
||||
continue
|
||||
}
|
||||
|
||||
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_APP_TYPE"},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if results.StdoutContents() != "" {
|
||||
common.PropertyWrite("builder", appName, "detected", results.StdoutContents())
|
||||
}
|
||||
}
|
||||
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "install-builder-prune",
|
||||
})
|
||||
|
||||
|
||||
141
plugins/buildpacks/buildpacks_test.go
Normal file
141
plugins/buildpacks/buildpacks_test.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package buildpacks
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func setupTestEnvironment(t *testing.T) string {
|
||||
t.Helper()
|
||||
tmpDir, err := os.MkdirTemp("", "buildpacks-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
os.Setenv("DOKKU_LIB_ROOT", tmpDir)
|
||||
os.Setenv("PLUGIN_PATH", "/var/lib/dokku/plugins")
|
||||
os.Setenv("PLUGIN_ENABLED_PATH", "/var/lib/dokku/plugins/enabled")
|
||||
|
||||
return tmpDir
|
||||
}
|
||||
|
||||
func teardownTestEnvironment(tmpDir string) {
|
||||
os.RemoveAll(tmpDir)
|
||||
}
|
||||
|
||||
func TestValidBuildpackURL(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
|
||||
url, err := validBuildpackURL("")
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("Must specify a buildpack"))
|
||||
|
||||
url, err = validBuildpackURL("heroku/nodejs")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("https://github.com/heroku/heroku-buildpack-nodejs.git"))
|
||||
|
||||
url, err = validBuildpackURL("heroku/python")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("https://github.com/heroku/heroku-buildpack-python.git"))
|
||||
|
||||
url, err = validBuildpackURL("heroku-community/apt")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("https://github.com/heroku/heroku-buildpack-apt.git"))
|
||||
|
||||
url, err = validBuildpackURL("https://github.com/heroku/heroku-buildpack-nodejs.git")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("https://github.com/heroku/heroku-buildpack-nodejs.git"))
|
||||
|
||||
url, err = validBuildpackURL("https://github.com/heroku/heroku-buildpack-nodejs")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("https://github.com/heroku/heroku-buildpack-nodejs"))
|
||||
|
||||
url, err = validBuildpackURL("git://github.com/heroku/heroku-buildpack-nodejs.git")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(url).To(Equal("git://github.com/heroku/heroku-buildpack-nodejs.git"))
|
||||
|
||||
_, err = validBuildpackURL("nodejs")
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("Invalid buildpack specified"))
|
||||
|
||||
_, err = validBuildpackURL("/nodejs")
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("Invalid buildpack specified"))
|
||||
}
|
||||
|
||||
func TestGetBuildpacksEmpty(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
tmpDir := setupTestEnvironment(t)
|
||||
defer teardownTestEnvironment(tmpDir)
|
||||
|
||||
buildpacks, err := getBuildpacks("test-app")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(buildpacks).To(BeEmpty())
|
||||
}
|
||||
|
||||
func TestGetBuildpacksFromProperties(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
tmpDir := setupTestEnvironment(t)
|
||||
defer teardownTestEnvironment(tmpDir)
|
||||
|
||||
propDir := filepath.Join(tmpDir, "config", "buildpacks", "test-app")
|
||||
Expect(os.MkdirAll(propDir, 0755)).To(Succeed())
|
||||
Expect(os.WriteFile(filepath.Join(propDir, "buildpacks"), []byte("https://github.com/heroku/heroku-buildpack-nodejs.git\nhttps://github.com/heroku/heroku-buildpack-python.git\n"), 0644)).To(Succeed())
|
||||
|
||||
buildpacks, err := getBuildpacks("test-app")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(buildpacks).To(HaveLen(2))
|
||||
Expect(buildpacks[0]).To(Equal("https://github.com/heroku/heroku-buildpack-nodejs.git"))
|
||||
Expect(buildpacks[1]).To(Equal("https://github.com/heroku/heroku-buildpack-python.git"))
|
||||
}
|
||||
|
||||
func TestGetBuildpacksFromAppJSON(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
tmpDir := setupTestEnvironment(t)
|
||||
defer teardownTestEnvironment(tmpDir)
|
||||
|
||||
appJSONDir := filepath.Join(tmpDir, "data", "app-json", "test-app")
|
||||
Expect(os.MkdirAll(appJSONDir, 0755)).To(Succeed())
|
||||
Expect(os.WriteFile(filepath.Join(appJSONDir, "app.json"), []byte(`{"buildpacks": [{"url": "https://github.com/heroku/heroku-buildpack-nodejs.git"}]}`), 0644)).To(Succeed())
|
||||
|
||||
buildpacks, err := getBuildpacks("test-app")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(buildpacks).To(HaveLen(1))
|
||||
Expect(buildpacks[0]).To(Equal("https://github.com/heroku/heroku-buildpack-nodejs.git"))
|
||||
}
|
||||
|
||||
func TestGetBuildpacksPropertiesOverrideAppJSON(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
tmpDir := setupTestEnvironment(t)
|
||||
defer teardownTestEnvironment(tmpDir)
|
||||
|
||||
propDir := filepath.Join(tmpDir, "config", "buildpacks", "test-app")
|
||||
Expect(os.MkdirAll(propDir, 0755)).To(Succeed())
|
||||
Expect(os.WriteFile(filepath.Join(propDir, "buildpacks"), []byte("https://github.com/heroku/heroku-buildpack-ruby.git\n"), 0644)).To(Succeed())
|
||||
|
||||
appJSONDir := filepath.Join(tmpDir, "data", "app-json", "test-app")
|
||||
Expect(os.MkdirAll(appJSONDir, 0755)).To(Succeed())
|
||||
Expect(os.WriteFile(filepath.Join(appJSONDir, "app.json"), []byte(`{"buildpacks": [{"url": "https://github.com/heroku/heroku-buildpack-nodejs.git"}]}`), 0644)).To(Succeed())
|
||||
|
||||
buildpacks, err := getBuildpacks("test-app")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(buildpacks).To(HaveLen(1))
|
||||
Expect(buildpacks[0]).To(Equal("https://github.com/heroku/heroku-buildpack-ruby.git"))
|
||||
}
|
||||
|
||||
func TestGetBuildpacksAppJSONEmptyArray(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
tmpDir := setupTestEnvironment(t)
|
||||
defer teardownTestEnvironment(tmpDir)
|
||||
|
||||
appJSONDir := filepath.Join(tmpDir, "data", "app-json", "test-app")
|
||||
Expect(os.MkdirAll(appJSONDir, 0755)).To(Succeed())
|
||||
Expect(os.WriteFile(filepath.Join(appJSONDir, "app.json"), []byte(`{"buildpacks": []}`), 0644)).To(Succeed())
|
||||
|
||||
buildpacks, err := getBuildpacks("test-app")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(buildpacks).To(BeEmpty())
|
||||
}
|
||||
@@ -8,9 +8,50 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
appjson "github.com/dokku/dokku/plugins/app-json"
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// getBuildpacks returns the buildpacks for a given app
|
||||
// the order of application is:
|
||||
// 1. .buildpacks: if it exists, use it
|
||||
// 2. app.json: if it exists and has buildpacks, use them
|
||||
// 3. buildpack properties: if they exist, use them
|
||||
// 4. buildpack detection
|
||||
func getBuildpacks(appName string) ([]string, error) {
|
||||
buildpacks, err := common.PropertyListGet("buildpacks", appName, "buildpacks")
|
||||
if err != nil {
|
||||
return buildpacks, err
|
||||
}
|
||||
|
||||
if len(buildpacks) > 0 {
|
||||
return buildpacks, nil
|
||||
}
|
||||
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "git-get-property",
|
||||
Args: []string{appName, "source-image"},
|
||||
})
|
||||
if results.StdoutContents() != "" {
|
||||
return buildpacks, nil
|
||||
}
|
||||
|
||||
appJSON, err := appjson.GetAppJSON(appName)
|
||||
if err != nil {
|
||||
return buildpacks, err
|
||||
}
|
||||
|
||||
if len(appJSON.Buildpacks) == 0 {
|
||||
return buildpacks, nil
|
||||
}
|
||||
|
||||
for _, b := range appJSON.Buildpacks {
|
||||
buildpacks = append(buildpacks, b.URL)
|
||||
}
|
||||
|
||||
return buildpacks, nil
|
||||
}
|
||||
|
||||
func rewriteBuildpacksFile(sourceWorkDir string) error {
|
||||
buildpacksPath := filepath.Join(sourceWorkDir, ".buildpacks")
|
||||
if !common.FileExists(buildpacksPath) {
|
||||
@@ -27,6 +68,10 @@ func rewriteBuildpacksFile(sourceWorkDir string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(buildpack, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
buildpack, err = validBuildpackURL(buildpack)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to parse .buildpacks file, line %d: %s", i, err)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user