Compare commits
482 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
213d89b1e4 | ||
|
|
76b9f03818 | ||
|
|
a0bae9b0a9 | ||
|
|
21ed5fb738 | ||
|
|
4ae48c6ea0 | ||
|
|
b8929712d4 | ||
|
|
ff00bcb218 | ||
|
|
580aa892de | ||
|
|
f9183bbff2 | ||
|
|
5dbb2951bb | ||
|
|
4346a18194 | ||
|
|
0cea642dd9 | ||
|
|
f86b2cb1cb | ||
|
|
641be4334d | ||
|
|
e13b9d33f9 | ||
|
|
bec6b9f14a | ||
|
|
f896c731f2 | ||
|
|
3bb21b6987 | ||
|
|
e9160db769 | ||
|
|
f4d27be7a6 | ||
|
|
411cb88796 | ||
|
|
25d96f3f23 | ||
|
|
da92b3721f | ||
|
|
34b19f99b9 | ||
|
|
214c8cc2e1 | ||
|
|
94c43f6dd8 | ||
|
|
59d880e3f9 | ||
|
|
14013c8a7c | ||
|
|
3493869fa4 | ||
|
|
d003bfaf0e | ||
|
|
b08f00a105 | ||
|
|
c8101aa2a7 | ||
|
|
a561a5069e | ||
|
|
5d802e3cf4 | ||
|
|
fec872711a | ||
|
|
44dd5e9eea | ||
|
|
64b104a2a3 | ||
|
|
ee11fa2c63 | ||
|
|
84f744f61f | ||
|
|
c7b8e50d8e | ||
|
|
a5603744ab | ||
|
|
b0f5b764bd | ||
|
|
5a517dde30 | ||
|
|
3bf6c72451 | ||
|
|
d635a49d6f | ||
|
|
5925efedc7 | ||
|
|
035c021485 | ||
|
|
a3538bbb66 | ||
|
|
2b5d2e10ea | ||
|
|
bc5acce55e | ||
|
|
fd9e06d56b | ||
|
|
f9186ca1fd | ||
|
|
e30b6d2ac4 | ||
|
|
6ce48992f3 | ||
|
|
3feedd8786 | ||
|
|
99b949da4a | ||
|
|
90e6be84a2 | ||
|
|
aee447b384 | ||
|
|
56313edd32 | ||
|
|
aa6a2e8cc3 | ||
|
|
631620b1df | ||
|
|
866c4a2939 | ||
|
|
b45c86dcc9 | ||
|
|
64a5b1517a | ||
|
|
79921d75d6 | ||
|
|
9517353df4 | ||
|
|
09c17e1653 | ||
|
|
80ebaada77 | ||
|
|
f9de91fc4b | ||
|
|
961bbca6d8 | ||
|
|
955f0a8f6b | ||
|
|
f960dc5856 | ||
|
|
ff529543a9 | ||
|
|
cdb6c1c62e | ||
|
|
6a01a4f731 | ||
|
|
ac95225809 | ||
|
|
953b6e0a16 | ||
|
|
c3a30a8879 | ||
|
|
75c0659dcf | ||
|
|
5cf86cb6a7 | ||
|
|
51c9bd23da | ||
|
|
bf2cfe1886 | ||
|
|
647af7bb0e | ||
|
|
caa60fa1ef | ||
|
|
3c8cba08e5 | ||
|
|
ee3956478c | ||
|
|
748b66f669 | ||
|
|
0b567ff1b9 | ||
|
|
82fa8de766 | ||
|
|
0758b2c738 | ||
|
|
0da6527ef6 | ||
|
|
055f803f57 | ||
|
|
5286612618 | ||
|
|
b2320121fe | ||
|
|
5df399273a | ||
|
|
8742f688e3 | ||
|
|
3d3c95545c | ||
|
|
052ba1fcfc | ||
|
|
6f178afcb6 | ||
|
|
e795ec97b9 | ||
|
|
35d249bb60 | ||
|
|
357e12bd83 | ||
|
|
e70f7918a3 | ||
|
|
4e8206501e | ||
|
|
82d1f8e11c | ||
|
|
9163f0d0a6 | ||
|
|
9378100bed | ||
|
|
cdcf1fc669 | ||
|
|
2bdf7b59c9 | ||
|
|
76b033234f | ||
|
|
f3bdd7e4ec | ||
|
|
3e7f9fdf5b | ||
|
|
0acdce85d9 | ||
|
|
c49e4d2f25 | ||
|
|
a56a4b96e9 | ||
|
|
691fd4bed2 | ||
|
|
54c94a8b17 | ||
|
|
8b24336369 | ||
|
|
5b3fc362a0 | ||
|
|
d52c4e45f4 | ||
|
|
ac4e332960 | ||
|
|
f86ed14668 | ||
|
|
d4832baf88 | ||
|
|
54907559b0 | ||
|
|
ca4bf93f24 | ||
|
|
f9ac9cc13c | ||
|
|
11115c4b94 | ||
|
|
ee1b6d1fef | ||
|
|
b31a8ddb19 | ||
|
|
a8bc49a1c3 | ||
|
|
1708276aff | ||
|
|
a147017e43 | ||
|
|
c41e81e008 | ||
|
|
a531cf1ab7 | ||
|
|
0042fc3265 | ||
|
|
af5421adf0 | ||
|
|
104f36b408 | ||
|
|
b0ced77d1e | ||
|
|
f7f31a5c8a | ||
|
|
55753a822b | ||
|
|
c1c5afdcbe | ||
|
|
0ac7c6d8d7 | ||
|
|
336c351d87 | ||
|
|
447b7d1e9c | ||
|
|
c61c7354d5 | ||
|
|
ca5e8201fc | ||
|
|
4001f318a6 | ||
|
|
fee155a0a6 | ||
|
|
536349990e | ||
|
|
f6439d3641 | ||
|
|
3544bdd308 | ||
|
|
6cb5d472e5 | ||
|
|
a4e6d06fd1 | ||
|
|
b4e3d85024 | ||
|
|
282b2df71a | ||
|
|
d00a7d741a | ||
|
|
a9b2f56ee8 | ||
|
|
b096d0f131 | ||
|
|
f6448cef2c | ||
|
|
2b963884b4 | ||
|
|
cecd07d914 | ||
|
|
436825b782 | ||
|
|
460d92e21c | ||
|
|
12c00b57fc | ||
|
|
db74bd4b5e | ||
|
|
5c12d7733d | ||
|
|
ef36fe0a53 | ||
|
|
fce9cf8bc7 | ||
|
|
71fd53d2e1 | ||
|
|
ada4a82d77 | ||
|
|
b8b0b527b0 | ||
|
|
b30eb48444 | ||
|
|
b32fb47e48 | ||
|
|
e4695dc99a | ||
|
|
7898f98488 | ||
|
|
3a36de7349 | ||
|
|
4551f258b2 | ||
|
|
162af06c80 | ||
|
|
da52b8133d | ||
|
|
bc6f2da13a | ||
|
|
ebdd5f2b2f | ||
|
|
7d73cf78c4 | ||
|
|
c45b95fc4d | ||
|
|
db2cbd802f | ||
|
|
22f1fcdc1f | ||
|
|
c2f927cd50 | ||
|
|
541464b9c8 | ||
|
|
993d727dcb | ||
|
|
228b6de482 | ||
|
|
bdc77c9706 | ||
|
|
90e5903760 | ||
|
|
d121eb982c | ||
|
|
2796733119 | ||
|
|
af614cd049 | ||
|
|
194bfc6f12 | ||
|
|
95b97defb7 | ||
|
|
b66df28d96 | ||
|
|
d0588698f5 | ||
|
|
41afd7646e | ||
|
|
029e98673f | ||
|
|
eb8316d3a8 | ||
|
|
f1e2f41bd9 | ||
|
|
59c1bef87b | ||
|
|
ff1296859b | ||
|
|
3a845f4d14 | ||
|
|
3ddce21aef | ||
|
|
cdce68f8a2 | ||
|
|
74dc94bad2 | ||
|
|
9123d14f3c | ||
|
|
66eb1340f5 | ||
|
|
822b7dddcd | ||
|
|
4eee229bbc | ||
|
|
7b515ea129 | ||
|
|
bd748052a1 | ||
|
|
2c274217de | ||
|
|
2a4393a63a | ||
|
|
cc0843391f | ||
|
|
a553f04966 | ||
|
|
9adf6e5f36 | ||
|
|
235078f111 | ||
|
|
392ac73d33 | ||
|
|
4f4fed7101 | ||
|
|
dbac12e9f1 | ||
|
|
93f87a0f07 | ||
|
|
d00aaf3ff3 | ||
|
|
e78d3bcc78 | ||
|
|
33dd8005dd | ||
|
|
90aa64e7e3 | ||
|
|
f4213a4bf5 | ||
|
|
253d47ecf5 | ||
|
|
0b93488006 | ||
|
|
9decf16ea1 | ||
|
|
2df0791fcd | ||
|
|
6eb8b8632c | ||
|
|
a70728f61e | ||
|
|
25abd38387 | ||
|
|
2974830e8f | ||
|
|
2c3f29daca | ||
|
|
38de83eabf | ||
|
|
01268ebad9 | ||
|
|
2cf2846c6b | ||
|
|
47c8141148 | ||
|
|
b8f94dfa7f | ||
|
|
4efe0eb9fd | ||
|
|
a6cfe3a2d1 | ||
|
|
390fe2b35a | ||
|
|
a5ee710496 | ||
|
|
1706729cfe | ||
|
|
51dc7799d0 | ||
|
|
07d301775e | ||
|
|
0619338607 | ||
|
|
902b7f6af4 | ||
|
|
25f87164ce | ||
|
|
67ce12b973 | ||
|
|
5d212f3195 | ||
|
|
05ffccd7e7 | ||
|
|
5dfda450d9 | ||
|
|
a7119ba693 | ||
|
|
870b93c8e3 | ||
|
|
48594ca0a4 | ||
|
|
5e279074fd | ||
|
|
5f0c5a5a4f | ||
|
|
983c462904 | ||
|
|
bc8adfa6e2 | ||
|
|
eb17a383c6 | ||
|
|
368a6999c9 | ||
|
|
1e7df47feb | ||
|
|
39f15930a0 | ||
|
|
a8fd9122fe | ||
|
|
09ee789849 | ||
|
|
117a9b43f9 | ||
|
|
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 | ||
|
|
c7afc0523d | ||
|
|
915172c0c5 | ||
|
|
24f460f5d3 | ||
|
|
1308e21947 | ||
|
|
2745e46054 | ||
|
|
f3e29c7c94 | ||
|
|
ddf470282e | ||
|
|
dcce09f19f | ||
|
|
fc7ddf34ba | ||
|
|
7529d8cb08 | ||
|
|
20f2100d46 | ||
|
|
5bf82d2585 | ||
|
|
2993fa800c | ||
|
|
08596c9648 | ||
|
|
b0b11bcf26 | ||
|
|
44dbbe6a34 | ||
|
|
5a787af3ae | ||
|
|
2b0f96dc1a | ||
|
|
8240096dda |
3
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -1,7 +1,8 @@
|
||||
---
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
labels: ["needs: investigation", "type: bug"]
|
||||
labels: ["needs: investigation"]
|
||||
type: Bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
10
.github/actions/build-image/action.yml
vendored
10
.github/actions/build-image/action.yml
vendored
@@ -13,19 +13,25 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: download packages
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: build
|
||||
path: build
|
||||
|
||||
- name: set up docker buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: build docker image
|
||||
shell: bash
|
||||
run: |
|
||||
docker buildx build \
|
||||
--load \
|
||||
--progress plain \
|
||||
--tag "dokku/dokku:latest" \
|
||||
.
|
||||
|
||||
- name: smoke test image
|
||||
shell: bash
|
||||
run: |
|
||||
make test-image-healthcheck IMAGE_TAG=dokku/dokku:latest
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -239,5 +239,5 @@ jobs:
|
||||
with:
|
||||
check_name: Unit Test Results
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
junit_files: test-results/**/*.xml
|
||||
files: test-results/**/*.xml
|
||||
comment_mode: "off"
|
||||
|
||||
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: 'type: dependencies'
|
||||
1
.github/workflows/lint.yml
vendored
1
.github/workflows/lint.yml
vendored
@@ -45,6 +45,7 @@ jobs:
|
||||
packer:
|
||||
name: packer
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event.pull_request.user.login != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
14
Dockerfile
14
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 \
|
||||
@@ -41,6 +45,7 @@ RUN mkdir -p /etc/apt/keyrings \
|
||||
&& echo "dokku dokku/hostname string $DOKKU_HOSTNAME" | debconf-set-selections \
|
||||
&& echo "dokku dokku/skip_key_file boolean $DOKKU_SKIP_KEY_FILE" | debconf-set-selections \
|
||||
&& echo "dokku dokku/vhost_enable boolean $DOKKU_VHOST_ENABLE" | debconf-set-selections \
|
||||
&& echo "dokku dokku/install_default_site boolean true" | debconf-set-selections \
|
||||
&& curl -sSL https://packagecloud.io/dokku/dokku/gpgkey | apt-key add - \
|
||||
&& echo "deb https://packagecloud.io/dokku/dokku/ubuntu/ noble main" | tee /etc/apt/sources.list.d/dokku.list \
|
||||
&& mkdir -p /etc/nginx/ \
|
||||
@@ -77,3 +82,6 @@ RUN \
|
||||
&& rm -f /usr/local/openresty/nginx/conf/sites-enabled/default /usr/share/openresty/html/index.html \
|
||||
&& sed -i '/imklog/d' /etc/rsyslog.conf \
|
||||
&& rm -f /var/log/btmp /var/log/wtmp /var/log/*log /var/log/apt/* /var/log/dokku/*.log /var/log/nginx/* /var/log/openresty/*
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5m --retries=3 \
|
||||
CMD curl -fsS http://127.0.0.1:18080/_dokku/health || exit 1
|
||||
|
||||
469
HISTORY.md
469
HISTORY.md
@@ -1,5 +1,474 @@
|
||||
# History
|
||||
|
||||
## 0.38.15
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.15/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.15 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8718: @josegonzalez Persist scheduler-k3s chart overrides as JSON maps
|
||||
|
||||
### Other
|
||||
|
||||
- #8720: @josegonzalez Persist scheduler-k3s annotations and labels as JSON maps
|
||||
|
||||
## 0.38.14
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.14/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.14 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### New Features
|
||||
|
||||
- #8716: @josegonzalez Add scheduler-k3s annotations:report and labels:report
|
||||
- #8715: @josegonzalez Add scheduler-k3s:charts:set and :charts:report
|
||||
|
||||
## 0.38.13
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.13/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.13 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8713: @josegonzalez Make storage:mount upsert the existing attachment
|
||||
|
||||
### New Features
|
||||
|
||||
- #8714: @josegonzalez Expose per-attachment fields in storage:report
|
||||
- #8712: @josegonzalez Expose attachment readonly and volume_options in storage:list json
|
||||
- #8711: @josegonzalez Add --volume-options flag to storage:mount
|
||||
|
||||
## 0.38.12
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.12/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.12 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8706: @josegonzalez Align apps:set/apps:report with what dokku actually reads
|
||||
|
||||
## 0.38.11
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.11/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.11 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8704: @josegonzalez Pass storage entry basename to chown-storage-dir
|
||||
|
||||
## 0.38.10
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.10/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.10 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### New Features
|
||||
|
||||
- #8702: @josegonzalez Prompt for confirmation on storage:destroy
|
||||
|
||||
### Tests
|
||||
|
||||
- #8698: @dependabot[bot] chore(deps-dev): bump org.apache.maven.plugins:maven-dependency-plugin from 3.10.0 to 3.11.0 in /tests/apps/java
|
||||
|
||||
## 0.38.9
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.9/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.9 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### New Features
|
||||
|
||||
- #8697: @josegonzalez Split openresty report into raw/computed/global
|
||||
|
||||
### Refactors
|
||||
|
||||
- #8696: @josegonzalez Treat empty ps restart-policy as an unset
|
||||
|
||||
## 0.38.8
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.8/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.8 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8690: @josegonzalez Unset bind-all-interfaces on empty value
|
||||
- #8689: @josegonzalez Expose remaining settable properties via :report
|
||||
|
||||
### New Features
|
||||
|
||||
- #8692: @Mordred Enable compression middleware for traefik when using scheduler-k3s
|
||||
- #8691: @josegonzalez Align Go-plugin :report JSON keys with bash-strip convention
|
||||
- #8688: @josegonzalez Promote registry image-repo-template to app + global
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8693: @dependabot[bot] chore(deps): bump helm.sh/helm/v3 from 3.20.2 to 3.21.0 in /plugins/scheduler-k3s
|
||||
|
||||
## 0.38.7
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.7/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.7 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
- #8672: @josegonzalez Prevent host shell injection from app.json cron commands
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8669: @josegonzalez Recover deployed image from registry on local miss
|
||||
- #8679: @josegonzalez Align ps/cron :report --global keys with plugin convention
|
||||
- #8678: @josegonzalez Split openresty report keys into global and computed pairs
|
||||
- #8676: @immanuwell Use SYSTEM for shfmt Darwin detection
|
||||
|
||||
### New Features
|
||||
|
||||
- #8677: @josegonzalez Warn on deprecated listen http2 in custom nginx templates
|
||||
|
||||
### Tests
|
||||
|
||||
- #8683: @dependabot[bot] chore(deps-dev): bump heroku/heroku-buildpack-php from 290 to 291 in /tests/apps/php
|
||||
- #8671: @josegonzalez Qualify scheduler-k3s ingressroute kubectl lookups
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8682: @dependabot[bot] chore(deps): bump k8s.io/apimachinery from 0.36.0 to 0.36.1 in /plugins/scheduler-k3s
|
||||
- #8681: @dependabot[bot] chore(deps): bump soupsieve from 2.8.3 to 2.8.4 in /docs/_build
|
||||
|
||||
### Other
|
||||
|
||||
- #8680: @josegonzalez Split more report global keys into raw and computed
|
||||
|
||||
## 0.38.6
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.6/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.6 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8633: @Mordred Correctly redirect http traffic to https when using scheduler-k3s
|
||||
- #8665: @josegonzalez Clarify byte-preserving behavior of config:set --encoded
|
||||
- #8666: @josegonzalez Depend on cron | cron-daemon to allow alternatives
|
||||
- #8638: @josegonzalez Support --global on cron:set
|
||||
|
||||
### Refactors
|
||||
|
||||
- #8668: @josegonzalez Hash scheduler-k3s cron-id label to fit Kubernetes' 63-byte cap
|
||||
- #8664: @josegonzalez Convert filesystem migration markers to plugin properties
|
||||
|
||||
### Documentation
|
||||
|
||||
- #8645: @zenspider Removed outdated warning about dokku-update not being able to upgrade to specific versions.
|
||||
|
||||
### Tests
|
||||
|
||||
- #8667: @josegonzalez Rename logs:report vector key test and guard old keys
|
||||
- #8662: @dependabot[bot] chore(deps): bump qs from 6.15.0 to 6.15.2 in /tests/apps/checks-root
|
||||
- #8661: @dependabot[bot] chore(deps): bump sass from 1.99.0 to 1.100.0 in /tests/apps/multi
|
||||
- #8658: @dependabot[bot] chore(deps-dev): bump heroku/heroku-buildpack-php from 288 to 290 in /tests/apps/php
|
||||
- #8657: @dependabot[bot] chore(deps): bump slim/slim from 4.15.1 to 4.15.2 in /tests/apps/php
|
||||
- #8654: @dependabot[bot] chore(deps): bump ruby from 4.0.4 to 4.0.5 in /tests/apps/dockerfile-entrypoint
|
||||
- #8642: @dependabot[bot] chore(deps): bump google.golang.org/grpc from 1.81.0 to 1.81.1 in /tests/apps/gogrpc
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8652: @dependabot[bot] chore(deps): bump github.com/onsi/gomega from 1.40.0 to 1.41.0 in /plugins/common
|
||||
- #8663: @dokku-bot chore: bump herokuish to 0.11.13
|
||||
- #8646: @dokku-bot chore: bump pack to 0.40.6
|
||||
- #8659: @dependabot[bot] chore(deps): bump golang.org/x/crypto from 0.51.0 to 0.52.0 in /plugins/common
|
||||
- #8660: @dependabot[bot] chore(deps): bump click from 8.4.0 to 8.4.1 in /docs/_build
|
||||
- #8655: @dependabot[bot] chore(deps): bump github.com/containerd/containerd from 1.7.30 to 1.7.32 in /plugins/scheduler-k3s
|
||||
- #8651: @dependabot[bot] chore(deps): bump click from 8.3.3 to 8.4.0 in /docs/_build
|
||||
- #8649: @dependabot[bot] chore(deps): bump github.com/onsi/gomega from 1.40.0 to 1.41.0 in /plugins/buildpacks
|
||||
- #8650: @dependabot[bot] chore(deps): bump github.com/onsi/gomega from 1.40.0 to 1.41.0 in /plugins/config
|
||||
- #8648: @dependabot[bot] chore(deps): bump zipp from 3.23.1 to 4.1.0 in /docs/_build
|
||||
- #8644: @dokku-bot chore: bump pack to 0.40.5
|
||||
- #8641: @dependabot[bot] chore(deps): bump traefik from v3.7.0 to v3.7.1 in /plugins/traefik-vhosts
|
||||
- #8634: @dependabot[bot] chore(deps): bump pymdown-extensions from 10.21.2 to 10.21.3 in /docs/_build
|
||||
|
||||
### Other
|
||||
|
||||
- #8640: @josegonzalez Split report global keys into raw and computed
|
||||
|
||||
## 0.38.5
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.5/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.5 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8627: @josegonzalez Preserve explicit https:443 port mappings on cert update
|
||||
|
||||
### New Features
|
||||
|
||||
- #8629: @josegonzalez Attach vector container to additional docker networks
|
||||
- #8624: @josegonzalez Expose certs-set and certs-remove plugin triggers
|
||||
- #8626: @josegonzalez Split caddy report tls-internal into raw, computed, and global
|
||||
|
||||
### Tests
|
||||
|
||||
- #8620: @dependabot[bot] chore(deps-dev): bump heroku/heroku-buildpack-php from 287 to 288 in /tests/apps/php
|
||||
- #8621: @dependabot[bot] chore(deps): bump ruby from 4.0.3 to 4.0.4 in /tests/apps/dockerfile-entrypoint
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8622: @dependabot[bot] chore(deps): bump k8s.io/kubernetes from 1.36.0 to 1.36.1 in /plugins/scheduler-k3s
|
||||
|
||||
## 0.38.4
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.4/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.4 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8615: @josegonzalez Reject per-app sets for openresty global-only properties
|
||||
- #8613: @josegonzalez Expose raw deploy-branch and keep-git-dir in git:report
|
||||
- #8549: @josegonzalez Route CNB images through launcher on scheduler-k3s
|
||||
|
||||
### New Features
|
||||
|
||||
- #8614: @josegonzalez Split scheduler-docker-local report into raw, computed, and global
|
||||
|
||||
### Documentation
|
||||
|
||||
- #8603: @cheif Add `dokku-http-oauth` to community plugins
|
||||
|
||||
### Tests
|
||||
|
||||
- #8618: @josegonzalez Isolate scheduler-k3s registry tags per bats file
|
||||
- #8616: @josegonzalez Migrate from junit_files to files in EnricoMi/publish-unit-test-result-action
|
||||
- #8617: @josegonzalez Upgrade actions in shared build-image compose action
|
||||
- #8609: @josegonzalez Skip packer lint job on dependabot PRs
|
||||
- #8604: @dependabot[bot] chore(deps): bump python from 3.14.3-bookworm to 3.15.0b1-bookworm in /tests/apps/dockerfile-release
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8606: @dependabot[bot] chore(deps): bump golang.org/x/crypto from 0.50.0 to 0.51.0 in /plugins/common
|
||||
- #8608: @dependabot[bot] chore(deps): bump github.com/traefik/traefik/v2 from 2.11.45 to 2.11.46 in /plugins/scheduler-k3s
|
||||
- #8607: @dependabot[bot] chore(deps): bump dokku/openresty-docker-proxy from 0.10.0 to 0.11.0 in /plugins/openresty-vhosts
|
||||
- #8605: @dependabot[bot] chore(deps): bump python from 3.14.3-alpine to 3.15.0b1-alpine in /docs/_build
|
||||
|
||||
## 0.38.3
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.3/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.3 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8602: @josegonzalez Reject per-app sets for global-only proxy properties
|
||||
- #8601: @josegonzalez Rename app-json:report flags to match property
|
||||
- #8600: @josegonzalez Report info-flag should not error when app undeployed
|
||||
|
||||
### New Features
|
||||
|
||||
- #8599: @josegonzalez Add docker healthcheck to dokku container
|
||||
|
||||
## 0.38.2
|
||||
|
||||
Install/update via the bootstrap script:
|
||||
|
||||
```shell
|
||||
wget -NP . https://dokku.com/install/v0.38.2/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.2 bash bootstrap.sh
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
- #8590: @josegonzalez Restrict app names to prevent command injection
|
||||
- #8591: @josegonzalez Harden archive extraction against symlink traversal
|
||||
- #8589: @josegonzalez Enforce 0600 permissions on .netrc credentials file
|
||||
- #8588: @josegonzalez Sanitize openresty include filenames to prevent eval injection
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #8593: @josegonzalez Gate ssl_reject_handshake behind nginx 1.19.4
|
||||
- #8578: @josegonzalez Reference SOURCECODE_WORK_DIR in builder core-post-extract
|
||||
|
||||
### Documentation
|
||||
|
||||
- #8592: @josegonzalez Add security section to release changelog
|
||||
- #8587: @vixalien Correct buildkit builder code block syntax
|
||||
- #8580: @othercorey Set issue type in bug report template
|
||||
|
||||
### Tests
|
||||
|
||||
- #8586: @josegonzalez Count assert_output_contains matches as fixed strings
|
||||
- #8581: @dependabot[bot] chore(deps): bump golang from 1.26.2 to 1.26.3 in /tests/apps/go-fail-predeploy
|
||||
- #8582: @dependabot[bot] chore(deps): bump golang from 1.26.2 to 1.26.3 in /tests/apps/gogrpc
|
||||
- #8584: @dependabot[bot] chore(deps): bump golang from 1.26.2 to 1.26.3 in /tests/apps/go-fail-postdeploy
|
||||
- #8583: @dependabot[bot] chore(deps): bump golang from 1.26.2 to 1.26.3 in /tests/apps/zombies-dockerfile-tini
|
||||
- #8585: @dependabot[bot] chore(deps): bump golang from 1.26.2 to 1.26.3 in /tests/apps/zombies-dockerfile-no-tini
|
||||
- #8574: @dependabot[bot] chore(deps): bump node from 25-alpine to 26-alpine in /tests/apps/dockerfile-noexpose
|
||||
- #8575: @dependabot[bot] chore(deps): bump node from 25-alpine to 26-alpine in /tests/apps/dockerfile-procfile-bad
|
||||
- #8577: @dependabot[bot] chore(deps): bump node from 25-alpine to 26-alpine in /tests/apps/dockerfile-app-json-formations
|
||||
- #8576: @dependabot[bot] chore(deps): bump node from 25-alpine to 26-alpine in /tests/apps/dockerfile
|
||||
- #8573: @dependabot[bot] chore(deps): bump node from 25-alpine to 26-alpine in /tests/apps/dockerfile-procfile
|
||||
|
||||
### Dependencies
|
||||
|
||||
- #8579: @josegonzalez Use type prefix for dokku-bot dependency label
|
||||
|
||||
## 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:
|
||||
|
||||
5
Makefile
5
Makefile
@@ -226,3 +226,8 @@ vagrant-acl-add:
|
||||
|
||||
vagrant-dokku:
|
||||
vagrant ssh -- "sudo -H -u root bash -c 'dokku $(RUN_ARGS)'"
|
||||
|
||||
IMAGE_TAG ?= dokku/dokku:latest
|
||||
|
||||
test-image-healthcheck:
|
||||
IMAGE_TAG=$(IMAGE_TAG) ./tests/image/healthcheck.sh
|
||||
|
||||
@@ -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.10/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.10 bash bootstrap.sh
|
||||
wget -NP . https://dokku.com/install/v0.38.15/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.15 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.6",
|
||||
"urls": {
|
||||
"amd64": "https://github.com/buildpacks/pack/releases/download/v0.40.6/pack-v0.40.6-linux.tgz",
|
||||
"arm64": "https://github.com/buildpacks/pack/releases/download/v0.40.6/pack-v0.40.6-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.13",
|
||||
"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.13/herokuish_0.11.13_linux_x86_64.tgz",
|
||||
"arm64": "https://github.com/gliderlabs/herokuish/releases/download/v0.11.13/herokuish_0.11.13_linux_x86_64.tgz"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -250,7 +250,7 @@ fn-repo-update-history-and-commit() {
|
||||
declare desc="Updates the history file and commits the changes"
|
||||
declare CURRENT_VERSION="$1" NEXT_VERSION="$2" IS_PATCH="$3"
|
||||
local PULL_REQUEST_ID TITLE AUTHOR TYPE CHANGELOG_TEXT
|
||||
local COMMIT_MESSAGE HISTORY HISTORY_CONTENTS HISTORY_BUG HISTORY_DEPENDENCY HISTORY_DEPRECATION HISTORY_DOCUMENTATION HISTORY_ENHANCEMENT HISTORY_BC_BREAK HISTORY_REFACTOR HISTORY_REMOVAL HISTORY_OTHER HISTORY_TESTS ISSUE_FILE
|
||||
local COMMIT_MESSAGE HISTORY HISTORY_CONTENTS HISTORY_BUG HISTORY_DEPENDENCY HISTORY_DEPRECATION HISTORY_DOCUMENTATION HISTORY_ENHANCEMENT HISTORY_BC_BREAK HISTORY_REFACTOR HISTORY_REMOVAL HISTORY_SECURITY HISTORY_OTHER HISTORY_TESTS ISSUE_FILE
|
||||
|
||||
pushd "$ROOT_DIR" >/dev/null
|
||||
|
||||
@@ -295,6 +295,8 @@ fn-repo-update-history-and-commit() {
|
||||
HISTORY_REFACTOR="${HISTORY_REFACTOR}"$'\n'"$CHANGELOG_TEXT"
|
||||
elif [[ "$TYPE" == "removal" ]]; then
|
||||
HISTORY_REMOVAL="${HISTORY_REMOVAL}"$'\n'"$CHANGELOG_TEXT"
|
||||
elif [[ "$TYPE" == "security" ]]; then
|
||||
HISTORY_SECURITY="${HISTORY_SECURITY}"$'\n'"$CHANGELOG_TEXT"
|
||||
elif [[ "$TYPE" == "tests" ]]; then
|
||||
HISTORY_TESTS="${HISTORY_TESTS}"$'\n'"$CHANGELOG_TEXT"
|
||||
else
|
||||
@@ -314,6 +316,11 @@ fn-repo-update-history-and-commit() {
|
||||
HISTORY="${HISTORY}"$'\n\n'"See the [${NEXT_VERSION} migration guide](/docs/appendices/${NEXT_VERSION}-migration-guide.md) for more information on migrating to ${NEXT_VERSION}."
|
||||
fi
|
||||
|
||||
if [[ "$HISTORY_SECURITY" ]]; then
|
||||
HISTORY="${HISTORY}"$'\n\n'"### Security"
|
||||
HISTORY="${HISTORY}"$'\n'"$HISTORY_SECURITY"
|
||||
fi
|
||||
|
||||
if [[ "$HISTORY_BC_BREAK" ]]; then
|
||||
HISTORY="${HISTORY}"$'\n\n'"### Backwards Compatibility Breaks"
|
||||
HISTORY="${HISTORY}"$'\n'"$HISTORY_BC_BREAK"
|
||||
|
||||
@@ -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
|
||||
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -1,9 +1,9 @@
|
||||
Package: dokku
|
||||
Version: 0.37.10
|
||||
Version: 0.38.15
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Depends: apache2-utils, locales, git, cpio, cron, curl, logrotate, man-db, netcat, sshcommand, docker-engine-cs (>= 19.03.0) | docker-engine (>= 19.03.0) | docker-io (>= 19.03.0) | docker.io (>= 19.03.0) | docker-ce (>= 19.03.0) | docker-ee (>= 19.03.0) | moby-engine, docker-compose-plugin | moby-compose | docker-compose, docker-buildx-plugin | moby-buildx | docker-buildx, docker-container-healthchecker, docker-image-labeler, lambda-builder, net-tools, netrc, parallel, procfile-util, rsync, dos2unix, unzip, util-linux
|
||||
Depends: apache2-utils, locales, git, cpio, cron | cron-daemon, curl, logrotate, man-db, netcat, sshcommand, docker-engine-cs (>= 19.03.0) | docker-engine (>= 19.03.0) | docker-io (>= 19.03.0) | docker.io (>= 19.03.0) | docker-ce (>= 19.03.0) | docker-ee (>= 19.03.0) | moby-engine, docker-compose-plugin | moby-compose | docker-compose, docker-buildx-plugin | moby-buildx | docker-buildx, docker-container-healthchecker, docker-image-labeler, lambda-builder, net-tools, netrc, parallel, procfile-util, rsync, dos2unix, unzip, util-linux
|
||||
Recommends: herokuish, bash-completion, dokku-update, dokku-event-listener
|
||||
Pre-Depends: gliderlabs-sigil, jq, nginx (>= 1.8.0) | openresty, bind9-dnsutils, debconf, plugn, sudo, python3, rsyslog
|
||||
Maintainer: Jose Diaz-Gonzalez <dokku@josediazgonzalez.com>
|
||||
|
||||
82
debian/postinst
vendored
82
debian/postinst
vendored
@@ -135,6 +135,85 @@ 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 nginx_bin nginx_version major minor patch
|
||||
nginx_bin="$(command -v nginx || true)"
|
||||
if [ -z "$nginx_bin" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
nginx_version="$("$nginx_bin" -v 2>&1 | cut -d'/' -f 2 | awk '{print $1}')"
|
||||
major="$(echo "$nginx_version" | awk -F. '{print $1}')"
|
||||
minor="$(echo "$nginx_version" | awk -F. '{print $2}')"
|
||||
patch="$(echo "$nginx_version" | awk -F. '{print $3}')"
|
||||
|
||||
# ssl_reject_handshake requires nginx >= 1.19.4; older nginx gets the
|
||||
# HTTP-only catch-all so the SSL listen lines do not require a cert.
|
||||
local default_vhost_basename="default-site.conf"
|
||||
if [ "${major:-0}" -lt 2 ]; then
|
||||
if [ "${major:-0}" -lt 1 ] || [ "${minor:-0}" -lt 19 ] || { [ "${minor:-0}" -eq 19 ] && [ "${patch:-0}" -lt 4 ]; }; then
|
||||
default_vhost_basename="default-site-legacy.conf"
|
||||
fi
|
||||
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_vhost_basename}"
|
||||
|
||||
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 +249,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
|
||||
|
||||
@@ -35,6 +35,9 @@ main() {
|
||||
|
||||
support-userns
|
||||
|
||||
rm -f /var/run/dokku/ready
|
||||
mkdir -p /var/run/dokku
|
||||
|
||||
if [[ ! -d /mnt/dokku ]]; then
|
||||
log-info "Creating missing /mnt/dokku"
|
||||
mkdir -p /mnt/dokku
|
||||
|
||||
16
docker/etc/nginx/conf.d/zz-dokku-health.conf
Normal file
16
docker/etc/nginx/conf.d/zz-dokku-health.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
# Internal health endpoint for the official dokku/dokku Docker image.
|
||||
# Bound to loopback so it is reachable only from inside the container
|
||||
# and never conflicts with user app vhosts on 80/443.
|
||||
server {
|
||||
listen 127.0.0.1:18080;
|
||||
server_name _;
|
||||
access_log off;
|
||||
default_type text/plain;
|
||||
|
||||
location = /_dokku/health {
|
||||
if (-f /var/run/dokku/ready) {
|
||||
return 200 "ok\n";
|
||||
}
|
||||
return 503 "not ready\n";
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,10 @@ if [[ "$1" -ne 0 ]]; then
|
||||
fi
|
||||
|
||||
echo "Done restoring dokku apps."
|
||||
exec sleep infinity
|
||||
|
||||
exit 0
|
||||
while ! (echo >/dev/tcp/127.0.0.1/22) >/dev/null 2>&1; do sleep 1; done
|
||||
while ! (echo >/dev/tcp/127.0.0.1/80) >/dev/null 2>&1; do sleep 1; done
|
||||
touch /var/run/dokku/ready
|
||||
echo "Dokku is ready."
|
||||
|
||||
exec sleep infinity
|
||||
|
||||
@@ -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)
|
||||
|
||||
2
docs/_build/Dockerfile
vendored
2
docs/_build/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM python:3.14.3-alpine
|
||||
FROM python:3.15.0b1-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
10
docs/_build/requirements.txt
vendored
10
docs/_build/requirements.txt
vendored
@@ -1,5 +1,5 @@
|
||||
beautifulsoup4==4.14.3
|
||||
click==8.3.3
|
||||
click==8.4.1
|
||||
ghp-import==2.1.0
|
||||
importlib-metadata==9.0.0
|
||||
Jinja2==3.1.6
|
||||
@@ -10,14 +10,14 @@ 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
|
||||
pymdown-extensions==10.21.3
|
||||
pyparsing==3.3.2
|
||||
python-dateutil==2.9.0.post0
|
||||
PyYAML==6.0.3
|
||||
pyyaml_env_tag==1.1
|
||||
six==1.17.0
|
||||
soupsieve==2.8.3
|
||||
soupsieve==2.8.4
|
||||
watchdog==6.0.0
|
||||
zipp==3.23.1
|
||||
zipp==4.1.0
|
||||
|
||||
197
docs/advanced-usage/builds.md
Normal file
197
docs/advanced-usage/builds.md
Normal file
@@ -0,0 +1,197 @@
|
||||
# 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.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `builds:report`. The JSON keys emitted by `builds:report --format json` are the same names with the leading `--builds-` stripped (e.g. `retention`, `global-retention`, `computed-retention`). Legacy keys with the `builds-` prefix (e.g. `builds-retention`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release. Status keys (`build-id`, `build-status`, etc.) have no plugin prefix and are unaffected.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `retention` | app + global | `20` | `--builds-retention`, `--builds-global-retention`, `--builds-computed-retention` | Number of recent build records kept per app; older finalized records are pruned at the end of each deploy |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `builds:report` but are not managed by `builds:set` - they are derived metadata recorded during the build:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--build-id` | Unique identifier of the most recent build for the app |
|
||||
| `--build-kind` | Whether the record was a `build` or a `deploy` |
|
||||
| `--build-status` | Display status (`running`, `succeeded`, `failed`, `canceled`, `abandoned`); computed at read time |
|
||||
| `--build-source` | Trigger that started the build (e.g. `git-hook`, `ps:rebuild`, `ps:restart`) |
|
||||
| `--build-pid` | PID of the build process |
|
||||
| `--build-started-at` | UNIX timestamp the build started |
|
||||
| `--build-finished-at` | UNIX timestamp the build finished |
|
||||
| `--build-exit-code` | Exit code of the build process |
|
||||
@@ -101,18 +101,20 @@ dokku app-json:report
|
||||
```
|
||||
=====> node-js-app app-json information
|
||||
App-json computed appjson path: app2.json
|
||||
App-json global appjson path: app.json
|
||||
App-json global appjson path:
|
||||
App-json appjson path: app2.json
|
||||
=====> python-sample app-json information
|
||||
App-json computed appjson path: app.json
|
||||
App-json global appjson path: app.json
|
||||
App-json global appjson path:
|
||||
App-json appjson path:
|
||||
=====> ruby-sample app-json information
|
||||
App-json computed appjson path: app.json
|
||||
App-json global appjson path: app.json
|
||||
App-json global appjson path:
|
||||
App-json appjson path:
|
||||
```
|
||||
|
||||
The `appjson-path` and `global-appjson-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-appjson-path` key holds the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default of `app.json`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -122,7 +124,7 @@ dokku app-json:report node-js-app
|
||||
```
|
||||
=====> node-js-app app-json information
|
||||
App-json computed appjson path: app2.json
|
||||
App-json global appjson path: app.json
|
||||
App-json global appjson path:
|
||||
App-json appjson path: app2.json
|
||||
```
|
||||
|
||||
|
||||
@@ -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,80 @@ 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
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following properties are recorded internally by the docker-options plugin and are not exposed via `docker-options:report`:
|
||||
|
||||
| Property | Scope | Description | Source |
|
||||
|---|---|---|---|
|
||||
| `migrated-from-files` | global | Global migration sentinel that records that the legacy `DOCKER_OPTIONS_<PHASE>` flat-file store has been drained into plugin properties | `plugins/docker-options/functions.go` writes `"true"` once the install-time migration runs |
|
||||
| `migrated-build` | per-app | Per-app marker recording that the app's legacy `DOCKER_OPTIONS_BUILD` file was drained into the `_default_.build` property list. Only set when the legacy file contained non-empty content | `plugins/docker-options/functions.go` writes `"true"` after the per-phase drain |
|
||||
| `migrated-deploy` | per-app | Per-app marker recording that the app's legacy `DOCKER_OPTIONS_DEPLOY` file was drained into the `_default_.deploy` property list. Only set when the legacy file contained non-empty content | `plugins/docker-options/functions.go` writes `"true"` after the per-phase drain |
|
||||
| `migrated-run` | per-app | Per-app marker recording that the app's legacy `DOCKER_OPTIONS_RUN` file was drained into the `_default_.run` property list. Only set when the legacy file contained non-empty content | `plugins/docker-options/functions.go` writes `"true"` after the per-phase drain |
|
||||
|
||||
@@ -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> [--force] # 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
|
||||
|
||||
@@ -44,9 +57,23 @@ dokku storage:list node-js-app --format json
|
||||
```
|
||||
[
|
||||
{
|
||||
"entry_name": "node-js-app",
|
||||
"host_path": "/var/lib/dokku/data/storage/node-js-app",
|
||||
"container_path": "/app/storage"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Each entry mirrors the underlying attachment. `readonly` (boolean) and `volume_options` (string) reflect `Attachment.Readonly` and `Attachment.VolumeOptions` directly and are only present when set, so external tooling can drift-detect attachments against the raw attachment fields. For example, a mount created with `--volume-options noexec,nosuid --volume-readonly` renders as:
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"entry_name": "node-js-data",
|
||||
"host_path": "/var/lib/dokku/data/storage/node-js-data",
|
||||
"container_path": "/app/storage",
|
||||
"volume_options": ""
|
||||
"readonly": true,
|
||||
"volume_options": "noexec,nosuid"
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -82,6 +109,8 @@ By default, permissions are set for usage with Herokuish buildpacks. These permi
|
||||
|
||||
Users deploying via Dockerfile will want to specify `--chown false` and manually `chown` the created directory if the user and/or group id of the runnning process in the deployed container do not correspond to any of the above options.
|
||||
|
||||
The `--chown` flag - whether on `storage:create` or `storage:ensure-directory` - only manages the default `/var/lib/dokku/data/storage/<name>` location. If a custom `<path>` is passed to `storage:create`, the chown call is refused and the operator must chown the path themselves.
|
||||
|
||||
> [!WARNING]
|
||||
> Failing to set the correct directory ownership may result in issues in persisting files written to the mounted storage directory.
|
||||
|
||||
@@ -103,6 +132,17 @@ In the first example, Dokku will then mount the shared contents of `/var/lib/dok
|
||||
|
||||
> If the `/storage` path within the container had pre-existing content, the container files will be over-written. This may be an issue for users that create assets at build time but then mount a directory at the same place during runtime. Files are not merged.
|
||||
|
||||
For named storage entries, additional Docker mount options can be passed via `--volume-options`. The value is a comma-separated mount-options string stored verbatim on the attachment and rendered into the `-v` flag at deploy time. This is useful for SELinux labels (`Z`, `z`) or hardening flags (`noexec,nosuid`):
|
||||
|
||||
```shell
|
||||
dokku storage:create node-js-data
|
||||
dokku storage:mount node-js-app node-js-data --container-dir /app/storage --volume-options Z
|
||||
```
|
||||
|
||||
When combined with `--volume-readonly`, the rendered options become `ro,<volume-options>` - for example, `--volume-options noexec,nosuid --volume-readonly` renders as `:ro,noexec,nosuid`.
|
||||
|
||||
Re-running `storage:mount` against a named entry with the same `--container-dir` and `--process-type` updates the existing attachment's mount-time attributes (`--phase`, `--volume-subpath`, `--volume-readonly`, `--volume-chown`, `--volume-options`) in place rather than appending a duplicate. This is the idempotent equivalent of `storage:set` for entries, and lets declarative tooling change a mount-time attribute without an unmount-then-remount dance that would briefly drop the volume from `storage:report`. Mount-time fields are rewritten wholesale, not merged - omitting a flag on a re-mount clears any previously-set value. The legacy `host:container[:opts]` form still rejects duplicates with `Mount path already exists.`.
|
||||
|
||||
Once persistent storage is mounted, the app requires a restart. See the [process scaling documentation](/docs/processes/process-management.md) for more information.
|
||||
|
||||
```shell
|
||||
@@ -127,6 +167,36 @@ Once persistent storage is unmounted, the app requires a restart. See the [proce
|
||||
dokku ps:restart app-name
|
||||
```
|
||||
|
||||
### Destroying storage entries
|
||||
|
||||
A named storage entry can be removed with the `storage:destroy` command. The entry must first be unmounted from every app that mounts it.
|
||||
|
||||
```shell
|
||||
dokku storage:destroy rdmtest-entry
|
||||
```
|
||||
|
||||
As the command is destructive - removing the registry entry and, depending on the scheduler and reclaim policy, the underlying volume - it will default to asking for confirmation before executing the removal.
|
||||
|
||||
```
|
||||
! WARNING: Potentially Destructive Action
|
||||
! This command will destroy storage entry rdmtest-entry.
|
||||
! To proceed, type "rdmtest-entry"
|
||||
> rdmtest-entry
|
||||
-----> Storage entry rdmtest-entry destroyed
|
||||
```
|
||||
|
||||
The confirmation may be avoided by providing the `--force` flag, which is useful for non-interactive or automated callers:
|
||||
|
||||
```shell
|
||||
dokku storage:destroy rdmtest-entry --force
|
||||
```
|
||||
|
||||
The global `--force` flag is also supported:
|
||||
|
||||
```shell
|
||||
dokku --force storage:destroy rdmtest-entry
|
||||
```
|
||||
|
||||
### Displaying storage reports for an app
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -172,6 +242,60 @@ You can pass flags which will output only the value of the specific information
|
||||
dokku storage:report node-js-app --storage-deploy-mounts
|
||||
```
|
||||
|
||||
In addition to the aggregated `Storage build/deploy/run mounts:` lines, the report emits one flat dotted key per attachment field, indexed from `1`. The key shape is `--storage-attachment.<index>.<field>` for each of `entry-name`, `host-path`, `container-path`, `phases`, `process-type`, `subpath`, `readonly`, `volume-options`, and `volume-chown`. Fields render as empty strings when unset, and attachments are ordered by lex-sort of the index (so `10` sorts before `2`):
|
||||
|
||||
```shell
|
||||
dokku storage:create node-js-data
|
||||
dokku storage:mount node-js-app node-js-data --container-dir /app/storage --volume-options Z --volume-chown herokuish --volume-subpath uploads
|
||||
dokku storage:report node-js-app
|
||||
```
|
||||
|
||||
```
|
||||
=====> node-js-app storage information
|
||||
Storage attachment 1 container path: /app/storage
|
||||
Storage attachment 1 entry name: node-js-data
|
||||
Storage attachment 1 host path: /var/lib/dokku/data/storage/node-js-data
|
||||
Storage attachment 1 phases: deploy,run
|
||||
Storage attachment 1 process type: _default_
|
||||
Storage attachment 1 readonly: false
|
||||
Storage attachment 1 subpath: uploads
|
||||
Storage attachment 1 volume chown: herokuish
|
||||
Storage attachment 1 volume options: Z
|
||||
Storage build mounts:
|
||||
Storage deploy mounts: -v /var/lib/dokku/data/storage/node-js-data:/app/storage:Z
|
||||
Storage run mounts: -v /var/lib/dokku/data/storage/node-js-data:/app/storage:Z
|
||||
```
|
||||
|
||||
The same keys are exposed in JSON output, both in the stripped (`attachment.1.volume-options`) and legacy (`storage-attachment.1.volume-options`) forms:
|
||||
|
||||
```shell
|
||||
dokku storage:report node-js-app --format json | jq '. | with_entries(select(.key | startswith("attachment.")))'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"attachment.1.container-path": "/app/storage",
|
||||
"attachment.1.entry-name": "node-js-data",
|
||||
"attachment.1.host-path": "/var/lib/dokku/data/storage/node-js-data",
|
||||
"attachment.1.phases": "deploy,run",
|
||||
"attachment.1.process-type": "_default_",
|
||||
"attachment.1.readonly": "false",
|
||||
"attachment.1.subpath": "uploads",
|
||||
"attachment.1.volume-chown": "herokuish",
|
||||
"attachment.1.volume-options": "Z"
|
||||
}
|
||||
```
|
||||
|
||||
A single attachment field can be fetched directly via the info-flag form:
|
||||
|
||||
```shell
|
||||
dokku storage:report node-js-app --storage-attachment.1.volume-options
|
||||
```
|
||||
|
||||
```
|
||||
Z
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Sharing storage across deploys
|
||||
@@ -214,3 +338,13 @@ By default, Dokku will execute your buildpack app processes as the `herokuishuse
|
||||
> this user must exist in your herokuish image.
|
||||
|
||||
Additionally, the default `docker-local` scheduler that comes with Dokku will ensure your storage mounts are owned by either `herokuishuser` or the overridden value you have set in `DOKKU_APP_USER`. See the [docker-local scheduler documentation](/docs/deployment/schedulers/docker-local.md#disabling-chown-of-persistent-storage) docs for more information.
|
||||
|
||||
## Properties
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following property is recorded internally by the storage plugin and is not exposed via `storage:report`:
|
||||
|
||||
| Property | Scope | Description | Source |
|
||||
|---|---|---|---|
|
||||
| `legacy-mounts-migrated` | per-app | Per-app marker recording that the app's legacy `-v` docker-options entries were drained into named storage entries plus attachments. Only set when at least one `-v` line was actually migrated; apps that have never had legacy mounts never receive this marker | `plugins/storage/migrate.go` writes `"true"` after a successful drain |
|
||||
|
||||
@@ -36,35 +36,35 @@ dokku plugin:list
|
||||
|
||||
```
|
||||
plugn: dev
|
||||
00_dokku-standard 0.37.10 enabled dokku core standard plugin
|
||||
20_events 0.37.10 enabled dokku core events logging plugin
|
||||
app-json 0.37.10 enabled dokku core app-json plugin
|
||||
apps 0.37.10 enabled dokku core apps plugin
|
||||
build-env 0.37.10 enabled dokku core build-env plugin
|
||||
buildpacks 0.37.10 enabled dokku core buildpacks plugin
|
||||
certs 0.37.10 enabled dokku core certificate management plugin
|
||||
checks 0.37.10 enabled dokku core checks plugin
|
||||
common 0.37.10 enabled dokku core common plugin
|
||||
config 0.37.10 enabled dokku core config plugin
|
||||
docker-options 0.37.10 enabled dokku core docker-options plugin
|
||||
domains 0.37.10 enabled dokku core domains plugin
|
||||
enter 0.37.10 enabled dokku core enter plugin
|
||||
git 0.37.10 enabled dokku core git plugin
|
||||
logs 0.37.10 enabled dokku core logs plugin
|
||||
network 0.37.10 enabled dokku core network plugin
|
||||
nginx-vhosts 0.37.10 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.37.10 enabled dokku core plugin plugin
|
||||
proxy 0.37.10 enabled dokku core proxy plugin
|
||||
ps 0.37.10 enabled dokku core ps plugin
|
||||
repo 0.37.10 enabled dokku core repo plugin
|
||||
resource 0.37.10 enabled dokku core resource plugin
|
||||
scheduler-docker-local 0.37.10 enabled dokku core scheduler-docker-local plugin
|
||||
shell 0.37.10 enabled dokku core shell plugin
|
||||
ssh-keys 0.37.10 enabled dokku core ssh-keys plugin
|
||||
storage 0.37.10 enabled dokku core storage plugin
|
||||
tags 0.37.10 enabled dokku core tags plugin
|
||||
tar 0.37.10 enabled dokku core tar plugin
|
||||
trace 0.37.10 enabled dokku core trace plugin
|
||||
00_dokku-standard 0.38.15 enabled dokku core standard plugin
|
||||
20_events 0.38.15 enabled dokku core events logging plugin
|
||||
app-json 0.38.15 enabled dokku core app-json plugin
|
||||
apps 0.38.15 enabled dokku core apps plugin
|
||||
build-env 0.38.15 enabled dokku core build-env plugin
|
||||
buildpacks 0.38.15 enabled dokku core buildpacks plugin
|
||||
certs 0.38.15 enabled dokku core certificate management plugin
|
||||
checks 0.38.15 enabled dokku core checks plugin
|
||||
common 0.38.15 enabled dokku core common plugin
|
||||
config 0.38.15 enabled dokku core config plugin
|
||||
docker-options 0.38.15 enabled dokku core docker-options plugin
|
||||
domains 0.38.15 enabled dokku core domains plugin
|
||||
enter 0.38.15 enabled dokku core enter plugin
|
||||
git 0.38.15 enabled dokku core git plugin
|
||||
logs 0.38.15 enabled dokku core logs plugin
|
||||
network 0.38.15 enabled dokku core network plugin
|
||||
nginx-vhosts 0.38.15 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.38.15 enabled dokku core plugin plugin
|
||||
proxy 0.38.15 enabled dokku core proxy plugin
|
||||
ps 0.38.15 enabled dokku core ps plugin
|
||||
repo 0.38.15 enabled dokku core repo plugin
|
||||
resource 0.38.15 enabled dokku core resource plugin
|
||||
scheduler-docker-local 0.38.15 enabled dokku core scheduler-docker-local plugin
|
||||
shell 0.38.15 enabled dokku core shell plugin
|
||||
ssh-keys 0.38.15 enabled dokku core ssh-keys plugin
|
||||
storage 0.38.15 enabled dokku core storage plugin
|
||||
tags 0.38.15 enabled dokku core tags plugin
|
||||
tar 0.38.15 enabled dokku core tar plugin
|
||||
trace 0.38.15 enabled dokku core trace plugin
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
|
||||
@@ -146,13 +146,27 @@ dokku registry:set node-js-app image-repo
|
||||
|
||||
### Templating the image repository name
|
||||
|
||||
Instead of setting the image repository name on a per-app basis, it can be set via a template globally with the `image-repo-template` property:
|
||||
Instead of setting the image repository name on a per-app basis, it can be set via a template with the `image-repo-template` property. The property can be set globally or for a specific app, with the per-app value overriding the global value when both are present:
|
||||
|
||||
```shell
|
||||
# globally
|
||||
dokku registry:set --global image-repo-template "my-awesome-prefix/{{ .AppName }}"
|
||||
|
||||
# per-app
|
||||
dokku registry:set node-js-app image-repo-template "my-awesome-prefix/{{ .AppName }}-prod"
|
||||
```
|
||||
|
||||
Dokku uses a Golang template and has access to the `AppName` variable as shown above.
|
||||
Dokku uses a Golang template and has access to the `AppName` variable as shown above. The per-app `image-repo` property always takes precedence over the rendered template when both are set.
|
||||
|
||||
Setting the property value to an empty string will reset the value to the system default. Resetting the value can be done per app or globally.
|
||||
|
||||
```shell
|
||||
# per-app
|
||||
dokku registry:set node-js-app image-repo-template
|
||||
|
||||
# globally
|
||||
dokku registry:set --global image-repo-template
|
||||
```
|
||||
|
||||
### Pushing images on build
|
||||
|
||||
@@ -178,6 +192,10 @@ dokku registry:set node-js-app push-on-release
|
||||
dokku registry:set --global push-on-release
|
||||
```
|
||||
|
||||
#### Recovering from local image GC
|
||||
|
||||
When `push-on-release` is enabled, Dokku treats the remote registry as the canonical store for app images. If a local image disappears - for example because a `docker image prune` cron ran, the host rebooted, or an operator removed it manually - subsequent commands that need the image (`ps:restart`, `ps:scale`, `dokku run`, `domains:add`, `certs:add`, etc.) will pull the missing tag back from the registry automatically. Per-app registry credentials configured via `registry:login` are honored during the pull. This recovery covers the deployed numeric tag pushed by the registry plugin - a missing `latest` tag will be ignored.
|
||||
|
||||
### Push extra tags
|
||||
|
||||
To push the image on release with extra tags, set the `push-extra-tags` to a comma-separated list of tags via the `registry:set` command. The default value for this property is empty. Setting the property will result in the image being tagged with extra tags every release.
|
||||
@@ -208,3 +226,18 @@ dokku registry:set node-js-app push-extra-tags
|
||||
# globally
|
||||
dokku registry:set --global push-extra-tags
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `registry:report`. The JSON keys emitted by `registry:report --format json` are the same names with the leading `--registry-` stripped (e.g. `image-repo`, `global-server`, `computed-push-on-release`). Legacy keys with the `registry-` prefix (e.g. `registry-image-repo`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `image-repo` | app only | `dokku/<app>` | `--registry-image-repo`, `--registry-computed-image-repo` | Repository name used when pushing the app's image (overrides the global template) |
|
||||
| `image-repo-template` | app + global | none | `--registry-image-repo-template`, `--registry-global-image-repo-template`, `--registry-computed-image-repo-template` | Go template used to compute the per-app image repository when `image-repo` is unset |
|
||||
| `push-extra-tags` | app + global | none | `--registry-push-extra-tags`, `--registry-global-push-extra-tags`, `--registry-computed-push-extra-tags` | Comma-separated list of additional tags pushed alongside the deploy tag |
|
||||
| `push-on-release` | app + global | `false` | `--registry-push-on-release`, `--registry-global-push-on-release`, `--registry-computed-push-on-release` | When `true`, pushes the image to the registry on every successful build |
|
||||
| `server` | app + global | none | `--registry-server`, `--registry-global-server`, `--registry-computed-server` | Registry server host (e.g. `ghcr.io`) used when pushing images |
|
||||
|
||||
@@ -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.
|
||||
|
||||
68
docs/appendices/0.38.0-migration-guide.md
Normal file
68
docs/appendices/0.38.0-migration-guide.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 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. On nginx older than 1.19.4 (e.g., Debian Bullseye's nginx 1.18.0), the postinst installs an HTTP-only variant of the catch-all that omits the SSL listener and `ssl_reject_handshake`, since that directive is unsupported on those versions. 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.
|
||||
- Every `:report` key of the form `<plugin>-global-<property>` now returns the raw stored global value (empty when the property has never been set) instead of the resolved value with the built-in default substituted in. A new `<plugin>-computed-<property>` key has been added wherever a default existed and returns the effective value (per-app value, falling back to the global value, then to the built-in default). This affects `app-json`, `builder-dockerfile`, `builder-herokuish`, `builder-lambda`, `builder-nixpacks`, `builder-pack`, `builder-railpack`, `caddy`, `checks`, `git`, `haproxy`, `logs`, `network`, `nginx`, `openresty`, `proxy`, `registry`, `scheduler`, `scheduler-k3s` and `traefik`. External tooling that read `<plugin>-global-<property>` and depended on the default value should switch to `<plugin>-computed-<property>`. The bare `<plugin>-<property>` keys for caddy/haproxy/traefik/openresty global-only properties (`caddy-image`, `haproxy-log-level`, `traefik-api-enabled`, `openresty-image`, `openresty-letsencrypt-email`, `openresty-letsencrypt-server`, `openresty-allowed-letsencrypt-domains-func-base64`, etc.) have also been replaced by the `global-` and `computed-` pair.
|
||||
- The `ps` and `cron` plugins now follow the same `<plugin>-global-<property>` / `<plugin>-computed-<property>` convention. The `ps:report` keys `stop-timeout-seconds`, `global-stop-timeout-seconds`, and `computed-stop-timeout-seconds` have been renamed to `ps-stop-timeout-seconds`, `ps-global-stop-timeout-seconds`, and `ps-computed-stop-timeout-seconds`. The `cron:report` keys `cron-mailfrom` and `cron-mailto` have been renamed to `cron-global-mailfrom` and `cron-global-mailto`, and new `cron-computed-mailfrom` and `cron-computed-mailto` keys have been added. The corresponding user-facing `--<flag>` arguments to `ps:report` and `cron:report` were renamed alongside the JSON keys; no aliases are kept. Additionally, both `ps:report --global` and `cron:report --global` now emit the `<plugin>-computed-<property>` keys for every settable global property with a default (`ps-computed-procfile-path`, `ps-computed-stop-timeout-seconds`, `cron-computed-maintenance`, `cron-computed-mailfrom`, `cron-computed-mailto`), matching the shape used by the other plugins.
|
||||
- A second round of `:report` additions surfaces every remaining settable-but-unreported property under the same raw/global/computed convention so external tooling can verify drift via `:report --format json` without falling back to a generic bash task. The `ps` plugin gains `--ps-dockerfile-start-cmd` and `--ps-computed-dockerfile-start-cmd`, `--ps-start-cmd` and `--ps-computed-start-cmd`, and the `--ps-skip-deploy` / `--ps-global-skip-deploy` / `--ps-computed-skip-deploy` triple (default `false`). The `builder` plugin gains the `--builder-skip-cleanup` triple (default `false`). The `scheduler` plugin gains the `--scheduler-shell` triple. The `proxy` plugin gains the `--proxy-proxy-port` and `--proxy-proxy-ssl-port` triples and exposes the raw `disabled` property as `--proxy-disabled` / `--proxy-computed-disabled`, alongside the existing inverted `--proxy-enabled`. The `openresty` plugin gains `--openresty-global-log-level` and `--openresty-computed-log-level` (default `ERROR`). The `nginx` plugin gains the `--nginx-nginx-service-command` triple. The `scheduler-k3s` plugin gains `--scheduler-k3s-global-token`, but the value is masked as `*******` in default stdout output; the raw value is returned only when the report is requested via `--format json` or when this flag is queried explicitly by name. The traefik `dns-provider-<env_var>` keys now follow the same explicit-query rule - previously they were unmasked only for `--format json`, but a query like `dokku traefik:report --traefik-dns-provider-cf_api_key` now returns the actual value instead of `*******`.
|
||||
- All Go-implemented plugins (`app-json`, `apps`, `builder`, `buildpacks`, `builds`, `cron`, `docker-options`, `logs`, `network`, `ports`, `proxy`, `ps`, `registry`, `resource`, `scheduler`, `scheduler-k3s`, `storage`) now emit JSON keys from `:report --format json` without the `<plugin>-` head segment, matching the shape bash plugins have always emitted. For example, `dokku ps:report myapp --format json` now contains `stop-timeout-seconds`, `global-stop-timeout-seconds`, and `computed-stop-timeout-seconds` keys. The CLI flag names (`--ps-stop-timeout-seconds`, etc.) are unchanged, and `:set` semantics are unchanged. For backwards compatibility during the 0.38.x patch series, the old `<plugin>-<property>` JSON keys are emitted side-by-side with the new keys, so external scripts reading either shape continue to work. The legacy keys will be dropped in a future major release. External JSON consumers should migrate to the new key shape.
|
||||
- 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 on nginx 1.19.4+, 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.
|
||||
|
||||
This change does not apply to nginx older than 1.19.4 (e.g., Debian Bullseye's nginx 1.18.0), where the catch-all is installed as an HTTP-only variant. On those systems, HTTPS handshakes to unknown hosts continue to fall through to the first port-443 server block as before.
|
||||
|
||||
### 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
|
||||
@@ -172,3 +288,14 @@ An autoscaling trigger consists of the following properties:
|
||||
- Example use-cases
|
||||
- Setting up OAuth clients and DNS
|
||||
- Loading seed/test data into the app’s test database
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `app-json:report`. The JSON keys emitted by `app-json:report --format json` are the same names with the leading `--app-json-` stripped (e.g. `appjson-path`, `global-appjson-path`, `computed-appjson-path`). Legacy keys with the `app-json-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `appjson-path` | app + global | `app.json` | `--app-json-appjson-path`, `--app-json-global-appjson-path`, `--app-json-computed-appjson-path` | Path within the app to the `app.json` manifest, relative to the build root |
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
# 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.
|
||||
|
||||
## HTTP/2
|
||||
|
||||
nginx 1.25.1 deprecated the `http2` parameter on the `listen` directive in favor of a standalone `http2 on;` directive. Custom `nginx.conf.sigil` templates that hardcode `listen ... ssl http2;` will produce `nginx: [warn] the "listen ... http2" directive is deprecated` warnings when run against nginx 1.25.1 or newer.
|
||||
|
||||
Dokku exposes the `HTTP2_DIRECTIVE_SUPPORTED` template variable, set to `"true"` when the host nginx is 1.25.1 or newer, so a single template can render the correct syntax against either version. The default template uses this pattern:
|
||||
|
||||
```
|
||||
{{ if eq $.HTTP2_DIRECTIVE_SUPPORTED "true" }}
|
||||
listen [{{ $.NGINX_BIND_ADDRESS_IP6 }}]:{{ $listen_port }} ssl;
|
||||
listen {{ if $.NGINX_BIND_ADDRESS_IP4 }}{{ $.NGINX_BIND_ADDRESS_IP4 }}:{{end}}{{ $listen_port }} ssl;
|
||||
http2 on;
|
||||
{{ else }}
|
||||
listen [{{ $.NGINX_BIND_ADDRESS_IP6 }}]:{{ $listen_port }} ssl http2;
|
||||
listen {{ if $.NGINX_BIND_ADDRESS_IP4 }}{{ $.NGINX_BIND_ADDRESS_IP4 }}:{{end}}{{ $listen_port }} ssl http2;
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
Dokku logs a deprecation warning during deploys when a custom template still uses the `listen ... http2` form, so the offending template can be located via the deploy output.
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/mstile-310x150.png"/>
|
||||
<square70x70logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.10\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.10\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.10\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.10\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.37.10\/docs\/assets\/favicons\/android-chrome-192x192.png",
|
||||
"src": "https:\/\/cdn.jsdelivr.net\/dokku\/dokku@v0.38.15\/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.10 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.15 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.10 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.15 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.10;
|
||||
#0.38.15;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
background: #0.37.10;
|
||||
background: #0.38.15;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
background: #0.37.10;
|
||||
background: #0.38.15;
|
||||
}
|
||||
|
||||
.powered-by_brands {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"0.34.9",
|
||||
"0.35.20",
|
||||
"0.36.11",
|
||||
"0.37.10"
|
||||
"0.37.10",
|
||||
"0.38.15"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ The following plugins are available and provided by Dokku maintainers. Please f
|
||||
| [InfluxDB](https://github.com/basgys/dokku-influxdb) | [basgys][] | 0.4.x |
|
||||
| [RethinkDB](https://github.com/stuartpb/dokku-rethinkdb-plugin) | [stuartpb][] | 0.3.x |
|
||||
| [Headless Chrome](https://github.com/lazyatom/dokku-chrome) | [lazyatom][] | 0.8.1+ |
|
||||
| [HTTP OAuth](https://github.com/cheif/dokku-http-oauth) | [cheif][] | 0.4.0+ |
|
||||
|
||||
### Plugins Implementing New Dokku Functionality
|
||||
|
||||
@@ -267,6 +268,7 @@ The following plugins are no longer maintained by their developers.
|
||||
[candlewaster]: https://notabug.org/candlewaster
|
||||
[cedricziel]: https://github.com/cedricziel
|
||||
[cef]: https://github.com/cef
|
||||
[cheif]: https://github.com/cheif
|
||||
[cjblomqvist]: https://github.com/cjblomqvist
|
||||
[crisward]: https://github.com/crisward
|
||||
[cu12]: https://github.com/cu12
|
||||
|
||||
@@ -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:
|
||||
@@ -42,10 +42,23 @@ Dokku can also read base64 encoded values. That's the easiest way to set a value
|
||||
dokku config:set --encoded node-js-app KEY="$(base64 -w 0 ~/.ssh/id_rsa)"
|
||||
```
|
||||
|
||||
Decoded values are stored byte-for-byte exactly as they were encoded. Be aware that `echo "value" | base64` appends a trailing `\n` before encoding because `echo` always adds a newline, and that newline becomes part of the stored value. This is rarely what you want for short inline values - use `printf '%s'` or `echo -n` instead:
|
||||
|
||||
```shell
|
||||
dokku config:set --encoded node-js-app KEY="$(printf '%s' "myvalue" | base64 -w 0)"
|
||||
dokku config:set --encoded node-js-app KEY="$(echo -n "myvalue" | base64 -w 0)"
|
||||
```
|
||||
|
||||
For multi-line values from a file (such as an SSH private key), `cat` and `base64 -w 0` preserve the file contents exactly:
|
||||
|
||||
```shell
|
||||
dokku config:set --encoded node-js-app KEY="$(cat ~/.ssh/id_rsa | base64 -w 0)"
|
||||
```
|
||||
|
||||
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 +67,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 +81,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 +140,15 @@ 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. |
|
||||
|
||||
## Properties
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following property is recorded internally by the config plugin and is not exposed via `config:report`:
|
||||
|
||||
| Property | Description | Source |
|
||||
|---|---|---|
|
||||
| `env-migrated` | Migration sentinel that records the per-app or global `DOKKU_*` env-var → property migration completed for 0.38.0 | `plugins/config/triggers.go` writes `"true"` after the upgrade-time pass |
|
||||
|
||||
@@ -41,6 +41,9 @@ dokku certs:add node-js-app < cert-key.tar
|
||||
cat yourdomain_com.crt yourdomain_com.ca-bundle > server.crt
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Archives passed to `certs:add` are validated before extraction to prevent path traversal and symlink escape attacks. Archives containing absolute paths, parent directory traversal entries, or symlinks pointing outside the extraction directory will be rejected.
|
||||
|
||||
#### SSL and Multiple Domains
|
||||
|
||||
When an SSL certificate is associated to an application, the certificate will be associated with _all_ domains currently associated with said application. Your certificate _should_ be associated with all of those domains, otherwise accessing the application will result in SSL errors. If you wish to remove one of the domains from the application, refer to the [domain configuration documentation](/docs/configuration/domains.md).
|
||||
@@ -140,8 +143,27 @@ Certain versions of nginx have bugs that prevent [HTTP/2](https://nginx.org/en/d
|
||||
|
||||
When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku ports:add <APP> https:443:99999`.
|
||||
|
||||
If an `https:443:*` port mapping already exists when a certificate is installed or renewed, Dokku will preserve it rather than rewriting it from the `http:80:*` mappings. This allows apps that terminate TLS inside the container (for example, with a configuration like `http:80:80 https:443:443`) to keep their explicit mapping across `dokku certs:add` and unattended renewals.
|
||||
|
||||
## Other
|
||||
|
||||
### Running behind a proxy (`X-Forwarded-Ssl`, etc.)
|
||||
|
||||
See the [running behind another proxy documentation](/docs/networking/proxies/nginx.md#running-behind-another-proxy--configuring-x-forwarded--headers) for more information on how to configure your Nginx config when your server is running behind a proxy (e.g. load balancer, etc.).
|
||||
|
||||
## Properties
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `certs:report` but are not managed by `certs:set` - they are derived from the on-disk certificate:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--ssl-enabled` | `true` when an SSL certificate is installed for the app |
|
||||
| `--ssl-dir` | Absolute path to the per-app certificate directory |
|
||||
| `--ssl-hostnames` | Hostnames the certificate covers (CN plus Subject Alternative Names) |
|
||||
| `--ssl-issuer` | Certificate issuer DN |
|
||||
| `--ssl-subject` | Certificate subject DN |
|
||||
| `--ssl-verified` | `true` if the certificate chain verifies against the system CA bundle |
|
||||
| `--ssl-expires-at` | Certificate `notAfter` timestamp |
|
||||
| `--ssl-starts-at` | Certificate `notBefore` timestamp |
|
||||
|
||||
@@ -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.
|
||||
@@ -297,3 +312,26 @@ You can pass flags which will output only the value of the specific information
|
||||
```shell
|
||||
dokku apps:report node-js-app --app-dir
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `apps:report`. The JSON keys emitted by `apps:report --format json` are the same names with the leading `--app-` stripped (e.g. `global-disable-autocreation`). Legacy keys with the `app-` prefix (e.g. `app-global-disable-autocreation`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `disable-autocreation` | global only | `false` | `--app-global-disable-autocreation` | When `true`, pushes to a remote for an app that does not yet exist are rejected instead of auto-creating the app |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `apps:report` but are not managed by `apps:set`:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--app-created-at` | UNIX timestamp of app creation |
|
||||
| `--app-deploy-source` | Source kind of the last deploy (`git`, `archive`, `docker-image`, `git-sync`) |
|
||||
| `--app-deploy-source-metadata` | Free-form metadata for the deploy source (commit sha, image ref, URL) |
|
||||
| `--app-dir` | Absolute path of the app root on disk |
|
||||
| `--app-locked` | `true` while a deploy or rebuild holds the app lock |
|
||||
|
||||
@@ -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:
|
||||
@@ -150,3 +172,24 @@ Custom plugins names _must_ have the prefix `builder-` or builder overriding via
|
||||
Builders can use any tools available on the system to build the docker image, and may even be used to schedule building off-server. The only current requirement is that the image must exist on the server at the end of the `builder-build` command, though this requirement may be relaxed in a future release.
|
||||
|
||||
For a simple example of how to implement this trigger, see `builder-pack`, which utilizes a cli tool - `pack-cli` - to generate an OCI image that is compatible with Docker and can be scheduled by the official scheduling plugins.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `builder:report`. The JSON keys emitted by `builder:report --format json` are the same names with the leading `--builder-` stripped (e.g. `selected`, `global-selected`, `computed-selected`). Legacy keys with the `builder-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `build-dir` | app + global | none | `--builder-build-dir`, `--builder-global-build-dir`, `--builder-computed-build-dir` | Subdirectory within the repository to use as the build context |
|
||||
| `selected` | app + global | none | `--builder-selected`, `--builder-global-selected`, `--builder-computed-selected` | Builder plugin to use; overrides automatic detection |
|
||||
| `skip-cleanup` | app + global | `false` | `--builder-skip-cleanup`, `--builder-global-skip-cleanup`, `--builder-computed-skip-cleanup` | When `true`, leaves intermediate build artifacts in place after the build |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `builder:report` but are not managed by `builder:set`:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--builder-detected` | Builder auto-selected for the app when `selected` is unset |
|
||||
|
||||
@@ -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:
|
||||
@@ -172,3 +190,16 @@ You can pass flags which will output only the value of the specific information
|
||||
```shell
|
||||
dokku buildpacks:report node-js-app --buildpacks-list
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
These properties are managed via `buildpacks:set-property` (the legacy command name for this plugin).
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `buildpacks:report`. The JSON keys emitted by `buildpacks:report --format json` are the same names with the leading `--buildpacks-` stripped (e.g. `stack`, `global-stack`, `computed-stack`). Legacy keys with the `buildpacks-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `stack` | app + global | none | `--buildpacks-stack`, `--buildpacks-global-stack`, `--buildpacks-computed-stack` | Herokuish stack image used to compile the app (e.g. `heroku/heroku:24`) |
|
||||
|
||||
@@ -98,18 +98,20 @@ dokku builder-pack:report
|
||||
```
|
||||
=====> node-js-app builder-pack information
|
||||
Builder pack computed projecttoml path: project2.toml
|
||||
Builder pack global projecttoml path: project.toml
|
||||
Builder pack global projecttoml path:
|
||||
Builder pack projecttoml path: project2.toml
|
||||
=====> python-sample builder-pack information
|
||||
Builder pack computed projecttoml path: project.toml
|
||||
Builder pack global projecttoml path: project.toml
|
||||
Builder pack global projecttoml path:
|
||||
Builder pack projecttoml path:
|
||||
=====> ruby-sample builder-pack information
|
||||
Builder pack computed projecttoml path: project.toml
|
||||
Builder pack global projecttoml path: project.json
|
||||
Builder pack global projecttoml path:
|
||||
Builder pack projecttoml path:
|
||||
```
|
||||
|
||||
The `projecttoml-path` and `global-projecttoml-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-projecttoml-path` key holds the effective value used at build time, falling back to the global value (where one has been set) and then to the built-in default of `project.toml`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -119,7 +121,7 @@ dokku builder-pack:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-pack information
|
||||
Builder pack computed projecttoml path: project2.toml
|
||||
Builder pack global projecttoml path: project.toml
|
||||
Builder pack global projecttoml path:
|
||||
Builder pack projecttoml path: project2.toml
|
||||
```
|
||||
|
||||
@@ -165,3 +167,11 @@ dokku buildpacks:set-property --global stack
|
||||
### Specifying commands via Procfile
|
||||
|
||||
See the [Procfile documentation](/docs/processes/process-management.md#procfile) for more information on how to specify different processes for your app.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `projecttoml-path` | app + global | `project.toml` | `--builder-pack-projecttoml-path`, `--builder-pack-global-projecttoml-path`, `--builder-pack-computed-projecttoml-path` | Path within the app to the CNB `project.toml` manifest, relative to the build root |
|
||||
|
||||
@@ -82,18 +82,20 @@ dokku builder-dockerfile:report
|
||||
```
|
||||
=====> node-js-app builder-dockerfile information
|
||||
Builder dockerfile computed dockerfile path: Dockerfile2
|
||||
Builder dockerfile global dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path:
|
||||
Builder dockerfile dockerfile path: Dockerfile2
|
||||
=====> python-sample builder-dockerfile information
|
||||
Builder dockerfile computed dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path:
|
||||
Builder dockerfile dockerfile path:
|
||||
=====> ruby-sample builder-dockerfile information
|
||||
Builder dockerfile computed dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path:
|
||||
Builder dockerfile dockerfile path:
|
||||
```
|
||||
|
||||
The `dockerfile-path` and `global-dockerfile-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-dockerfile-path` key holds the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default of `Dockerfile`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -103,7 +105,7 @@ dokku builder-dockerfile:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-dockerfile information
|
||||
Builder dockerfile computed dockerfile path: Dockerfile2
|
||||
Builder dockerfile global dockerfile path: Dockerfile
|
||||
Builder dockerfile global dockerfile path:
|
||||
Builder dockerfile dockerfile path: Dockerfile2
|
||||
```
|
||||
|
||||
@@ -185,7 +187,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 +196,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
|
||||
|
||||
@@ -209,3 +215,11 @@ See the [Procfile documentation](/docs/processes/process-management.md#procfile)
|
||||
### Exposed ports
|
||||
|
||||
See the [port management documentation](/docs/networking/port-management.md) for more information on how Dokku exposes ports for applications and how you can configure these for your app.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `dockerfile-path` | app + global | `Dockerfile` | `--builder-dockerfile-dockerfile-path`, `--builder-dockerfile-global-dockerfile-path`, `--builder-dockerfile-computed-dockerfile-path` | Path within the app to the Dockerfile used by the dockerfile builder |
|
||||
|
||||
@@ -117,18 +117,20 @@ dokku builder-herokuish:report
|
||||
```
|
||||
=====> node-js-app builder-herokuish information
|
||||
Builder herokuish computed allowed: false
|
||||
Builder herokuish global allowed: true
|
||||
Builder herokuish global allowed:
|
||||
Builder herokuish allowed: false
|
||||
=====> python-sample builder-herokuish information
|
||||
Builder herokuish computed allowed: true
|
||||
Builder herokuish global allowed: true
|
||||
Builder herokuish global allowed:
|
||||
Builder herokuish allowed:
|
||||
=====> ruby-sample builder-herokuish information
|
||||
Builder herokuish computed allowed: true
|
||||
Builder herokuish global allowed: true
|
||||
Builder herokuish global allowed:
|
||||
Builder herokuish allowed:
|
||||
```
|
||||
|
||||
The `allowed` and `global-allowed` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-allowed` key holds the effective value used at build time, falling back to the global value (where one has been set) and then to the built-in default (`true` on amd64, `false` otherwise).
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -138,7 +140,7 @@ dokku builder-herokuish:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-herokuish information
|
||||
Builder herokuish computed allowed: false
|
||||
Builder herokuish global allowed: true
|
||||
Builder herokuish global allowed:
|
||||
Builder herokuish allowed: false
|
||||
```
|
||||
|
||||
@@ -208,4 +210,12 @@ See the [buildpack management documentation](/docs/processes/process-management.
|
||||
|
||||
### Displaying buildpack reports for an app
|
||||
|
||||
See the [buildpack management documentation](/docs/processes/process-management.md#displaying-buildpack-reports-for-an-app) for more information on how to display buildpack reports for an app.
|
||||
See the [buildpack management documentation](/docs/processes/process-management.md#displaying-buildpack-reports-for-an-app) for more information on how to display buildpack reports for an app.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `allowed` | app + global | `true` | `--builder-herokuish-allowed`, `--builder-herokuish-global-allowed`, `--builder-herokuish-computed-allowed` | When `false`, the herokuish builder is skipped during builder detection for this app |
|
||||
@@ -84,18 +84,20 @@ dokku builder-lambda:report
|
||||
```
|
||||
=====> node-js-app builder-lambda information
|
||||
Builder lambda computed lambdayml path: lambda2.yml
|
||||
Builder lambda global lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path:
|
||||
Builder lambda lambdayml path: lambda2.yml
|
||||
=====> python-sample builder-lambda information
|
||||
Builder lambda computed lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path:
|
||||
Builder lambda lambdayml path:
|
||||
=====> ruby-sample builder-lambda information
|
||||
Builder lambda computed lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path:
|
||||
Builder lambda lambdayml path:
|
||||
```
|
||||
|
||||
The `lambdayml-path` and `global-lambdayml-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-lambdayml-path` key holds the effective value used at build time, falling back to the global value (where one has been set) and then to the built-in default of `lambda.yml`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -105,7 +107,7 @@ dokku builder-lambda:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-lambda information
|
||||
Builder lambda computed lambdayml path: lambda2.yml
|
||||
Builder lambda global lambdayml path: lambda.yml
|
||||
Builder lambda global lambdayml path:
|
||||
Builder lambda lambdayml path: lambda2.yml
|
||||
```
|
||||
|
||||
@@ -118,3 +120,11 @@ dokku builder-lambda:report node-js-app --builder-lambda-lambdayml-path
|
||||
```
|
||||
lambda2.yml
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `lambdayml-path` | app + global | `lambda.yml` | `--builder-lambda-lambdayml-path`, `--builder-lambda-global-lambdayml-path`, `--builder-lambda-computed-lambdayml-path` | Path within the app to the `lambda.yml` manifest used by the lambda builder |
|
||||
|
||||
@@ -97,18 +97,20 @@ dokku builder-nixpacks:report
|
||||
```
|
||||
=====> node-js-app builder-nixpacks information
|
||||
Builder-nixpacks computed nixpackstoml path: nixpacks2.toml
|
||||
Builder-nixpacks global nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path:
|
||||
Builder-nixpacks nixpackstoml path: nixpacks2.toml
|
||||
=====> python-sample builder-nixpacks information
|
||||
Builder-nixpacks computed nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path:
|
||||
Builder-nixpacks nixpackstoml path:
|
||||
=====> ruby-sample builder-nixpacks information
|
||||
Builder-nixpacks computed nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path:
|
||||
Builder-nixpacks nixpackstoml path:
|
||||
```
|
||||
|
||||
The `nixpackstoml-path` and `global-nixpackstoml-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-nixpackstoml-path` key holds the effective value used at build time, falling back to the global value (where one has been set) and then to the built-in default of `nixpacks.toml`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -118,7 +120,7 @@ dokku builder-nixpacks:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-nixpacks information
|
||||
Builder-nixpacks computed nixpackstoml path: nixpacks2.toml
|
||||
Builder-nixpacks global nixpackstoml path: nixpacks.toml
|
||||
Builder-nixpacks global nixpackstoml path:
|
||||
Builder-nixpacks nixpackstoml path: nixpacks2.toml
|
||||
```
|
||||
|
||||
@@ -131,3 +133,11 @@ dokku builder-nixpacks:report node-js-app --builder-nixpacks-nixpackstoml-path
|
||||
```
|
||||
nixpacks2.toml
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `nixpackstoml-path` | app + global | `nixpacks.toml` | `--builder-nixpacks-nixpackstoml-path`, `--builder-nixpacks-global-nixpackstoml-path`, `--builder-nixpacks-computed-nixpackstoml-path` | Path within the app to the `nixpacks.toml` manifest used by the nixpacks builder |
|
||||
|
||||
@@ -20,7 +20,7 @@ Before using Railpacks, the following steps must be taken:
|
||||
```shell
|
||||
touch /etc/default/dokku
|
||||
echo "export BUILDKIT_HOST='docker-container://buildkit'" >> /etc/default/dokku
|
||||
````
|
||||
```
|
||||
|
||||
### Detection
|
||||
|
||||
@@ -106,18 +106,20 @@ dokku builder-railpack:report
|
||||
```
|
||||
=====> node-js-app builder-railpack information
|
||||
Builder-railpack computed railpackjson path: railpack2.json
|
||||
Builder-railpack global railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path:
|
||||
Builder-railpack railpackjson path: railpack2.json
|
||||
=====> python-sample builder-railpack information
|
||||
Builder-railpack computed railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path:
|
||||
Builder-railpack railpackjson path:
|
||||
=====> ruby-sample builder-railpack information
|
||||
Builder-railpack computed railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path:
|
||||
Builder-railpack railpackjson path:
|
||||
```
|
||||
|
||||
The `railpackjson-path` and `global-railpackjson-path` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-railpackjson-path` key holds the effective value used at build time, falling back to the global value (where one has been set) and then to the built-in default of `railpack.json`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -127,7 +129,7 @@ dokku builder-railpack:report node-js-app
|
||||
```
|
||||
=====> node-js-app builder-railpack information
|
||||
Builder-railpack computed railpackjson path: railpack2.json
|
||||
Builder-railpack global railpackjson path: railpack.json
|
||||
Builder-railpack global railpackjson path:
|
||||
Builder-railpack railpackjson path: railpack2.json
|
||||
```
|
||||
|
||||
@@ -140,3 +142,11 @@ dokku builder-railpack:report node-js-app --builder-railpack-railpackjson-path
|
||||
```
|
||||
railpack2.json
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `railpackjson-path` | app + global | `railpack.json` | `--builder-railpack-railpackjson-path`, `--builder-railpack-global-railpackjson-path`, `--builder-railpack-computed-railpackjson-path` | Path within the app to the `railpack.json` manifest used by the railpack builder |
|
||||
|
||||
@@ -178,6 +178,39 @@ Setting this to an empty string will reset the version to the version currently
|
||||
dokku logs:set --global vector-image
|
||||
```
|
||||
|
||||
#### Attaching Vector to additional Docker networks
|
||||
|
||||
By default, the Vector container runs with `network_mode: bridge` and can only reach app containers that are also on the default bridge network. Apps deployed onto a per-app network or a custom network - typically via `dokku network:set <app> initial-network <name>` - are not reachable from Vector over Docker's internal DNS, so sinks that need to talk to those apps directly (for example, an in-host log search service such as [Logpond](https://github.com/dokku/logpond)) would have to route traffic out through the external proxy.
|
||||
|
||||
The global `vector-networks` property accepts a comma-separated list of Docker networks for Vector to join.
|
||||
|
||||
```shell
|
||||
dokku logs:set --global vector-networks dokku-logs
|
||||
```
|
||||
|
||||
Multiple networks may be specified by separating them with a comma.
|
||||
|
||||
```shell
|
||||
dokku logs:set --global vector-networks dokku-logs,observability
|
||||
```
|
||||
|
||||
Setting this property **replaces** the default bridge attachment: the Vector container will be on the configured user-defined networks only, not the default Docker `bridge` network. Outbound traffic continues to work through the user-defined networks' NAT, so external sinks such as Datadog or hosted HTTP endpoints remain reachable.
|
||||
|
||||
Each network must already exist; setting a non-existent network or the reserved `bridge` value will fail. The list can be cleared by setting an empty value, which restores the default `network_mode: bridge` configuration.
|
||||
|
||||
```shell
|
||||
dokku logs:set --global vector-networks
|
||||
```
|
||||
|
||||
Network attachments are reconciled by `docker compose` on every `logs:vector-start`, so after changing the value the Vector container must be cycled.
|
||||
|
||||
```shell
|
||||
dokku logs:vector-stop
|
||||
dokku logs:vector-start
|
||||
```
|
||||
|
||||
Once attached, an app on `dokku-logs` (for example via `dokku network:set node-js-app initial-network dokku-logs`) is reachable from Vector at `<app>.<process>:<port>` over the shared network without round-tripping through the external proxy.
|
||||
|
||||
#### Configuring a log sink
|
||||
|
||||
Vector uses the concept of log "sinks" to send logs to a given endpoint. Log sinks may be configured globally or on a per-app basis by specifying a `vector-sink` in DSN form with the `logs:set` command. Specifying a sink value will reload any running vector container.
|
||||
@@ -278,3 +311,18 @@ As with app-specific label alias settings, the global value may also be cleared
|
||||
```shell
|
||||
dokku logs:set --global app-label-alias
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `logs:report`. The JSON keys emitted by `logs:report --format json` are the same names with the leading `--logs-` stripped (e.g. `max-size`, `global-max-size`, `computed-max-size`). Legacy keys with the `logs-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `app-label-alias` | app + global | `com.dokku.app-name` | `--logs-app-label-alias`, `--logs-global-app-label-alias`, `--logs-computed-app-label-alias` | Docker label key whose value is used to identify the app when shipping logs |
|
||||
| `max-size` | app + global | `10m` | `--logs-max-size`, `--logs-global-max-size`, `--logs-computed-max-size` | Maximum size of an individual log file before rotation |
|
||||
| `vector-image` | global only | _parsed from `plugins/logs/Dockerfile`_ | `--logs-global-vector-image`, `--logs-computed-vector-image` | Docker image used to run the vector log-shipper container |
|
||||
| `vector-networks` | global only | none | `--logs-global-vector-networks`, `--logs-computed-vector-networks` | Comma-separated list of docker networks the vector container is attached to |
|
||||
| `vector-sink` | app + global | none | `--logs-vector-sink`, `--logs-global-vector-sink`, `--logs-computed-vector-sink` | DSN-style sink configuration for vector (e.g. `console://` or `loki://...`) |
|
||||
|
||||
@@ -32,3 +32,29 @@ Finally, if the archive url is specified as `--`, the archive will be fetched fr
|
||||
```shell
|
||||
curl -sSL https://github.com/dokku/smoke-test-app/releases/download/2.0.0/smoke-test-app.tar | dokku git:from-archive node-js-app --
|
||||
```
|
||||
|
||||
## Archive Safety
|
||||
|
||||
Archive contents are validated before extraction to prevent path traversal and symlink escape attacks. Archives containing absolute paths, parent directory traversal entries (`..`), or symlinks pointing outside the extraction directory are rejected.
|
||||
|
||||
The following limits can be configured via global git properties:
|
||||
|
||||
- `archive-max-size` - maximum archive size in bytes (default: `1073741824`, 1 GiB)
|
||||
- `archive-max-files` - maximum number of entries in an archive (default: `10000`)
|
||||
|
||||
```shell
|
||||
dokku git:set --global archive-max-size 2147483648
|
||||
dokku git:set --global archive-max-files 20000
|
||||
```
|
||||
|
||||
Unset a property to restore the default:
|
||||
|
||||
```shell
|
||||
dokku git:set --global archive-max-size
|
||||
```
|
||||
|
||||
The current values can be inspected via the global git report:
|
||||
|
||||
```shell
|
||||
dokku git:report --global
|
||||
```
|
||||
|
||||
@@ -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,73 @@ 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 computed archive max files: 10000
|
||||
Git computed archive max size: 1073741824
|
||||
Git computed deploy branch: master
|
||||
Git computed keep git dir: false
|
||||
Git deploy branch:
|
||||
Git global archive max files:
|
||||
Git global archive max size:
|
||||
Git global deploy branch:
|
||||
Git global keep git dir:
|
||||
Git keep git dir:
|
||||
Git rev env var: GIT_REV
|
||||
Git sha: a1b2c3d
|
||||
Git source image:
|
||||
Git last updated at: 1700000000
|
||||
```
|
||||
|
||||
The bare per-app keys (`deploy-branch`, `keep-git-dir`) and the `global-<prop>` keys hold the raw per-app or global value respectively, and are empty when nothing has been set. The `computed-<prop>` keys hold the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default.
|
||||
|
||||
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.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `archive-max-files` | app + global | none | `--git-global-archive-max-files`, `--git-computed-archive-max-files` | Maximum number of files allowed in an uploaded archive deploy |
|
||||
| `archive-max-size` | app + global | none | `--git-global-archive-max-size`, `--git-computed-archive-max-size` | Maximum total size of an uploaded archive deploy |
|
||||
| `deploy-branch` | app + global | `master` | `--git-deploy-branch`, `--git-global-deploy-branch`, `--git-computed-deploy-branch` | Branch name pushed by the git remote that triggers a deploy |
|
||||
| `keep-git-dir` | app + global | `false` | `--git-keep-git-dir`, `--git-global-keep-git-dir`, `--git-computed-keep-git-dir` | When `true`, retains the `.git` directory inside the build context |
|
||||
| `rev-env-var` | app + global | `GIT_REV` | `--git-rev-env-var` | Environment variable name receiving the deployed commit SHA; empty disables injection |
|
||||
| `source-image` | app + global | none | `--git-source-image` | Docker image to clone application source from when deploying from an image |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `git:report` but are not managed by `git:set` - they are derived from repository state:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--git-sha` | HEAD commit SHA of the app's git repo |
|
||||
| `--git-last-updated-at` | UNIX timestamp of the last write to the deploy branch ref |
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
```
|
||||
scheduler-docker-local:report [<app>] [<flag>] # Displays a scheduler-docker-local report for one or more apps
|
||||
scheduler-docker-local:set <app> <key> (<value>) # Set or clear a scheduler-docker-local property for an app
|
||||
scheduler-docker-local:set [<app>|--global] <key> (<value>) # Set or clear a scheduler-docker-local property for an app or globally
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -46,7 +46,19 @@ Once set, you may re-enable it by setting a blank value for `init-process`:
|
||||
dokku scheduler-docker-local:set node-js-app init-process
|
||||
```
|
||||
|
||||
All image containers with the label `org.opencontainers.image.vendor=linuxserver.io` will have the automatic init process injection force-disabled without further intervention.
|
||||
The default value may also be configured globally with the `--global` flag. Per-app values take precedence over the global value when set.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set --global init-process false
|
||||
```
|
||||
|
||||
The global value may also be unset by setting a blank value.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set --global init-process
|
||||
```
|
||||
|
||||
All image containers with the label `org.opencontainers.image.vendor=linuxserver.io` will have the automatic init process injection force-disabled without further intervention when neither an app-level nor a global value is set.
|
||||
|
||||
### Deploying Process Types in Parallel
|
||||
|
||||
@@ -66,6 +78,18 @@ Once set, you may reset it by setting a blank value for `parallel-schedule-count
|
||||
dokku scheduler-docker-local:set node-js-app parallel-schedule-count
|
||||
```
|
||||
|
||||
The default value may also be configured globally with the `--global` flag. Per-app values take precedence over the global value when set.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set --global parallel-schedule-count 4
|
||||
```
|
||||
|
||||
The global value may also be unset by setting a blank value.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set --global parallel-schedule-count
|
||||
```
|
||||
|
||||
If the value of `parallel-schedule-count` is increased and a given process type fails to schedule successfully, then any in-flight process types will continue to be processed, while all process types that have not been scheduled will be skipped before the deployment finally fails.
|
||||
|
||||
Container scheduling output is shown in the order it is received, and thus may be out of order in case of output to stderr.
|
||||
@@ -100,6 +124,57 @@ Note that increasing the value of `max_parallel` may significantly impact CPU ut
|
||||
|
||||
See the [app.json location documentation](/docs/advanced-usage/deployment-tasks.md#changing-the-appjson-location) for more information on where to place your `app.json` file.
|
||||
|
||||
### Displaying scheduler-docker-local reports for an app
|
||||
|
||||
You can get a report about the app's scheduler-docker-local configuration using the `scheduler-docker-local:report` command:
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:report
|
||||
```
|
||||
|
||||
```
|
||||
=====> node-js-app scheduler-docker-local information
|
||||
Scheduler docker local computed init process: true
|
||||
Scheduler docker local computed parallel schedule count:1
|
||||
Scheduler docker local global init process: true
|
||||
Scheduler docker local global parallel schedule count: 1
|
||||
Scheduler docker local init process:
|
||||
Scheduler docker local parallel schedule count:
|
||||
```
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:report node-js-app
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:report node-js-app --scheduler-docker-local-computed-init-process
|
||||
```
|
||||
|
||||
When run against `--global`, only the global keys are reported.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:report --global
|
||||
```
|
||||
|
||||
The available keys are:
|
||||
|
||||
- `--scheduler-docker-local-init-process`: the raw per-app init-process value (empty when unset).
|
||||
- `--scheduler-docker-local-computed-init-process`: the effective init-process value, computed as the per-app value if set, otherwise the global value, otherwise `true`.
|
||||
- `--scheduler-docker-local-global-init-process`: the global init-process value (defaults to `true`).
|
||||
- `--scheduler-docker-local-parallel-schedule-count`: the raw per-app parallel-schedule-count value (empty when unset).
|
||||
- `--scheduler-docker-local-computed-parallel-schedule-count`: the effective parallel-schedule-count value, computed as the per-app value if set, otherwise the global value, otherwise `1`.
|
||||
- `--scheduler-docker-local-global-parallel-schedule-count`: the global parallel-schedule-count value (defaults to `1`).
|
||||
|
||||
The report may also be emitted as JSON using `--format json`, which is useful for external tooling that needs to distinguish a value set on the app from one that is defaulting.
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:report node-js-app --format json
|
||||
```
|
||||
|
||||
## Scheduler Interface
|
||||
|
||||
The following sections describe implemented scheduler functionality for the `docker-local` scheduler.
|
||||
@@ -141,3 +216,12 @@ The `docker-local` scheduler supports a minimal list of resource _limits_ and _r
|
||||
|
||||
- memory: (docker option: `--memory-reservation`) should be specified with a suffix of `b` (bytes), `k` (kilobytes), `m` (megabytes), `g` (gigabytes). Default unit is `m` (megabytes).
|
||||
- See the ["Memory" section](https://docs.docker.com/config/containers/resource_constraints/#memory) of the Docker Runtime Options documentation for more information.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `init-process` | app + global | `true` | `--scheduler-docker-local-init-process`, `--scheduler-docker-local-global-init-process`, `--scheduler-docker-local-computed-init-process` | When `true`, runs containers with Docker's `--init` flag (reaping zombie processes) |
|
||||
| `parallel-schedule-count` | app + global | `1` | `--scheduler-docker-local-parallel-schedule-count`, `--scheduler-docker-local-global-parallel-schedule-count`, `--scheduler-docker-local-computed-parallel-schedule-count` | Maximum number of containers scheduled in parallel during a deploy |
|
||||
|
||||
@@ -5,14 +5,18 @@
|
||||
|
||||
```
|
||||
scheduler-k3s:annotations:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE>, Set or clear an annotation for a given app/process-type/resource-type combination
|
||||
scheduler-k3s:annotations:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE] # Displays a scheduler-k3s annotations report for one or more apps
|
||||
scheduler-k3s:autoscaling-auth:set <app|--global> <trigger> [<--metadata key=value>...], Set or clear a scheduler-k3s autoscaling keda trigger authentication resource for an app
|
||||
scheduler-k3s:autoscaling-auth:report <app|--global> [--format stdout|json] [--include-metadata] # Displays a scheduler-k3s autoscaling auth report for an app
|
||||
scheduler-k3s:autoscaling-auth:report [<app>|--global] [--format stdout|json] [--include-metadata] # Displays a scheduler-k3s autoscaling auth report for one or more apps
|
||||
scheduler-k3s:charts:report [<chart>] [--format stdout|json] # Displays a scheduler-k3s chart override report
|
||||
scheduler-k3s:charts:set <chart-name.property> (<value>) # Set or clear a chart-specific helm value
|
||||
scheduler-k3s:cluster:add [ssh://user@host:port] # Adds a server node to a Dokku-managed cluster
|
||||
scheduler-k3s:cluster:list # Lists all nodes in a Dokku-managed cluster
|
||||
scheduler-k3s:cluster:remove [node-id] # Removes client node to a Dokku-managed cluster
|
||||
scheduler-k3s:ensure-charts # Ensures the k3s charts are installed
|
||||
scheduler-k3s:initialize # Initializes a cluster
|
||||
scheduler-k3s:labels:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE> # Set or clear a label for a given app/process-type/resource-type combination
|
||||
scheduler-k3s:labels:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE] # Displays a scheduler-k3s labels report for one or more apps
|
||||
scheduler-k3s:profiles:add <profile> [--role ROLE] [--insecure-allow-unknown-hosts] [--taint-scheduling] [--kubelet-args KUBELET_ARGS] Adds a node profile to the k3s cluster
|
||||
scheduler-k3s:profiles:list [--format json|stdout] # Lists all node profiles in the k3s cluster
|
||||
scheduler-k3s:profiles:remove <profile> # Removes a node profile from the k3s cluster
|
||||
@@ -372,6 +376,8 @@ The following resource types are supported:
|
||||
- `traefik_ingressroute`
|
||||
- `traefik_middleware`
|
||||
|
||||
Annotation keys may contain `/` (e.g. Kubernetes-style keys such as `prometheus.io/scrape`) and values may span multiple lines; both are preserved verbatim.
|
||||
|
||||
A `ps:restart` is required after setting annotations in order to have them apply to running resources.
|
||||
|
||||
#### Removing an annotation
|
||||
@@ -385,6 +391,35 @@ dokku scheduler-k3s:annotations:set node-js-app annotation.key --resource-type d
|
||||
|
||||
A `ps:restart` is required after removing annotations in order to remove them from running resources.
|
||||
|
||||
#### Displaying annotations
|
||||
|
||||
Configured annotations can be inspected with the `scheduler-k3s:annotations:report` command. Without arguments, it iterates every app and prints all annotations. Passing an app name (or `--global`) scopes the report:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:annotations:report
|
||||
dokku scheduler-k3s:annotations:report node-js-app
|
||||
dokku scheduler-k3s:annotations:report --global
|
||||
```
|
||||
|
||||
`--process-type` and `--resource-type` flags narrow the output to a specific scope, matching the flags accepted by `scheduler-k3s:annotations:set`:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:annotations:report node-js-app --resource-type deployment
|
||||
dokku scheduler-k3s:annotations:report node-js-app --process-type web --resource-type deployment
|
||||
```
|
||||
|
||||
JSON output emits flat keys of the form `{process_type}.{resource_type}.{annotation_key}`. The literal `--global` process type is rendered as `global` to keep keys free of leading dashes:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:annotations:report node-js-app --format json
|
||||
```
|
||||
|
||||
A single value can also be read directly with a flag of the form `--scheduler-k3s-annotations.{process_type}.{resource_type}.{annotation_key}`:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:annotations:report node-js-app --scheduler-k3s-annotations.global.deployment.annotation.key
|
||||
```
|
||||
|
||||
#### Setting Labels
|
||||
|
||||
Dokku injects certain labels into each created resource by default, but it may be necessary to inject others for tighter integration with third-party tools. The `scheduler-k3s:labels:set` command can be used to perform this task. The command takes an app name and a required `--resource-type` flag.
|
||||
@@ -413,6 +448,8 @@ The following resource types are supported:
|
||||
- `traefik_ingressroute`
|
||||
- `traefik_middleware`
|
||||
|
||||
Label keys may contain `/` (e.g. Kubernetes-style keys such as `app.kubernetes.io/part-of`) and values may span multiple lines; both are preserved verbatim.
|
||||
|
||||
A `ps:restart` is required after setting labels in order to have them apply to running resources.
|
||||
|
||||
#### Removing a label
|
||||
@@ -426,6 +463,20 @@ dokku scheduler-k3s:labels:set node-js-app label.key --resource-type deployment
|
||||
|
||||
A `ps:restart` is required after removing labels in order to remove them from running resources.
|
||||
|
||||
#### Displaying labels
|
||||
|
||||
Configured labels can be inspected with the `scheduler-k3s:labels:report` command. The surface mirrors `scheduler-k3s:annotations:report`:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:labels:report
|
||||
dokku scheduler-k3s:labels:report node-js-app
|
||||
dokku scheduler-k3s:labels:report --global
|
||||
dokku scheduler-k3s:labels:report node-js-app --resource-type deployment
|
||||
dokku scheduler-k3s:labels:report node-js-app --process-type web --resource-type deployment
|
||||
dokku scheduler-k3s:labels:report node-js-app --format json
|
||||
dokku scheduler-k3s:labels:report node-js-app --scheduler-k3s-labels.global.deployment.label.key
|
||||
```
|
||||
|
||||
### Autoscaling
|
||||
|
||||
#### Workload Autoscaling
|
||||
@@ -444,7 +495,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 +527,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:
|
||||
@@ -562,10 +615,12 @@ dokku scheduler-k3s:autoscaling-auth:set $APP $TRIGGER_TYPE
|
||||
|
||||
##### Displaying an Authentication Resource report
|
||||
|
||||
To see a list of authentication resources managed by Dokku, run the `scheduler-k3s:autoscaling-auth:report` command.
|
||||
To see a list of authentication resources managed by Dokku, run the `scheduler-k3s:autoscaling-auth:report` command. Without arguments, the report iterates every app; passing an app name (or `--global`) scopes the report:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:autoscaling-auth:report
|
||||
dokku scheduler-k3s:autoscaling-auth:report node-js-app
|
||||
dokku scheduler-k3s:autoscaling-auth:report --global
|
||||
```
|
||||
|
||||
```
|
||||
@@ -656,21 +711,34 @@ The default value for the `kube-context` is an empty string, and will result in
|
||||
|
||||
### Customizing Helm Chart Properties
|
||||
|
||||
Dokku includes a number of helm charts by default with settings that are optimized for Dokku. That said, it may be useful to further customize the charts for a given environment. Users can customize which charts are installed by setting properties prefixed with `chart.$CHART_NAME.` with the `--global` flag.
|
||||
Dokku includes a number of helm charts by default with settings that are optimized for Dokku. That said, it may be useful to further customize the charts for a given environment. Chart overrides are managed via the `scheduler-k3s:charts:set` command, which takes a `<chart-name>.<property>` argument and a value. Chart overrides are always global because helm charts are not managed on a per-app basis.
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:set --global chart.cert-manager.version 1.13.3
|
||||
dokku scheduler-k3s:charts:set cert-manager.version 1.13.3
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Properties follow dot-notation, and are expanded according to Helm's internal logic. See the [Helm documentation](https://helm.sh/docs/helm/helm_install/#helm-install) for `helm install` for further details.
|
||||
|
||||
To unset a chart property, omit the value from the `scheduler-k3s:set` call:
|
||||
Property names may contain `/` (e.g. for Kubernetes-style annotation keys such as `service.annotations.prometheus.io/scrape`) and values may span multiple lines; both are preserved verbatim.
|
||||
|
||||
To unset a chart property, omit the value from the `scheduler-k3s:charts:set` call:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:set --global chart.cert-manager.version
|
||||
dokku scheduler-k3s:charts:set cert-manager.version
|
||||
```
|
||||
|
||||
Configured chart overrides can be inspected with the `scheduler-k3s:charts:report` command. Without an argument, it lists every chart known to Dokku along with any configured overrides; passing a chart name scopes the report to that chart:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:charts:report
|
||||
dokku scheduler-k3s:charts:report cert-manager
|
||||
dokku scheduler-k3s:charts:report --format json
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The legacy form `dokku scheduler-k3s:set --global chart.<chart>.<property> <value>` continues to work but is deprecated and will be removed in a future major release. Migrate to `scheduler-k3s:charts:set` instead.
|
||||
|
||||
A `scheduler-k3s:ensure-charts` command with the `--force` flag is required after changing any chart properties in order to have them apply. This will install all charts, not just the ones that have changed.
|
||||
|
||||
```shell
|
||||
@@ -683,6 +751,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 +839,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
|
||||
@@ -755,3 +853,28 @@ If unspecified for any task, the default reservation will be `.1` CPU and `128Mi
|
||||
|
||||
> [!NOTE]
|
||||
> Cron tasks retrieve resource limits based on the computed cron task ID.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `scheduler-k3s:report`. The JSON keys emitted by `scheduler-k3s:report --format json` are the same names with the leading `--scheduler-k3s-` stripped (e.g. `deploy-timeout`, `global-deploy-timeout`, `computed-deploy-timeout`). Legacy keys with the `scheduler-k3s-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `deploy-timeout` | app + global | `300s` | `--scheduler-k3s-deploy-timeout`, `--scheduler-k3s-global-deploy-timeout`, `--scheduler-k3s-computed-deploy-timeout` | Timeout for a single helm install/upgrade cycle |
|
||||
| `image-pull-secrets` | app + global | none | `--scheduler-k3s-image-pull-secrets`, `--scheduler-k3s-global-image-pull-secrets`, `--scheduler-k3s-computed-image-pull-secrets` | Comma-separated list of Kubernetes secret names used to pull private images |
|
||||
| `ingress-class` | global only | `nginx` | `--scheduler-k3s-global-ingress-class`, `--scheduler-k3s-computed-ingress-class` | IngressClass name used for app ingresses (e.g. `nginx`, `traefik`) |
|
||||
| `kube-context` | global only | none | `--scheduler-k3s-global-kube-context`, `--scheduler-k3s-computed-kube-context` | Kube context name used by helm and kubectl invocations |
|
||||
| `kubeconfig-path` | global only | `/etc/rancher/k3s/k3s.yaml` | `--scheduler-k3s-global-kubeconfig-path`, `--scheduler-k3s-computed-kubeconfig-path` | Filesystem path to the kubeconfig used to talk to the cluster |
|
||||
| `kustomize-root-path` | app + global | `config/kustomize` | `--scheduler-k3s-kustomize-root-path`, `--scheduler-k3s-global-kustomize-root-path`, `--scheduler-k3s-computed-kustomize-root-path` | Path within the app to a kustomize root applied after the helm install |
|
||||
| `letsencrypt-email-prod` | global only | none | `--scheduler-k3s-global-letsencrypt-email-prod`, `--scheduler-k3s-computed-letsencrypt-email-prod` | Contact email for the production cert-manager ClusterIssuer |
|
||||
| `letsencrypt-email-stag` | global only | none | `--scheduler-k3s-global-letsencrypt-email-stag`, `--scheduler-k3s-computed-letsencrypt-email-stag` | Contact email for the staging cert-manager ClusterIssuer |
|
||||
| `letsencrypt-server` | app + global | `prod` | `--scheduler-k3s-letsencrypt-server`, `--scheduler-k3s-global-letsencrypt-server`, `--scheduler-k3s-computed-letsencrypt-server` | ACME directory (`prod` or `staging`) used for app certificates |
|
||||
| `namespace` | app + global | `default` | `--scheduler-k3s-namespace`, `--scheduler-k3s-global-namespace`, `--scheduler-k3s-computed-namespace` | Kubernetes namespace into which the app's resources are installed |
|
||||
| `network-interface` | global only | `eth0` | `--scheduler-k3s-global-network-interface`, `--scheduler-k3s-computed-network-interface` | Host network interface used by k3s |
|
||||
| `rollback-on-failure` | app + global | `false` | `--scheduler-k3s-rollback-on-failure`, `--scheduler-k3s-global-rollback-on-failure`, `--scheduler-k3s-computed-rollback-on-failure` | When `true`, helm rolls back the release if a deploy fails |
|
||||
| `shm-size` | app + global | none | `--scheduler-k3s-shm-size`, `--scheduler-k3s-global-shm-size`, `--scheduler-k3s-computed-shm-size` | `/dev/shm` size override applied to app containers |
|
||||
| `token` | global only | none | `--scheduler-k3s-global-token` (masked as `*******` in default stdout output; the raw value is returned when queried via `--format json` or when this flag is requested explicitly) | Cluster join token used by `scheduler-k3s:cluster-add` |
|
||||
| `chart.<chart-name>.<property>` | global only | none | `--scheduler-k3s-global-chart.<chart-name>.<property>` (dynamic per chart/property) | Override a value injected into the helm chart named `<chart-name>` (one row per chart/property pair). Manage these via the dedicated `scheduler-k3s:charts:set` / `scheduler-k3s:charts:report` commands; the `scheduler-k3s:set`/`scheduler-k3s:report` form is deprecated. |
|
||||
|
||||
@@ -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:
|
||||
@@ -60,14 +80,16 @@ dokku scheduler:report
|
||||
Scheduler selected: herokuish
|
||||
=====> python-sample scheduler information
|
||||
Scheduler computed selected: dockerfile
|
||||
Scheduler global selected: herokuish
|
||||
Scheduler global selected:
|
||||
Scheduler selected: dockerfile
|
||||
=====> ruby-sample scheduler information
|
||||
Scheduler computed selected: herokuish
|
||||
Scheduler global selected: herokuish
|
||||
Scheduler computed selected: docker-local
|
||||
Scheduler global selected:
|
||||
Scheduler selected:
|
||||
```
|
||||
|
||||
The `selected` and `global-selected` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-selected` key holds the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default of `docker-local`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -76,6 +98,8 @@ dokku scheduler:report node-js-app
|
||||
|
||||
```
|
||||
=====> node-js-app scheduler information
|
||||
Scheduler computed selected: herokuish
|
||||
Scheduler global selected:
|
||||
Scheduler selected: herokuish
|
||||
```
|
||||
|
||||
@@ -123,3 +147,15 @@ Schedulers may decide to omit some functionality here, or use plugin triggers to
|
||||
Schedulers can use any tools available on the system to build the docker image, and may even be used to interact with off-server systems. The only current requirement is that the scheduler must have access to the image built in the build phase. If this is not the case, the registry plugin can be used to push the image to a registry that the scheduler software can access.
|
||||
|
||||
Deployment tasks are currently executed directly on the primary Dokku server.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `scheduler:report`. The JSON keys emitted by `scheduler:report --format json` are the same names with the leading `--scheduler-` stripped (e.g. `selected`, `global-selected`, `computed-selected`). Legacy keys with the `scheduler-` prefix are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `selected` | app + global | `docker-local` | `--scheduler-selected`, `--scheduler-global-selected`, `--scheduler-computed-selected` | Scheduler plugin used to deploy this app (`docker-local`, `k3s`, etc.) |
|
||||
| `shell` | app + global | none | `--scheduler-shell`, `--scheduler-global-shell`, `--scheduler-computed-shell` | Shell used by `enter`/`run` commands when entering a container |
|
||||
|
||||
@@ -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
|
||||
@@ -101,22 +95,24 @@ dokku checks:report
|
||||
Checks disabled list: none
|
||||
Checks skipped list: none
|
||||
Checks computed wait to retire: 60
|
||||
Checks global wait to retire: 60
|
||||
Checks global wait to retire:
|
||||
Checks wait to retire:
|
||||
=====> python-app checks information
|
||||
Checks disabled list: none
|
||||
Checks skipped list: none
|
||||
Checks computed wait to retire: 60
|
||||
Checks global wait to retire: 60
|
||||
Checks global wait to retire:
|
||||
Checks wait to retire:
|
||||
=====> ruby-app checks information
|
||||
Checks disabled list: _all_
|
||||
Checks skipped list: none
|
||||
Checks computed wait to retire: 60
|
||||
Checks global wait to retire: 60
|
||||
Checks global wait to retire:
|
||||
Checks wait to retire:
|
||||
```
|
||||
|
||||
The `wait-to-retire` and `global-wait-to-retire` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-wait-to-retire` key holds the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default of `60`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -126,10 +122,10 @@ dokku checks:report node-js-app
|
||||
```
|
||||
=====> node-js-app checks information
|
||||
Checks disabled list: none
|
||||
Checks skipped list: none
|
||||
Checks skipped list: none
|
||||
Checks computed wait to retire: 60
|
||||
Checks global wait to retire: 60
|
||||
Checks wait to retire:
|
||||
Checks global wait to retire:
|
||||
Checks wait to retire:
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
@@ -269,3 +265,11 @@ dokku checks:run node-js-app web.3
|
||||
-----> Running pre-flight checks
|
||||
Invalid container id specified (APP.web.3)
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `wait-to-retire` | app + global | `60` | `--checks-wait-to-retire`, `--checks-global-wait-to-retire`, `--checks-computed-wait-to-retire` | Seconds to wait between deploying the new container and stopping the old one |
|
||||
|
||||
@@ -411,6 +411,42 @@ elif [[ "$KEY_TYPE" == "key" ]]; then
|
||||
fi
|
||||
```
|
||||
|
||||
### `certs-remove`
|
||||
|
||||
- Description: Removes the SSL cert/key pair from an app and fires the `post-certs-remove` and `post-domains-update` triggers. Fails if no app-specific SSL endpoint is defined.
|
||||
- Invoked by:
|
||||
- Arguments: `$APP`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
# Removes the SSL endpoint for an app
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
APP="$1"
|
||||
|
||||
dokku certs:remove "$APP"
|
||||
```
|
||||
|
||||
### `certs-set`
|
||||
|
||||
- Description: Installs an SSL cert/key pair onto an app and fires the `post-certs-update` and `post-domains-update` triggers. `$CRT_FILE` and `$KEY_FILE` must be paths to readable PEM-encoded files.
|
||||
- Invoked by:
|
||||
- Arguments: `$APP $CRT_FILE $KEY_FILE`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
# Installs a cert/key pair for an app
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
APP="$1"; CRT_FILE="$2"; KEY_FILE="$3"
|
||||
|
||||
dokku certs:add "$APP" "$CRT_FILE" "$KEY_FILE"
|
||||
```
|
||||
|
||||
### `check-deploy`
|
||||
|
||||
- Description: Allows you to run checks on a deploy before Dokku allows the container to handle requests.
|
||||
@@ -545,6 +581,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 +845,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 +2940,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.10-2 (Mon Feb 22 23:20:37 CET 2016)"
|
||||
# wait for "==> build-arch: ==> Finished making: dokku 0.38.15-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.10
|
||||
docker pull dokku/dokku:0.38.15
|
||||
```
|
||||
|
||||
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.10
|
||||
dokku/dokku:0.38.15
|
||||
```
|
||||
|
||||
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.10
|
||||
image: dokku/dokku:0.38.15
|
||||
container_name: dokku
|
||||
network_mode: bridge
|
||||
ports:
|
||||
@@ -44,7 +44,38 @@ services:
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
The above command will start a new docker container that is ready when a message similar to `Runit started as PID 12345` appears.
|
||||
## Container readiness
|
||||
|
||||
The image ships with a Docker `HEALTHCHECK` that flips from `starting` to `healthy` once first-boot bootstrap is complete (skel restored, `plugin-list` plugins installed, core install triggers fired), nginx and sshd are accepting connections, and `dokku ps:restore` has finished. Until those conditions hold, the container is considered unhealthy and dependent services should not yet send traffic.
|
||||
|
||||
To check the current state from the host:
|
||||
|
||||
```shell
|
||||
docker inspect --format='{{.State.Health.Status}}' dokku
|
||||
```
|
||||
|
||||
Internally, the check is backed by a loopback-only HTTP endpoint:
|
||||
|
||||
```shell
|
||||
docker exec dokku curl -fsS http://127.0.0.1:18080/_dokku/health
|
||||
```
|
||||
|
||||
The endpoint binds to `127.0.0.1:18080` inside the container by design - it is not published to the host and does not interfere with user app vhosts on ports 80/443.
|
||||
|
||||
Compose dependents can gate on the healthcheck via `depends_on` with `condition: service_healthy`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
dokku:
|
||||
image: dokku/dokku:0.38.15
|
||||
# ...
|
||||
bootstrap:
|
||||
image: alpine:3.20
|
||||
command: ["echo", "dokku is ready"]
|
||||
depends_on:
|
||||
dokku:
|
||||
condition: service_healthy
|
||||
```
|
||||
|
||||
Dokku is run in the following configuration:
|
||||
|
||||
@@ -83,7 +114,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.10
|
||||
FROM dokku/dokku:0.38.15
|
||||
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
|
||||
```
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
# - `DOKKU_IP`
|
||||
# - `FORWARDED_PORT`.
|
||||
cd path/to/dokku
|
||||
|
||||
|
||||
# for most users
|
||||
vagrant up
|
||||
|
||||
|
||||
# windows users must instead use the following in an elevated command prompt
|
||||
vagrant up dokku-windows
|
||||
```
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
```shell
|
||||
# usually your key is already available under the current user's `~/.ssh/authorized_keys` file
|
||||
cat ~/.ssh/authorized_keys | dokku ssh-keys:add admin
|
||||
cat ~/.ssh/authorized_keys | sudo dokku ssh-keys:add admin
|
||||
|
||||
# you can use any domain you already have access to
|
||||
dokku domains:set-global dokku.me
|
||||
|
||||
@@ -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.10/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.37.10 bash bootstrap.sh
|
||||
wget -NP . https://dokku.com/install/v0.38.15/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.38.15 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)
|
||||
@@ -83,9 +84,6 @@ Please read the migration guides for each version in between your currently inst
|
||||
|
||||
#### Upgrading using `dokku-update`
|
||||
|
||||
> [!WARNING]
|
||||
> The `dokku-update` package currently does not support upgrading to a specific version of Dokku. If this is required by a particular migration guide, use the `apt` method for upgrading.
|
||||
|
||||
We provide a helpful binary called `dokku-update`. This is a recommended package that:
|
||||
|
||||
- Can be installed separately, so upgrading Dokku will not affect the running of this package.
|
||||
@@ -152,4 +150,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.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/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.10/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.15/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.15/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.15/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.15/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.15/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.15/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.15/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.15/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.15/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10</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.15</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.10 bash bootstrap.sh</span>
|
||||
<span class="command">sudo DOKKU_TAG=v0.38.15 bash bootstrap.sh</span>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ dokku network:report
|
||||
=====> node-js-app network information
|
||||
Network attach post create:
|
||||
Network attach post deploy:
|
||||
Network bind all interfaces: false
|
||||
Network bind all interfaces:
|
||||
Network computed attach post create:
|
||||
Network computed attach post deploy:
|
||||
Network computed bind all interfaces:false
|
||||
@@ -436,7 +436,7 @@ dokku network:report
|
||||
Network computed tld:
|
||||
Network global attach post create:
|
||||
Network global attach post deploy:
|
||||
Network global bind all interfaces:false
|
||||
Network global bind all interfaces:
|
||||
Network global initial network:
|
||||
Network global tld:
|
||||
Network initial network:
|
||||
@@ -445,7 +445,7 @@ dokku network:report
|
||||
=====> python-sample network information
|
||||
Network attach post create:
|
||||
Network attach post deploy:
|
||||
Network bind all interfaces: false
|
||||
Network bind all interfaces:
|
||||
Network computed attach post create:
|
||||
Network computed attach post deploy:
|
||||
Network computed bind all interfaces:false
|
||||
@@ -453,7 +453,7 @@ dokku network:report
|
||||
Network computed tld:
|
||||
Network global attach post create:
|
||||
Network global attach post deploy:
|
||||
Network global bind all interfaces:false
|
||||
Network global bind all interfaces:
|
||||
Network global initial network:
|
||||
Network global tld:
|
||||
Network initial network:
|
||||
@@ -462,7 +462,7 @@ dokku network:report
|
||||
=====> ruby-sample network information
|
||||
Network attach post create:
|
||||
Network attach post deploy:
|
||||
Network bind all interfaces: false
|
||||
Network bind all interfaces:
|
||||
Network computed attach post create:
|
||||
Network computed attach post deploy:
|
||||
Network computed bind all interfaces:false
|
||||
@@ -470,7 +470,7 @@ dokku network:report
|
||||
Network computed tld:
|
||||
Network global attach post create:
|
||||
Network global attach post deploy:
|
||||
Network global bind all interfaces:false
|
||||
Network global bind all interfaces:
|
||||
Network global initial network:
|
||||
Network global tld:
|
||||
Network initial network:
|
||||
@@ -478,6 +478,8 @@ dokku network:report
|
||||
Network web listeners:
|
||||
```
|
||||
|
||||
The per-app and `global-` keys for each property hold the raw values and are empty when nothing has been set. The `computed-` keys hold the effective value, falling back to the global value (where one has been set) and then to the built-in default (`false` for `bind-all-interfaces`, empty otherwise).
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -488,7 +490,7 @@ dokku network:report node-js-app
|
||||
=====> node-js-app network information
|
||||
Network attach post create:
|
||||
Network attach post deploy:
|
||||
Network bind all interfaces: false
|
||||
Network bind all interfaces:
|
||||
Network computed attach post create:
|
||||
Network computed attach post deploy:
|
||||
Network computed bind all interfaces:false
|
||||
@@ -496,7 +498,7 @@ dokku network:report node-js-app
|
||||
Network computed tld:
|
||||
Network global attach post create:
|
||||
Network global attach post deploy:
|
||||
Network global bind all interfaces:false
|
||||
Network global bind all interfaces:
|
||||
Network global initial network:
|
||||
Network global tld:
|
||||
Network initial network:
|
||||
@@ -509,3 +511,27 @@ You can pass flags which will output only the value of the specific information
|
||||
```shell
|
||||
dokku network:report node-js-app --network-bind-all-interfaces
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `network:report`. The JSON keys emitted by `network:report --format json` are the same names with the leading `--network-` stripped (e.g. `attach-post-create`, `global-attach-post-create`, `computed-attach-post-create`). Legacy keys with the `network-` prefix (e.g. `network-attach-post-create`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `attach-post-create` | app + global | none | `--network-attach-post-create`, `--network-global-attach-post-create`, `--network-computed-attach-post-create` | Networks attached to a container immediately after creation, before the deploy phase |
|
||||
| `attach-post-deploy` | app + global | none | `--network-attach-post-deploy`, `--network-global-attach-post-deploy`, `--network-computed-attach-post-deploy` | Networks attached to a container after it passes healthchecks |
|
||||
| `bind-all-interfaces` | app + global | `false` | `--network-bind-all-interfaces`, `--network-global-bind-all-interfaces`, `--network-computed-bind-all-interfaces` | When `true`, binds containers to `0.0.0.0` instead of the default Docker network address |
|
||||
| `initial-network` | app + global | none | `--network-initial-network`, `--network-global-initial-network`, `--network-computed-initial-network` | Network attached at container creation time |
|
||||
| `static-web-listener` | app only | none | `--network-static-web-listener` | Static `host:port` override used in proxy templates when no container is running |
|
||||
| `tld` | app + global | none | `--network-tld`, `--network-global-tld`, `--network-computed-tld` | Top-level domain appended to auto-generated app vhosts |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flag surfaces in `network:report` but is not managed by `network:set` - it is derived from the running app state:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--network-web-listeners` | Current `web` process listeners (host:port) for the deployed app |
|
||||
|
||||
@@ -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
|
||||
@@ -220,3 +220,13 @@ You can pass flags which will output only the value of the specific information
|
||||
```shell
|
||||
dokku ports:report node-js-app --ports-map
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `ports:report` but are not managed by `ports:set` - they are derived from the deploy:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--ports-map-detected` | Port mapping inferred from `EXPOSE` directives or the running container |
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
Dokku provides integration with the [Caddy](https://caddyserver.com/) proxy service by utilizing the Docker label-based integration implemented by [Caddy Docker Proxy](https://github.com/lucaslorentz/caddy-docker-proxy).
|
||||
|
||||
```
|
||||
caddy:report [<app>] [<flag>] # Displays a caddy report for one or more apps
|
||||
caddy:logs [--num num] [--tail] # Display caddy log output
|
||||
caddy:set <app> <property> (<value>) # Set or clear an caddy property for an app
|
||||
caddy:show-config <app> # Display caddy compose config
|
||||
caddy:start # Starts the caddy server
|
||||
caddy:stop # Stops the caddy server
|
||||
caddy:report [<app>] [<flag>] # Displays a caddy report for one or more apps
|
||||
caddy:logs [--num num] [--tail] # Display caddy log output
|
||||
caddy:set [<app>|--global] <property> (<value>) # Set or clear an caddy property for an app or globally
|
||||
caddy:show-config <app> # Display caddy compose config
|
||||
caddy:start # Starts the caddy server
|
||||
caddy:stop # Stops the caddy server
|
||||
```
|
||||
|
||||
## Requirements
|
||||
@@ -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.
|
||||
@@ -191,12 +191,25 @@ After enabling, the Caddy container will need to be restarted and apps will need
|
||||
|
||||
### Using Caddy's Internal TLS server
|
||||
|
||||
To switch to Caddy's internal TLS server for certificate provisioning, set the `tls-internal` property. This can only be set on a per-app basis.
|
||||
To switch to Caddy's internal TLS server for certificate provisioning, set the `tls-internal` property.
|
||||
|
||||
```shell
|
||||
dokku caddy:set node-js-app tls-internal true
|
||||
```
|
||||
|
||||
The default value may also be configured globally with the `--global` flag. Per-app values take precedence over the global value when set.
|
||||
|
||||
```shell
|
||||
dokku caddy:set --global tls-internal true
|
||||
```
|
||||
|
||||
Both the per-app and the global value may be unset by setting a blank value.
|
||||
|
||||
```shell
|
||||
dokku caddy:set node-js-app tls-internal
|
||||
dokku caddy:set --global tls-internal
|
||||
```
|
||||
|
||||
## Displaying Caddy reports for an app
|
||||
|
||||
You can get a report about the app's Caddy config using the `caddy:report` command:
|
||||
@@ -207,28 +220,23 @@ dokku caddy:report
|
||||
|
||||
```
|
||||
=====> node-js-app caddy information
|
||||
Caddy image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy letsencrypt email:
|
||||
Caddy letsencrypt server:
|
||||
Caddy log level: ERROR
|
||||
Caddy polling interval: 5s
|
||||
Caddy tls internal: false
|
||||
=====> python-app caddy information
|
||||
Caddy image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy letsencrypt email:
|
||||
Caddy letsencrypt server:
|
||||
Caddy log level: ERROR
|
||||
Caddy polling interval: 5s
|
||||
Caddy tls internal: false
|
||||
=====> ruby-app caddy information
|
||||
Caddy image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy letsencrypt email:
|
||||
Caddy letsencrypt server:
|
||||
Caddy log level: ERROR
|
||||
Caddy polling interval: 5s
|
||||
Caddy tls internal: false
|
||||
Caddy computed image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy computed letsencrypt email:
|
||||
Caddy computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Caddy computed log level: ERROR
|
||||
Caddy computed polling interval: 5s
|
||||
Caddy computed tls internal: false
|
||||
Caddy global image:
|
||||
Caddy global letsencrypt email:
|
||||
Caddy global letsencrypt server:
|
||||
Caddy global log level:
|
||||
Caddy global polling interval:
|
||||
Caddy global tls internal:
|
||||
Caddy tls internal:
|
||||
```
|
||||
|
||||
The `global-<prop>` keys hold the raw global value and are empty when nothing has been set globally. The `computed-<prop>` keys hold the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default. The bare `tls-internal` key holds the raw per-app value.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -237,16 +245,44 @@ dokku caddy:report node-js-app
|
||||
|
||||
```
|
||||
=====> node-js-app caddy information
|
||||
Caddy image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy letsencrypt email:
|
||||
Caddy letsencrypt server:
|
||||
Caddy log level: ERROR
|
||||
Caddy polling interval: 5s
|
||||
Caddy tls internal: false
|
||||
Caddy computed image: lucaslorentz/caddy-docker-proxy:2.7
|
||||
Caddy computed letsencrypt email:
|
||||
Caddy computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Caddy computed log level: ERROR
|
||||
Caddy computed polling interval: 5s
|
||||
Caddy computed tls internal: false
|
||||
Caddy global image:
|
||||
Caddy global letsencrypt email:
|
||||
Caddy global letsencrypt server:
|
||||
Caddy global log level:
|
||||
Caddy global polling interval:
|
||||
Caddy global tls internal:
|
||||
Caddy tls internal:
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku caddy:report node-js-app --caddy-image
|
||||
dokku caddy:report node-js-app --caddy-computed-image
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `image` | global only | _parsed from `plugins/caddy-vhosts/Dockerfile`_ | `--caddy-global-image`, `--caddy-computed-image` | Docker image used to run the Caddy container |
|
||||
| `letsencrypt-email` | global only | none | `--caddy-global-letsencrypt-email`, `--caddy-computed-letsencrypt-email` | Contact email enabling letsencrypt; empty disables https issuance |
|
||||
| `letsencrypt-server` | global only | `https://acme-v02.api.letsencrypt.org/directory` | `--caddy-global-letsencrypt-server`, `--caddy-computed-letsencrypt-server` | ACME directory used when requesting certificates |
|
||||
| `log-level` | global only | `ERROR` | `--caddy-global-log-level`, `--caddy-computed-log-level` | Caddy log level |
|
||||
| `polling-interval` | global only | `5s` | `--caddy-global-polling-interval`, `--caddy-computed-polling-interval` | Frequency at which Caddy polls the Docker API for label changes |
|
||||
| `tls-internal` | app + global | `false` | `--caddy-tls-internal`, `--caddy-global-tls-internal`, `--caddy-computed-tls-internal` | When `true`, uses Caddy's built-in self-signed TLS instead of letsencrypt |
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following properties are not managed by `caddy:set` but are recorded internally by the plugin:
|
||||
|
||||
| Property | Description | Source |
|
||||
|---|---|---|
|
||||
| `proxy-status` | `started`/`stopped` state of the caddy compose project | `cmd-caddy-start`/`cmd-caddy-stop` in `plugins/caddy-vhosts/command-functions` |
|
||||
|
||||
@@ -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.
|
||||
@@ -195,13 +205,20 @@ dokku haproxy:report
|
||||
|
||||
```
|
||||
=====> node-js-app haproxy information
|
||||
Haproxy image: byjg/easy-haproxy:4.0.0
|
||||
=====> python-app haproxy information
|
||||
Haproxy image: byjg/easy-haproxy:4.0.0
|
||||
=====> ruby-app haproxy information
|
||||
Haproxy image: byjg/easy-haproxy:4.0.0
|
||||
Haproxy computed image: byjg/easy-haproxy:4.0.0
|
||||
Haproxy computed letsencrypt email:
|
||||
Haproxy computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Haproxy computed log level: ERROR
|
||||
Haproxy computed refresh conf: 10
|
||||
Haproxy global image:
|
||||
Haproxy global letsencrypt email:
|
||||
Haproxy global letsencrypt server:
|
||||
Haproxy global log level:
|
||||
Haproxy global refresh conf:
|
||||
```
|
||||
|
||||
The `global-<prop>` keys hold the raw global value and are empty when nothing has been set globally. The `computed-<prop>` keys hold the effective value used at deploy time, falling back to the built-in default when the global value is empty.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -210,11 +227,42 @@ dokku haproxy:report node-js-app
|
||||
|
||||
```
|
||||
=====> node-js-app haproxy information
|
||||
Haproxy image: byjg/easy-haproxy:4.0.0
|
||||
Haproxy computed image: byjg/easy-haproxy:4.0.0
|
||||
Haproxy computed letsencrypt email:
|
||||
Haproxy computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Haproxy computed log level: ERROR
|
||||
Haproxy computed refresh conf: 10
|
||||
Haproxy global image:
|
||||
Haproxy global letsencrypt email:
|
||||
Haproxy global letsencrypt server:
|
||||
Haproxy global log level:
|
||||
Haproxy global refresh conf:
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku haproxy:report node-js-app --haproxy-image
|
||||
dokku haproxy:report node-js-app --haproxy-computed-image
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
All haproxy properties are global only. Set with `haproxy:set --global <property> <value>`.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `image` | global only | _parsed from `plugins/haproxy-vhosts/Dockerfile`_ | `--haproxy-global-image`, `--haproxy-computed-image` | Docker image used to run the Haproxy container |
|
||||
| `letsencrypt-email` | global only | none | `--haproxy-global-letsencrypt-email`, `--haproxy-computed-letsencrypt-email` | Contact email enabling letsencrypt; empty disables https issuance |
|
||||
| `letsencrypt-server` | global only | `https://acme-v02.api.letsencrypt.org/directory` | `--haproxy-global-letsencrypt-server`, `--haproxy-computed-letsencrypt-server` | ACME directory used when requesting certificates |
|
||||
| `log-level` | global only | `ERROR` | `--haproxy-global-log-level`, `--haproxy-computed-log-level` | Haproxy log level |
|
||||
| `refresh-conf` | global only | `10` | `--haproxy-global-refresh-conf`, `--haproxy-computed-refresh-conf` | Seconds between Haproxy polls of the Docker API for label changes |
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following properties are not managed by `haproxy:set` but are recorded internally by the plugin:
|
||||
|
||||
| Property | Description | Source |
|
||||
|---|---|---|
|
||||
| `proxy-status` | `started`/`stopped` state of the haproxy compose project | `cmd-haproxy-start`/`cmd-haproxy-stop` in `plugins/haproxy-vhosts/command-functions` |
|
||||
|
||||
@@ -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,107 @@ 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.
|
||||
On systems running nginx older than 1.19.4 (e.g., Debian Bullseye, which ships nginx 1.18.0), `ssl_reject_handshake` is not available. The postinst detects this and installs an HTTP-only variant instead:
|
||||
|
||||
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.
|
||||
```nginx
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
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.
|
||||
server_name _;
|
||||
access_log off;
|
||||
|
||||
return 444;
|
||||
}
|
||||
```
|
||||
|
||||
On these systems, HTTPS requests to unknown hosts are not rejected by the catch-all - nginx falls through to the lexicographically first port-443 server block and presents that block's certificate, the same behavior as before 0.38.0.
|
||||
|
||||
#### TLS handshake behavior
|
||||
|
||||
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.
|
||||
|
||||
| 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 on nginx 1.19.4+. On older nginx, falls through to the lexicographically first port-443 server block and presents its cert, producing a cert-mismatch error. |
|
||||
| HTTPS to the server's IP with no SNI, or with an SNI matching no app | Handshake rejected on nginx 1.19.4+. On older nginx, falls through to the first port-443 server block. |
|
||||
| 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 +349,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)
|
||||
@@ -506,3 +620,60 @@ See the [ports documentation](/docs/networking/port-management.md) for more info
|
||||
### Regenerating nginx config
|
||||
|
||||
See the [proxy documentation](/docs/networking/proxy-management.md#regenerating-proxy-config) for more information on how to rebuild the nginx proxy configuration for your app.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
All nginx-vhosts properties are settable at both the app and global scope.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `access-log-format` | app + global | none | `--nginx-access-log-format`, `--nginx-global-access-log-format`, `--nginx-computed-access-log-format` | Custom nginx `log_format` directive used for the access log |
|
||||
| `access-log-path` | app + global | _`{nginx-log-root}/{app}-access.log`_ | `--nginx-access-log-path`, `--nginx-global-access-log-path`, `--nginx-computed-access-log-path` | Path inside the nginx container where access logs are written |
|
||||
| `bind-address-ipv4` | app + global | none | `--nginx-bind-address-ipv4`, `--nginx-global-bind-address-ipv4`, `--nginx-computed-bind-address-ipv4` | IPv4 address the nginx server block binds to |
|
||||
| `bind-address-ipv6` | app + global | `::` | `--nginx-bind-address-ipv6`, `--nginx-global-bind-address-ipv6`, `--nginx-computed-bind-address-ipv6` | IPv6 address the nginx server block binds to |
|
||||
| `client-body-timeout` | app + global | `60s` | `--nginx-client-body-timeout`, `--nginx-global-client-body-timeout`, `--nginx-computed-client-body-timeout` | Time allowed to read the request body from the client |
|
||||
| `client-header-timeout` | app + global | `60s` | `--nginx-client-header-timeout`, `--nginx-global-client-header-timeout`, `--nginx-computed-client-header-timeout` | Time allowed to read the request header from the client |
|
||||
| `client-max-body-size` | app + global | `1m` | `--nginx-client-max-body-size`, `--nginx-global-client-max-body-size`, `--nginx-computed-client-max-body-size` | Maximum allowed request body size |
|
||||
| `disable-custom-config` | app + global | `false` | `--nginx-disable-custom-config`, `--nginx-global-disable-custom-config`, `--nginx-computed-disable-custom-config` | When `true`, ignores app-supplied `nginx.conf.d/*.conf` snippets |
|
||||
| `error-log-path` | app + global | _`{nginx-log-root}/{app}-error.log`_ | `--nginx-error-log-path`, `--nginx-global-error-log-path`, `--nginx-computed-error-log-path` | Path inside the nginx container where error logs are written |
|
||||
| `hsts` | app + global | `true` | `--nginx-hsts`, `--nginx-global-hsts`, `--nginx-computed-hsts` | When `true`, emits a `Strict-Transport-Security` header on HTTPS responses |
|
||||
| `hsts-include-subdomains` | app + global | `true` | `--nginx-hsts-include-subdomains`, `--nginx-global-hsts-include-subdomains`, `--nginx-computed-hsts-include-subdomains` | Adds the `includeSubDomains` directive to the HSTS header |
|
||||
| `hsts-max-age` | app + global | `15724800` | `--nginx-hsts-max-age`, `--nginx-global-hsts-max-age`, `--nginx-computed-hsts-max-age` | `max-age` value (seconds) in the HSTS header |
|
||||
| `hsts-preload` | app + global | `false` | `--nginx-hsts-preload`, `--nginx-global-hsts-preload`, `--nginx-computed-hsts-preload` | Adds the `preload` directive to the HSTS header |
|
||||
| `keepalive-timeout` | app + global | `75s` | `--nginx-keepalive-timeout`, `--nginx-global-keepalive-timeout`, `--nginx-computed-keepalive-timeout` | Time an idle keep-alive connection stays open |
|
||||
| `lingering-timeout` | app + global | `5s` | `--nginx-lingering-timeout`, `--nginx-global-lingering-timeout`, `--nginx-computed-lingering-timeout` | Time nginx waits for more client data when closing a connection |
|
||||
| `nginx-conf-sigil-path` | app + global | `nginx.conf.sigil` | `--nginx-nginx-conf-sigil-path`, `--nginx-global-nginx-conf-sigil-path`, `--nginx-computed-nginx-conf-sigil-path` | Path within the app to a custom `nginx.conf.sigil` template |
|
||||
| `nginx-service-command` | app + global | none | `--nginx-nginx-service-command`, `--nginx-global-nginx-service-command`, `--nginx-computed-nginx-service-command` | Override command used by `nginx:start`/`nginx:stop`/`nginx:reload` |
|
||||
| `proxy-buffer-size` | app + global | _system pagesize_ | `--nginx-proxy-buffer-size`, `--nginx-global-proxy-buffer-size`, `--nginx-computed-proxy-buffer-size` | Buffer size for reading the first part of the upstream response |
|
||||
| `proxy-buffering` | app + global | `on` | `--nginx-proxy-buffering`, `--nginx-global-proxy-buffering`, `--nginx-computed-proxy-buffering` | Whether nginx buffers upstream responses (`on` or `off`) |
|
||||
| `proxy-buffers` | app + global | _`8 {pagesize}`_ | `--nginx-proxy-buffers`, `--nginx-global-proxy-buffers`, `--nginx-computed-proxy-buffers` | Number and size of buffers used for an upstream response |
|
||||
| `proxy-busy-buffers-size` | app + global | _`2 * pagesize`_ | `--nginx-proxy-busy-buffers-size`, `--nginx-global-proxy-busy-buffers-size`, `--nginx-computed-proxy-busy-buffers-size` | Maximum buffer size that can be busy sending a response to the client |
|
||||
| `proxy-connect-timeout` | app + global | `60s` | `--nginx-proxy-connect-timeout`, `--nginx-global-proxy-connect-timeout`, `--nginx-computed-proxy-connect-timeout` | Time to establish a connection to the upstream |
|
||||
| `proxy-keepalive` | app + global | none | `--nginx-proxy-keepalive`, `--nginx-global-proxy-keepalive`, `--nginx-computed-proxy-keepalive` | Number of idle keep-alive connections to upstream servers held open per worker |
|
||||
| `proxy-read-timeout` | app + global | `60s` | `--nginx-proxy-read-timeout`, `--nginx-global-proxy-read-timeout`, `--nginx-computed-proxy-read-timeout` | Time to read a response from the upstream |
|
||||
| `proxy-send-timeout` | app + global | `60s` | `--nginx-proxy-send-timeout`, `--nginx-global-proxy-send-timeout`, `--nginx-computed-proxy-send-timeout` | Time to transmit a request to the upstream |
|
||||
| `send-timeout` | app + global | `60s` | `--nginx-send-timeout`, `--nginx-global-send-timeout`, `--nginx-computed-send-timeout` | Time between two successive write operations to the client |
|
||||
| `underscore-in-headers` | app + global | `off` | `--nginx-underscore-in-headers`, `--nginx-global-underscore-in-headers`, `--nginx-computed-underscore-in-headers` | Whether to allow underscores in client request header field names |
|
||||
| `x-forwarded-for-value` | app + global | `$remote_addr` | `--nginx-x-forwarded-for-value`, `--nginx-global-x-forwarded-for-value`, `--nginx-computed-x-forwarded-for-value` | Value used for the `X-Forwarded-For` header |
|
||||
| `x-forwarded-port-value` | app + global | `$server_port` | `--nginx-x-forwarded-port-value`, `--nginx-global-x-forwarded-port-value`, `--nginx-computed-x-forwarded-port-value` | Value used for the `X-Forwarded-Port` header |
|
||||
| `x-forwarded-proto-value` | app + global | `$scheme` | `--nginx-x-forwarded-proto-value`, `--nginx-global-x-forwarded-proto-value`, `--nginx-computed-x-forwarded-proto-value` | Value used for the `X-Forwarded-Proto` header |
|
||||
| `x-forwarded-ssl` | app + global | none | `--nginx-x-forwarded-ssl`, `--nginx-global-x-forwarded-ssl`, `--nginx-computed-x-forwarded-ssl` | Value used for the `X-Forwarded-Ssl` header (e.g. `on`/`off`) |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flag surfaces in `nginx:report` but is not managed by `nginx:set`:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--nginx-last-visited-at` | UNIX timestamp of the last request served by nginx for the app |
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following properties are recorded internally by the plugin and are not exposed via `nginx:report`:
|
||||
|
||||
| Property | Description | Source |
|
||||
|---|---|---|
|
||||
| `proxy-status` | `started`/`stopped` state of the nginx system service | `cmd-nginx-start`/`cmd-nginx-stop` |
|
||||
| `nginx-conf-sigil-migrated` | Migration sentinel set the first time a v1 template is rewritten to the current schema | `plugins/nginx-vhosts/install` writes `"true"` once the install-time migration runs |
|
||||
|
||||
@@ -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.
|
||||
@@ -124,6 +124,8 @@ The following folders within an app repository may have `*.conf` files that will
|
||||
- `openresty/http-includes/`: Injected in the `server` block serving http(s) requests for the app.
|
||||
- `openresty/http-location-includes/`: Injected in the `location` block that proxies to the app in the app's respective `server` block.
|
||||
|
||||
Custom snippets filenames may only include alphanumeric, underscore, and dot characters. For security reasons, filenames that contain other characters will be ignored.
|
||||
|
||||
### Label Management
|
||||
|
||||
The OpenResty plugin allows you to add custom container labels to apps. These labels are injected into containers during deployment and can be used to configure OpenResty behavior beyond what the plugin provides by default.
|
||||
@@ -275,5 +277,50 @@ dokku openresty:report node-js-app
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku openresty:report node-js-app --openresty-letsencrypt-email
|
||||
dokku openresty:report node-js-app --openresty-computed-letsencrypt-email
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
Five properties (`image`, `log-level`, `letsencrypt-email`, `letsencrypt-server`, `allowed-letsencrypt-domains-func-base64`) are global only. The rest may be set per-app or globally with `--global`; a global value applies to any app that has no per-app value, otherwise the built-in default is used.
|
||||
|
||||
Global-only properties expose two report flags: `--openresty-global-<property>` returns the raw stored value (empty when the property has never been set), while `--openresty-computed-<property>` returns the effective value (the global value if set, otherwise the built-in default).
|
||||
|
||||
App-or-global properties expose three report flags: `--openresty-<property>` returns the raw per-app value (empty when unset), `--openresty-global-<property>` returns the raw global value (empty when unset), and `--openresty-computed-<property>` returns the effective value, resolving the per-app value first, then the global value, then the built-in default.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `access-log-format` | app or global | none | `--openresty-access-log-format`, `--openresty-global-access-log-format`, `--openresty-computed-access-log-format` | Custom nginx `log_format` directive used for the access log |
|
||||
| `access-log-path` | app or global | _`/var/log/nginx/{app}-access.log`_ | `--openresty-access-log-path`, `--openresty-global-access-log-path`, `--openresty-computed-access-log-path` | Path inside the openresty container where access logs are written |
|
||||
| `allowed-letsencrypt-domains-func-base64` | global only | _allow-all stub_ | `--openresty-global-allowed-letsencrypt-domains-func-base64`, `--openresty-computed-allowed-letsencrypt-domains-func-base64` | Base64-encoded Lua function deciding which domains may request a letsencrypt certificate |
|
||||
| `bind-address-ipv4` | app or global | none | `--openresty-bind-address-ipv4`, `--openresty-global-bind-address-ipv4`, `--openresty-computed-bind-address-ipv4` | IPv4 address the openresty server block binds to |
|
||||
| `bind-address-ipv6` | app or global | `::` | `--openresty-bind-address-ipv6`, `--openresty-global-bind-address-ipv6`, `--openresty-computed-bind-address-ipv6` | IPv6 address the openresty server block binds to |
|
||||
| `client-body-timeout` | app or global | `60s` | `--openresty-client-body-timeout`, `--openresty-global-client-body-timeout`, `--openresty-computed-client-body-timeout` | Time allowed to read the request body from the client |
|
||||
| `client-header-timeout` | app or global | `60s` | `--openresty-client-header-timeout`, `--openresty-global-client-header-timeout`, `--openresty-computed-client-header-timeout` | Time allowed to read the request header from the client |
|
||||
| `client-max-body-size` | app or global | `1m` | `--openresty-client-max-body-size`, `--openresty-global-client-max-body-size`, `--openresty-computed-client-max-body-size` | Maximum allowed request body size |
|
||||
| `error-log-path` | app or global | _`/var/log/nginx/{app}-error.log`_ | `--openresty-error-log-path`, `--openresty-global-error-log-path`, `--openresty-computed-error-log-path` | Path inside the openresty container where error logs are written |
|
||||
| `hsts` | app or global | `true` | `--openresty-hsts`, `--openresty-global-hsts`, `--openresty-computed-hsts` | When `true`, emits a `Strict-Transport-Security` header on HTTPS responses |
|
||||
| `hsts-include-subdomains` | app or global | `true` | `--openresty-hsts-include-subdomains`, `--openresty-global-hsts-include-subdomains`, `--openresty-computed-hsts-include-subdomains` | Adds the `includeSubDomains` directive to the HSTS header |
|
||||
| `hsts-max-age` | app or global | `15724800` | `--openresty-hsts-max-age`, `--openresty-global-hsts-max-age`, `--openresty-computed-hsts-max-age` | `max-age` value (seconds) in the HSTS header |
|
||||
| `hsts-preload` | app or global | `false` | `--openresty-hsts-preload`, `--openresty-global-hsts-preload`, `--openresty-computed-hsts-preload` | Adds the `preload` directive to the HSTS header |
|
||||
| `image` | global only | _parsed from `plugins/openresty-vhosts/Dockerfile`_ | `--openresty-global-image`, `--openresty-computed-image` | Docker image used to run the openresty container |
|
||||
| `keepalive-timeout` | app or global | `75s` | `--openresty-keepalive-timeout`, `--openresty-global-keepalive-timeout`, `--openresty-computed-keepalive-timeout` | Time an idle keep-alive connection stays open |
|
||||
| `letsencrypt-email` | global only | none | `--openresty-global-letsencrypt-email`, `--openresty-computed-letsencrypt-email` | Contact email enabling letsencrypt; empty disables https issuance |
|
||||
| `letsencrypt-server` | global only | `https://acme-v02.api.letsencrypt.org/directory` | `--openresty-global-letsencrypt-server`, `--openresty-computed-letsencrypt-server` | ACME directory used when requesting certificates |
|
||||
| `lingering-timeout` | app or global | `5s` | `--openresty-lingering-timeout`, `--openresty-global-lingering-timeout`, `--openresty-computed-lingering-timeout` | Time openresty waits for more client data when closing a connection |
|
||||
| `log-level` | global only | `ERROR` | `--openresty-global-log-level`, `--openresty-computed-log-level` | Openresty log level |
|
||||
| `proxy-buffer-size` | app or global | _system pagesize_ | `--openresty-proxy-buffer-size`, `--openresty-global-proxy-buffer-size`, `--openresty-computed-proxy-buffer-size` | Buffer size for reading the first part of the upstream response |
|
||||
| `proxy-buffering` | app or global | `on` | `--openresty-proxy-buffering`, `--openresty-global-proxy-buffering`, `--openresty-computed-proxy-buffering` | Whether openresty buffers upstream responses (`on` or `off`) |
|
||||
| `proxy-buffers` | app or global | _`8 {pagesize}`_ | `--openresty-proxy-buffers`, `--openresty-global-proxy-buffers`, `--openresty-computed-proxy-buffers` | Number and size of buffers used for an upstream response |
|
||||
| `proxy-busy-buffers-size` | app or global | _`2 * pagesize`_ | `--openresty-proxy-busy-buffers-size`, `--openresty-global-proxy-busy-buffers-size`, `--openresty-computed-proxy-busy-buffers-size` | Maximum buffer size that can be busy sending a response to the client |
|
||||
| `proxy-connect-timeout` | app or global | `60s` | `--openresty-proxy-connect-timeout`, `--openresty-global-proxy-connect-timeout`, `--openresty-computed-proxy-connect-timeout` | Time to establish a connection to the upstream |
|
||||
| `proxy-read-timeout` | app or global | `60s` | `--openresty-proxy-read-timeout`, `--openresty-global-proxy-read-timeout`, `--openresty-computed-proxy-read-timeout` | Time to read a response from the upstream |
|
||||
| `proxy-send-timeout` | app or global | `60s` | `--openresty-proxy-send-timeout`, `--openresty-global-proxy-send-timeout`, `--openresty-computed-proxy-send-timeout` | Time to transmit a request to the upstream |
|
||||
| `send-timeout` | app or global | `60s` | `--openresty-send-timeout`, `--openresty-global-send-timeout`, `--openresty-computed-send-timeout` | Time between two successive write operations to the client |
|
||||
| `underscore-in-headers` | app or global | `off` | `--openresty-underscore-in-headers`, `--openresty-global-underscore-in-headers`, `--openresty-computed-underscore-in-headers` | Whether to allow underscores in client request header field names |
|
||||
| `x-forwarded-for-value` | app or global | `$remote_addr` | `--openresty-x-forwarded-for-value`, `--openresty-global-x-forwarded-for-value`, `--openresty-computed-x-forwarded-for-value` | Value used for the `X-Forwarded-For` header |
|
||||
| `x-forwarded-port-value` | app or global | `$server_port` | `--openresty-x-forwarded-port-value`, `--openresty-global-x-forwarded-port-value`, `--openresty-computed-x-forwarded-port-value` | Value used for the `X-Forwarded-Port` header |
|
||||
| `x-forwarded-proto-value` | app or global | `$scheme` | `--openresty-x-forwarded-proto-value`, `--openresty-global-x-forwarded-proto-value`, `--openresty-computed-x-forwarded-proto-value` | Value used for the `X-Forwarded-Proto` header |
|
||||
| `x-forwarded-ssl` | app or global | none | `--openresty-x-forwarded-ssl`, `--openresty-global-x-forwarded-ssl`, `--openresty-computed-x-forwarded-ssl` | Value used for the `X-Forwarded-Ssl` header (e.g. `on`/`off`) |
|
||||
|
||||
@@ -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.
|
||||
@@ -331,43 +331,30 @@ dokku traefik:report
|
||||
|
||||
```
|
||||
=====> node-js-app traefik information
|
||||
Traefik api enabled: false
|
||||
Traefik api vhost: traefik.dokku.me
|
||||
Traefik basic auth password: password
|
||||
Traefik basic auth username: user
|
||||
Traefik challenge mode: tls
|
||||
Traefik dashboard enabled: false
|
||||
Traefik dns provider:
|
||||
Traefik image: traefik:v2.8
|
||||
Traefik letsencrypt email:
|
||||
Traefik letsencrypt server:
|
||||
Traefik log level: ERROR
|
||||
=====> python-app traefik information
|
||||
Traefik api enabled: false
|
||||
Traefik api vhost: traefik.dokku.me
|
||||
Traefik basic auth password: password
|
||||
Traefik basic auth username: user
|
||||
Traefik challenge mode: tls
|
||||
Traefik dashboard enabled: false
|
||||
Traefik dns provider:
|
||||
Traefik image: traefik:v2.8
|
||||
Traefik letsencrypt email:
|
||||
Traefik letsencrypt server:
|
||||
Traefik log level: ERROR
|
||||
=====> ruby-app traefik information
|
||||
Traefik api enabled: false
|
||||
Traefik api vhost: traefik.dokku.me
|
||||
Traefik basic auth password: password
|
||||
Traefik basic auth username: user
|
||||
Traefik challenge mode: tls
|
||||
Traefik dashboard enabled: false
|
||||
Traefik dns provider:
|
||||
Traefik image: traefik:v2.8
|
||||
Traefik letsencrypt email:
|
||||
Traefik letsencrypt server:
|
||||
Traefik log level: ERROR
|
||||
Traefik computed api enabled: false
|
||||
Traefik computed api vhost: traefik.dokku.me
|
||||
Traefik computed challenge mode: tls
|
||||
Traefik computed dashboard enabled: false
|
||||
Traefik computed http entry point: http
|
||||
Traefik computed https entry point: https
|
||||
Traefik computed image: traefik:v2.8
|
||||
Traefik computed letsencrypt email:
|
||||
Traefik computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Traefik computed log level: ERROR
|
||||
Traefik global api enabled:
|
||||
Traefik global api vhost:
|
||||
Traefik global challenge mode:
|
||||
Traefik global dashboard enabled:
|
||||
Traefik global http entry point:
|
||||
Traefik global https entry point:
|
||||
Traefik global image:
|
||||
Traefik global letsencrypt email:
|
||||
Traefik global letsencrypt server:
|
||||
Traefik global log level:
|
||||
```
|
||||
|
||||
The `global-<prop>` keys hold the raw global value and are empty when nothing has been set globally. The `computed-<prop>` keys hold the effective value used at deploy time, falling back to the built-in default when the global value is empty.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -376,21 +363,63 @@ dokku traefik:report node-js-app
|
||||
|
||||
```
|
||||
=====> node-js-app traefik information
|
||||
Traefik api enabled: false
|
||||
Traefik api vhost: traefik.dokku.me
|
||||
Traefik basic auth password: password
|
||||
Traefik basic auth username: user
|
||||
Traefik challenge mode: tls
|
||||
Traefik dashboard enabled: false
|
||||
Traefik dns provider:
|
||||
Traefik image: traefik:v2.8
|
||||
Traefik letsencrypt email:
|
||||
Traefik letsencrypt server:
|
||||
Traefik log level: ERROR
|
||||
Traefik computed api enabled: false
|
||||
Traefik computed api vhost: traefik.dokku.me
|
||||
Traefik computed challenge mode: tls
|
||||
Traefik computed dashboard enabled: false
|
||||
Traefik computed http entry point: http
|
||||
Traefik computed https entry point: https
|
||||
Traefik computed image: traefik:v2.8
|
||||
Traefik computed letsencrypt email:
|
||||
Traefik computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory
|
||||
Traefik computed log level: ERROR
|
||||
Traefik global api enabled:
|
||||
Traefik global api vhost:
|
||||
Traefik global challenge mode:
|
||||
Traefik global dashboard enabled:
|
||||
Traefik global http entry point:
|
||||
Traefik global https entry point:
|
||||
Traefik global image:
|
||||
Traefik global letsencrypt email:
|
||||
Traefik global letsencrypt server:
|
||||
Traefik global log level:
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku traefik:report node-js-app --traefik-api-enabled
|
||||
dokku traefik:report node-js-app --traefik-computed-api-enabled
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
All traefik properties are global only. Set with `traefik:set --global <property> <value>`.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `api-enabled` | global only | `false` | `--traefik-global-api-enabled`, `--traefik-computed-api-enabled` | When `true`, enables the Traefik HTTP API |
|
||||
| `api-entry-point` | global only | none | `--traefik-global-api-entry-point`, `--traefik-computed-api-entry-point` | Name of the entry point used by the Traefik API |
|
||||
| `api-entry-point-address` | global only | none | `--traefik-global-api-entry-point-address`, `--traefik-computed-api-entry-point-address` | Address (`host:port`) the Traefik API listens on |
|
||||
| `api-vhost` | global only | `traefik.dokku.me` | `--traefik-global-api-vhost`, `--traefik-computed-api-vhost` | Virtual host that routes to the Traefik API |
|
||||
| `basic-auth-password` | global only | none | `--traefik-global-basic-auth-password`, `--traefik-computed-basic-auth-password` | Password for basic auth in front of the API/dashboard |
|
||||
| `basic-auth-username` | global only | none | `--traefik-global-basic-auth-username`, `--traefik-computed-basic-auth-username` | Username for basic auth in front of the API/dashboard |
|
||||
| `challenge-mode` | global only | `tls` | `--traefik-global-challenge-mode`, `--traefik-computed-challenge-mode` | ACME challenge method used by Traefik (`tls`, `http`, or `dns`) |
|
||||
| `dashboard-enabled` | global only | `false` | `--traefik-global-dashboard-enabled`, `--traefik-computed-dashboard-enabled` | When `true`, enables the Traefik dashboard |
|
||||
| `dns-provider` | global only | none | `--traefik-global-dns-provider`, `--traefik-computed-dns-provider` | Lego DNS provider name used when `challenge-mode` is `dns` |
|
||||
| `dns-provider-<ENV_VAR>` | global only | none | `--traefik-dns-provider-<env_var>` (masked as `*******` in the default stdout report; the raw value is returned when queried via `--format json` or when this flag is requested explicitly) | Per-provider environment variables passed to the Traefik container; `<ENV_VAR>` is the upstream variable name (e.g. `dns-provider-cloudflare-api-token`) |
|
||||
| `http-entry-point` | global only | `http` | `--traefik-global-http-entry-point`, `--traefik-computed-http-entry-point` | Entry point name handling plaintext HTTP traffic |
|
||||
| `https-entry-point` | global only | `https` | `--traefik-global-https-entry-point`, `--traefik-computed-https-entry-point` | Entry point name handling TLS-terminated HTTPS traffic |
|
||||
| `image` | global only | _parsed from `plugins/traefik-vhosts/Dockerfile`_ | `--traefik-global-image`, `--traefik-computed-image` | Docker image used to run the Traefik container |
|
||||
| `letsencrypt-email` | global only | none | `--traefik-global-letsencrypt-email`, `--traefik-computed-letsencrypt-email` | Contact email enabling letsencrypt; empty disables https issuance |
|
||||
| `letsencrypt-server` | global only | `https://acme-v02.api.letsencrypt.org/directory` | `--traefik-global-letsencrypt-server`, `--traefik-computed-letsencrypt-server` | ACME directory used when requesting certificates |
|
||||
| `log-level` | global only | `ERROR` | `--traefik-global-log-level`, `--traefik-computed-log-level` | Traefik log level |
|
||||
|
||||
### Internal properties
|
||||
|
||||
The following properties are not managed by `traefik:set` but are recorded internally by the plugin:
|
||||
|
||||
| Property | Description | Source |
|
||||
|---|---|---|
|
||||
| `proxy-status` | `started`/`stopped` state of the traefik compose project | `cmd-traefik-start`/`cmd-traefik-stop` in `plugins/traefik-vhosts/command-functions` |
|
||||
|
||||
@@ -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.
|
||||
@@ -100,16 +142,24 @@ dokku proxy:report
|
||||
|
||||
```
|
||||
=====> node-js-app proxy information
|
||||
Proxy computed type: nginx
|
||||
Proxy enabled: true
|
||||
Proxy type: nginx
|
||||
Proxy global type:
|
||||
Proxy type:
|
||||
=====> python-sample proxy information
|
||||
Proxy computed type: nginx
|
||||
Proxy enabled: true
|
||||
Proxy type: nginx
|
||||
Proxy global type:
|
||||
Proxy type:
|
||||
=====> ruby-sample proxy information
|
||||
Proxy computed type: nginx
|
||||
Proxy enabled: true
|
||||
Proxy type: nginx
|
||||
Proxy global type:
|
||||
Proxy type:
|
||||
```
|
||||
|
||||
The `type` and `global-type` keys hold the raw per-app and global value respectively, and are empty when nothing has been set. The `computed-type` key holds the effective value used at deploy time, falling back to the global value (where one has been set) and then to the built-in default of `nginx`.
|
||||
|
||||
You can run the command for a specific app also.
|
||||
|
||||
```shell
|
||||
@@ -118,14 +168,16 @@ dokku proxy:report node-js-app
|
||||
|
||||
```
|
||||
=====> node-js-app proxy information
|
||||
Proxy computed type: nginx
|
||||
Proxy enabled: true
|
||||
Proxy type: nginx
|
||||
Proxy global type:
|
||||
Proxy type:
|
||||
```
|
||||
|
||||
You can pass flags which will output only the value of the specific information you want. For example:
|
||||
|
||||
```shell
|
||||
dokku proxy:report node-js-app --proxy-type
|
||||
dokku proxy:report node-js-app --proxy-computed-type
|
||||
```
|
||||
|
||||
#### Proxy Port Scheme
|
||||
@@ -184,3 +236,25 @@ Proxy implementations may decide to omit some functionality here, or use plugin
|
||||
Individual proxy implementations _may_ trigger app rebuilds, depending on how proxy metadata is exposed for the proxy implementation.
|
||||
|
||||
Finally, proxy implementations _may_ install extra software needed for the proxy itself in whatever manner deemed fit. Proxy software can run on the host itself or within a running Docker container with either exposed ports or host networking.
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `proxy:report`. The JSON keys emitted by `proxy:report --format json` are the same names with the leading `--proxy-` stripped (e.g. `type`, `global-type`, `computed-type`). Legacy keys with the `proxy-` prefix (e.g. `proxy-type`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `disabled` | app only | `false` | `--proxy-disabled`, `--proxy-computed-disabled` (also exposed inverted as `--proxy-enabled`) | When `true`, disables proxy integration for this app (`proxy:enable`/`proxy:disable` write this) |
|
||||
| `proxy-port` | app + global | none | `--proxy-proxy-port`, `--proxy-global-proxy-port`, `--proxy-computed-proxy-port` | Override port used for the HTTP listener in the generated proxy config |
|
||||
| `proxy-ssl-port` | app + global | none | `--proxy-proxy-ssl-port`, `--proxy-global-proxy-ssl-port`, `--proxy-computed-proxy-ssl-port` | Override port used for the HTTPS listener in the generated proxy config |
|
||||
| `type` | app + global | `nginx` | `--proxy-type`, `--proxy-global-type`, `--proxy-computed-type` | Proxy implementation handling traffic for the app (`nginx`, `caddy`, `haproxy`, `traefik`, `openresty`, or a custom plugin) |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `proxy:report` but are not managed by `proxy:set`:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--proxy-enabled` | `true` when the app's `disabled` property is not `true` |
|
||||
|
||||
@@ -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]
|
||||
@@ -345,6 +367,20 @@ dokku ps:set node-js-app restart-policy on-failure
|
||||
dokku ps:set node-js-app restart-policy on-failure:20
|
||||
```
|
||||
|
||||
The default policy (`on-failure:10`) may be restored by passing an empty value:
|
||||
|
||||
```shell
|
||||
dokku ps:set node-js-app restart-policy
|
||||
```
|
||||
|
||||
A global default may also be set, and is used by any app that does not have an app-specific restart policy:
|
||||
|
||||
```shell
|
||||
dokku ps:set --global restart-policy always
|
||||
```
|
||||
|
||||
The effective policy applied to an app's containers is resolved as the app-specific value, then the global value, then the built-in `on-failure:10` default. This computed value can be inspected via the `--ps-computed-restart-policy` report flag.
|
||||
|
||||
Restart policies have no bearing on server reboot, and Dokku will always attempt to restart your apps at that point unless they were manually stopped.
|
||||
|
||||
Dokku also runs `dokku-event-listener` in the background via the system's init service. This monitors container state, performing the following actions:
|
||||
@@ -369,8 +405,10 @@ dokku ps:report
|
||||
Processes: 0
|
||||
Ps can scale: true
|
||||
Ps computed procfile path: Procfile2
|
||||
Ps computed restart policy: on-failure:10
|
||||
Ps global procfile path: Procfile
|
||||
Ps restart policy: on-failure:10
|
||||
Ps global restart policy:
|
||||
Ps restart policy:
|
||||
Ps procfile path: Procfile2
|
||||
Restore: true
|
||||
Running: false
|
||||
@@ -379,8 +417,10 @@ dokku ps:report
|
||||
Processes: 0
|
||||
Ps can scale: true
|
||||
Ps computed procfile path: Procfile
|
||||
Ps computed restart policy: on-failure:10
|
||||
Ps global procfile path: Procfile
|
||||
Ps restart policy: on-failure:10
|
||||
Ps global restart policy:
|
||||
Ps restart policy:
|
||||
Ps procfile path:
|
||||
Restore: true
|
||||
Running: false
|
||||
@@ -389,8 +429,10 @@ dokku ps:report
|
||||
Processes: 0
|
||||
Ps can scale: true
|
||||
Ps computed procfile path: Procfile
|
||||
Ps computed restart policy: on-failure:10
|
||||
Ps global procfile path: Procfile
|
||||
Ps restart policy: on-failure:10
|
||||
Ps global restart policy:
|
||||
Ps restart policy:
|
||||
Ps procfile path:
|
||||
Restore: true
|
||||
Running: false
|
||||
@@ -407,7 +449,9 @@ dokku ps:report node-js-app
|
||||
Deployed: false
|
||||
Processes: 0
|
||||
Ps can scale: true
|
||||
Ps restart policy: on-failure:10
|
||||
Ps computed restart policy: on-failure:10
|
||||
Ps global restart policy:
|
||||
Ps restart policy:
|
||||
Restore: true
|
||||
Running: false
|
||||
```
|
||||
@@ -429,3 +473,44 @@ 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
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `ps:report`. The JSON keys emitted by `ps:report --format json` are the same names with the leading `--ps-` stripped (e.g. `procfile-path`, `global-procfile-path`, `computed-procfile-path`). Legacy keys with the `ps-` prefix (e.g. `ps-procfile-path`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `dockerfile-start-cmd` | app only | none | `--ps-dockerfile-start-cmd`, `--ps-computed-dockerfile-start-cmd` | Override `CMD` for Dockerfile-based apps |
|
||||
| `procfile-path` | app + global | `Procfile` | `--ps-procfile-path`, `--ps-global-procfile-path`, `--ps-computed-procfile-path` | Path to the app's Procfile, relative to the build root |
|
||||
| `restart-policy` | app + global | `on-failure:10` | `--ps-restart-policy`, `--ps-global-restart-policy`, `--ps-computed-restart-policy` | Docker restart policy applied to deployed containers (`no`, `always`, `unless-stopped`, `on-failure[:max-retries]`) |
|
||||
| `restore` | app only | `true` | `--restore` | When `true`, the app is restarted automatically by `ps:retire` after a host reboot |
|
||||
| `skip-deploy` | app + global | `false` | `--ps-skip-deploy`, `--ps-global-skip-deploy`, `--ps-computed-skip-deploy` | When `true`, skips the deploy phase after a successful build |
|
||||
| `start-cmd` | app only | none | `--ps-start-cmd`, `--ps-computed-start-cmd` | Override start command for buildpack apps |
|
||||
| `stop-timeout-seconds` | app + global | `30` | `--ps-stop-timeout-seconds`, `--ps-global-stop-timeout-seconds`, `--ps-computed-stop-timeout-seconds` | Seconds Docker waits before SIGKILLing a container on stop |
|
||||
|
||||
### Read-only flags
|
||||
|
||||
The following flags surface in `ps:report` but are not managed by `ps:set` - they are derived from the running process state:
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--ps-can-scale` | `false` when the app's procfile or builder forbids horizontal scaling |
|
||||
| `--deployed` | `true` after the first successful deploy |
|
||||
| `--running` | `true` while any container for the app is running |
|
||||
| `--processes` | Total scaled process count across all proctypes |
|
||||
| `--status-<proctype>` | Container status and ID for each running proctype (one entry per Procfile process type) |
|
||||
|
||||
@@ -59,6 +59,7 @@ When running scheduled cron tasks, there are a few items to be aware of:
|
||||
- Each scheduled task is executed within a one-off `run` container, and thus inherit any docker-options specified for `run` containers. Resources are never shared between scheduled tasks.
|
||||
- Scheduled cron tasks are supported on a per-scheduler basis, and are currently only implemented by the `docker-local` scheduler.
|
||||
- Tasks for _all_ apps managed by the `docker-local` scheduler are written to a single crontab file owned by the `dokku` user. The `dokku` user's crontab should be considered reserved for this purpose.
|
||||
- The `command` is tokenized and exec'd directly inside the container. Shell features such as `;`, `&&`, `|`, and `>` are _not_ interpreted. Commands that contain a bare shell operator are rejected when `app.json` is validated at deploy time, so a malformed cron command will fail the deploy rather than silently fail to run. If shell semantics are required, wrap the command explicitly, for example `"sh -c 'do-thing > /var/log/x.log'"`.
|
||||
|
||||
|
||||
### Changing cron management settings
|
||||
@@ -68,7 +69,7 @@ The `cron` plugin provides a number of settings that can be used to managed depl
|
||||
| Name | Description | Level | Global Default |
|
||||
|-----------------------|----------------------------------------------------------------|-------------|----------------|
|
||||
| `mailfrom` | Sets the `MAILFROM` variable in a cron file for cron reporting | Global-only | empty string |
|
||||
| `maintenance` | Whether to have cron running for the app or not. | App-only | `false` |
|
||||
| `maintenance` | Whether to have cron running for the app or not. | App and Global | `false` |
|
||||
| `mailto` | Sets the `MAILTO` variable in a cron file for cron reporting | Global-only | empty string |
|
||||
|
||||
All settings can be set via the `cron:set` command. Using `maintenance` as an example:
|
||||
@@ -295,3 +296,17 @@ SHELL=/bin/bash
|
||||
### PLACE ALL CRON TASKS ABOVE, DO NOT REMOVE THE WHITESPACE AFTER THIS LINE
|
||||
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### Settable properties
|
||||
|
||||
> [!NOTE]
|
||||
> The `Report flags` column lists the CLI argument names accepted by `cron:report`. The JSON keys emitted by `cron:report --format json` are the same names with the leading `--cron-` stripped (e.g. `global-mailto`, `computed-mailto`, `maintenance`). Legacy keys with the `cron-` prefix (e.g. `cron-global-mailto`) are also emitted during the 0.38.x deprecation window and will be removed in a future major release.
|
||||
|
||||
| Property | Scope | Default | Report flags | Description |
|
||||
|---|---|---|---|---|
|
||||
| `mailfrom` | global only | none | `--cron-global-mailfrom`, `--cron-computed-mailfrom` | `From:` address used in cron failure emails |
|
||||
| `mailto` | global only | none | `--cron-global-mailto`, `--cron-computed-mailto` | Recipient address for cron failure emails; empty disables email |
|
||||
| `maintenance` | app + global | `false` | `--cron-maintenance`, `--cron-global-maintenance`, `--cron-computed-maintenance` | When `true`, suspends all cron tasks for the app (or globally) |
|
||||
| `maintenance.<cron-id>` | app only | `false` | `--cron-maintenance-<cron-id>` (dynamic per task) | Suspends an individual cron task by its computed ID (one row per task); written by `cron:suspend`/`cron:resume` |
|
||||
|
||||
@@ -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.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/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.10/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.15/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.15/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.15/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.15/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.15/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.15/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.15/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.15/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.15/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.37.10/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/gh/dokku/dokku@v0.38.15/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.10"
|
||||
version = "0.38.15"
|
||||
[plugin.config]
|
||||
|
||||
@@ -28,7 +28,7 @@ cmd-report() {
|
||||
dokku_log_info1 "herokuish version: "
|
||||
if [[ "$ARCHITECTURE" == "arm64" ]]; then
|
||||
dokku_log_warn "herokuish not supported on $ARCHITECTURE architecture"
|
||||
elif verify_image "$DOKKU_IMAGE"; then
|
||||
elif fn-verify-app-image "" "$DOKKU_IMAGE"; then
|
||||
"$DOCKER_BIN" container run $DOKKU_GLOBAL_RUN_ARGS --rm "$DOKKU_IMAGE" herokuish version | sed "s/^/ /"
|
||||
else
|
||||
dokku_log_warn "Herokuish image $DOKKU_IMAGE is not available"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core events logging plugin"
|
||||
version = "0.37.10"
|
||||
version = "0.38.15"
|
||||
[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,16 +18,15 @@ 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
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/crypto v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
|
||||
@@ -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.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA=
|
||||
github.com/onsi/gomega v1.41.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=
|
||||
@@ -42,19 +42,18 @@ github.com/tailscale/hujson v0.0.0-20250605163823-992244df8c5a h1:a6TNDN9CgG+cYj
|
||||
github.com/tailscale/hujson v0.0.0-20250605163823-992244df8c5a/go.mod h1:EbW0wDK/qEUYI0A5bqq0C2kF8JTQwWONmGDBbzsxxHo=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
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/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
|
||||
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
|
||||
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=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
|
||||
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
|
||||
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core app-json plugin"
|
||||
version = "0.37.10"
|
||||
version = "0.38.15"
|
||||
[plugin.config]
|
||||
|
||||
@@ -6,14 +6,24 @@ 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-computed-appjson-path": reportComputedAppjsonpath,
|
||||
"--app-json-global-appjson-path": reportGlobalAppjsonpath,
|
||||
}
|
||||
} else {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--app-json-computed-appjson-path": reportComputedAppjsonpath,
|
||||
"--app-json-global-appjson-path": reportGlobalAppjsonpath,
|
||||
"--app-json-appjson-path": reportAppjsonpath,
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
@@ -21,10 +31,18 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
trimPrefix := false
|
||||
uppercaseFirstCharacter := true
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp("app-json", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "app-json",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: true,
|
||||
})
|
||||
}
|
||||
|
||||
func reportComputedAppjsonpath(appName string) string {
|
||||
@@ -32,12 +50,15 @@ func reportComputedAppjsonpath(appName string) string {
|
||||
if value == "" {
|
||||
value = reportGlobalAppjsonpath(appName)
|
||||
}
|
||||
if value == "" {
|
||||
value = "app.json"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalAppjsonpath(appName string) string {
|
||||
return common.PropertyGetDefault("app-json", "--global", "appjson-path", "app.json")
|
||||
return common.PropertyGet("app-json", "--global", "appjson-path")
|
||||
}
|
||||
|
||||
func reportAppjsonpath(appName string) 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,11 @@ 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
|
||||
@@ -21,9 +21,9 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/crypto v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
|
||||
@@ -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.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA=
|
||||
github.com/onsi/gomega v1.41.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=
|
||||
@@ -38,18 +38,18 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
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/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
|
||||
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
|
||||
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=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
|
||||
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
|
||||
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core apps plugin"
|
||||
version = "0.37.10"
|
||||
version = "0.38.15"
|
||||
[plugin.config]
|
||||
|
||||
@@ -9,16 +9,26 @@ 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{
|
||||
"--app-global-disable-autocreation": reportGlobalDisableAutocreation,
|
||||
}
|
||||
} else {
|
||||
flags = map[string]common.ReportFunc{
|
||||
"--app-created-at": reportCreatedAt,
|
||||
"--app-deploy-source": reportDeploySource,
|
||||
"--app-deploy-source-metadata": reportDeploySourceMetadata,
|
||||
"--app-dir": reportDir,
|
||||
"--app-global-disable-autocreation": reportGlobalDisableAutocreation,
|
||||
"--app-locked": reportLocked,
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
@@ -26,10 +36,18 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
trimPrefix := false
|
||||
uppercaseFirstCharacter := true
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp("app", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "app",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: true,
|
||||
})
|
||||
}
|
||||
|
||||
func reportCreatedAt(appName string) string {
|
||||
@@ -52,6 +70,10 @@ func reportDir(appName string) string {
|
||||
return common.AppRoot(appName)
|
||||
}
|
||||
|
||||
func reportGlobalDisableAutocreation(appName string) string {
|
||||
return common.PropertyGet("apps", "--global", "disable-autocreation")
|
||||
}
|
||||
|
||||
func reportLocked(appName string) string {
|
||||
locked := "false"
|
||||
if appIsLocked(appName) {
|
||||
|
||||
@@ -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,15 @@ 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 {
|
||||
if appName != "--global" && property == "disable-autocreation" {
|
||||
common.LogFail("Property can only be specified globally")
|
||||
}
|
||||
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") {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user