Merge pull request #8688 from dokku/8685-registry-image-repo-template-should-be-app-global-not-global-only

Promote registry image-repo-template to app + global
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-27 04:49:16 -04:00
committed by GitHub
5 changed files with 186 additions and 16 deletions

View File

@@ -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
@@ -220,7 +234,7 @@ dokku registry:set --global push-extra-tags
| 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` | global only | none | `--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` | Comma-separated list of additional tags pushed alongside the deploy tag |
| `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 |

View File

@@ -63,7 +63,10 @@ func GetDockerConfigArgs(appName string) []string {
}
func getImageRepoFromTemplate(appName string) (string, error) {
imageRepoTemplate := common.PropertyGet("registry", "--global", "image-repo-template")
imageRepoTemplate := strings.TrimSpace(reportImageRepoTemplate(appName))
if imageRepoTemplate == "" {
imageRepoTemplate = reportGlobalImageRepoTemplate(appName)
}
if imageRepoTemplate == "" {
return "", nil
}
@@ -131,11 +134,7 @@ func incrementTagVersion(appName string) (int, error) {
}
func getRegistryPushExtraTagsForApp(appName string) string {
value := common.PropertyGet("registry", appName, "push-extra-tags")
if value == "" {
value = common.PropertyGet("registry", "--global", "push-extra-tags")
}
return value
return reportComputedPushExtraTags(appName)
}
func pushToRegistry(appName string, tag int, imageID string, imageRepo string) error {

View File

@@ -3,10 +3,11 @@ package registry
var (
// DefaultProperties is a map of all valid registry properties with corresponding default property values
DefaultProperties = map[string]string{
"image-repo": "",
"push-on-release": "false",
"server": "",
"push-extra-tags": "",
"image-repo": "",
"image-repo-template": "",
"push-on-release": "false",
"server": "",
"push-extra-tags": "",
}
// GlobalProperties is a map of all valid global registry properties

View File

@@ -23,6 +23,8 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
"--registry-global-server": reportGlobalServer,
"--registry-computed-image-repo-template": reportComputedImageRepoTemplate,
"--registry-global-image-repo-template": reportGlobalImageRepoTemplate,
"--registry-computed-push-extra-tags": reportComputedPushExtraTags,
"--registry-global-push-extra-tags": reportGlobalPushExtraTags,
}
} else {
flags = map[string]common.ReportFunc{
@@ -35,9 +37,12 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
"--registry-global-server": reportGlobalServer,
"--registry-computed-image-repo-template": reportComputedImageRepoTemplate,
"--registry-global-image-repo-template": reportGlobalImageRepoTemplate,
"--registry-image-repo-template": reportImageRepoTemplate,
"--registry-server": reportServer,
"--registry-tag-version": reportTagVersion,
"--registry-push-extra-tags": reportPushExtraTags,
"--registry-global-push-extra-tags": reportGlobalPushExtraTags,
"--registry-computed-push-extra-tags": reportComputedPushExtraTags,
}
}
@@ -96,12 +101,20 @@ func reportComputedServer(appName string) string {
return strings.TrimSpace(server)
}
func reportImageRepoTemplate(appName string) string {
return common.PropertyGet("registry", appName, "image-repo-template")
}
func reportGlobalImageRepoTemplate(appName string) string {
return common.PropertyGet("registry", "--global", "image-repo-template")
}
func reportComputedImageRepoTemplate(appName string) string {
return reportGlobalImageRepoTemplate(appName)
value := strings.TrimSpace(reportImageRepoTemplate(appName))
if value == "" {
value = reportGlobalImageRepoTemplate(appName)
}
return value
}
func reportGlobalServer(appName string) string {
@@ -120,3 +133,18 @@ func reportTagVersion(appName string) string {
func reportPushExtraTags(appName string) string {
return common.PropertyGet("registry", appName, "push-extra-tags")
}
func reportGlobalPushExtraTags(appName string) string {
return common.PropertyGet("registry", "--global", "push-extra-tags")
}
func reportComputedPushExtraTags(appName string) string {
value := strings.TrimSpace(reportPushExtraTags(appName))
if value == "" {
value = reportGlobalPushExtraTags(appName)
}
if value == "" {
value = DefaultProperties["push-extra-tags"]
}
return value
}

View File

@@ -181,6 +181,83 @@ teardown() {
assert_success
}
@test "(registry:report) image-repo-template raw vs computed vs global" {
run /bin/bash -c "dokku registry:set --global image-repo-template"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-image-repo-template\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-global-image-repo-template\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo-template\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:set --global image-repo-template 'global-prefix/{{ .AppName }}'"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-image-repo-template\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-global-image-repo-template\"'"
assert_success
assert_output 'global-prefix/{{ .AppName }}'
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo-template\"'"
assert_success
assert_output 'global-prefix/{{ .AppName }}'
# The global template renders into the computed image-repo.
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo\"'"
assert_success
assert_output "global-prefix/$TEST_APP"
# Per-app template overrides the global template.
run /bin/bash -c "dokku registry:set $TEST_APP image-repo-template 'app-prefix/{{ .AppName }}-prod'"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-image-repo-template\"'"
assert_success
assert_output 'app-prefix/{{ .AppName }}-prod'
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-global-image-repo-template\"'"
assert_success
assert_output 'global-prefix/{{ .AppName }}'
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo-template\"'"
assert_success
assert_output 'app-prefix/{{ .AppName }}-prod'
# The per-app template flows through to the computed image-repo.
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo\"'"
assert_success
assert_output "app-prefix/$TEST_APP-prod"
# Unsetting the per-app template restores the global template behavior.
run /bin/bash -c "dokku registry:set $TEST_APP image-repo-template"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-image-repo-template\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo-template\"'"
assert_success
assert_output 'global-prefix/{{ .AppName }}'
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-image-repo\"'"
assert_success
assert_output "global-prefix/$TEST_APP"
run /bin/bash -c "dokku registry:set --global image-repo-template"
assert_success
}
@test "(registry:report) push-on-release raw vs computed vs global" {
run /bin/bash -c "dokku registry:set --global push-on-release"
assert_success
@@ -233,6 +310,8 @@ teardown() {
assert_success
run /bin/bash -c "dokku registry:set --global image-repo-template"
assert_success
run /bin/bash -c "dokku registry:set --global push-extra-tags"
assert_success
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-global-push-on-release\"'"
assert_success
@@ -258,12 +337,22 @@ teardown() {
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-global-push-extra-tags\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-computed-push-extra-tags\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:set --global push-on-release true"
assert_success
run /bin/bash -c "dokku registry:set --global server ghcr.io"
assert_success
run /bin/bash -c "dokku registry:set --global image-repo-template 'dokku/{{ APP }}'"
assert_success
run /bin/bash -c "dokku registry:set --global push-extra-tags latest,stable"
assert_success
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-global-push-on-release\"'"
assert_success
@@ -289,19 +378,51 @@ teardown() {
assert_success
assert_output 'dokku/{{ APP }}'
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-global-push-extra-tags\"'"
assert_success
assert_output "latest,stable"
run /bin/bash -c "dokku registry:report --global --format json | jq -r '.\"registry-computed-push-extra-tags\"'"
assert_success
assert_output "latest,stable"
run /bin/bash -c "dokku registry:set --global push-on-release"
assert_success
run /bin/bash -c "dokku registry:set --global server"
assert_success
run /bin/bash -c "dokku registry:set --global image-repo-template"
assert_success
run /bin/bash -c "dokku registry:set --global push-extra-tags"
assert_success
}
@test "(registry:report) push-extra-tags raw" {
@test "(registry:report) push-extra-tags raw vs computed vs global" {
run /bin/bash -c "dokku registry:set --global push-extra-tags"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-push-extra-tags\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-global-push-extra-tags\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-push-extra-tags\"'"
assert_success
assert_output ""
run /bin/bash -c "dokku registry:set --global push-extra-tags global-tag"
assert_success
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-global-push-extra-tags\"'"
assert_success
assert_output "global-tag"
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-push-extra-tags\"'"
assert_success
assert_output "global-tag"
run /bin/bash -c "dokku registry:set $TEST_APP push-extra-tags release,stable"
assert_success
@@ -309,8 +430,15 @@ teardown() {
assert_success
assert_output "release,stable"
run /bin/bash -c "dokku registry:report $TEST_APP --format json | jq -r '.\"registry-computed-push-extra-tags\"'"
assert_success
assert_output "release,stable"
run /bin/bash -c "dokku registry:set $TEST_APP push-extra-tags"
assert_success
run /bin/bash -c "dokku registry:set --global push-extra-tags"
assert_success
}
@test "(registry) registry:set server" {