sbt-native-packager
sbt-native-packager copied to clipboard
publishing one container to multiple docker registries
I wonder if there's a pattern for publishing to multiple docker registries? I have the need currently to publish to a regular private hosted registry and to AWS ECR, I've implemented this with a multi module build and at least doesn't rebuild the container both times:
lazy val root = project
.in(file("."))
.settings(
commonSettings,
dockerAliases ++= Seq(
dockerAlias.value.withRegistryHost(Some("docker.private.com")),
dockerAlias.value.withRegistryHost(Some("account.dkr.ecr.cn-northwest-1.amazonaws.com.cn"))
)
)
.enablePlugins(JavaAppPackaging)
.enablePlugins(DockerPlugin)
lazy val dockerRegistryHere = project
.in(file("registry/here"))
.settings(
commonSettings,
dockerRepository := Some("docker.private.com"),
Docker / packageName := "xxx/yyy",
Docker / publishLocal := { (publishLocal in (root, Docker)).value }
).dependsOn(root)
.enablePlugins(DockerPlugin)
lazy val dockerRegistryCNECR = project
.in(file("registry/cnecr"))
.settings(
dockerRepository := Some("account.dkr.ecr.cn-northwest-1.amazonaws.com.cn"),
Docker / packageName := "xxx/yyy",
Docker / publishLocal := { (publishLocal in (root, Docker)).value },
Ecr / region := Region.getRegion(Regions.CN_NORTHWEST_1),
Ecr / repositoryName := (Docker / packageName).value,
Ecr / localDockerImage := (Docker / packageName).value + ":" + (version in Docker).value,
Ecr / push := ((Ecr / push) dependsOn (Ecr / login)).value
)
.enablePlugins(EcrPlugin)
.enablePlugins(DockerPlugin)
would love to generalize this further to support multiple registries of each type:
val dockerRegistries = settingKey[Seq[String]]("Docker Registries")
val ecrRegistries = settingKey[Seq[String]]("AWS ECR Registries")
looking for an suggestions on an approach ... wonder if it's possible to iterate those setting keys in a command and invoking the relevant task? Does sbt-native-packager already support this in some way?
I have zero experience with the DockerPlugin, but I know it does support publishing to multiple registries. Look at how dockerRepository is used - you can override dockerAliases with aliases in many registries, and DockerPlugin will push all of them. You actually have this in your root project!
The main problem in your case seems to be that you're using sbt-ecr, which only supports pushing to a single repository. Now, it is definitely possible to circumvent this by generating a subproject per each ECR repository (see sbt.AutoPlugin.derivedProjects), but it would be better (and probably easier) to make a PR to sbt-ecr with this feature.
PS: The default dockerAliases value can include multiple aliases. So in root you probably want to duplicate all of those:
dockerAliases := dockerAliases.value.flatMap { alias => Seq(
alias.withRegistryHost(Some("docker.private.com")),
alias.withRegistryHost(Some("account.dkr.ecr.cn-northwest-1.amazonaws.com.cn"))
)}
Also, your .enablePlugins calls should go before .settings. Otherwise, depending on how the plugin is written, it can overwrite some of your settings. sbt-native-packager strives to preserve these when possible, but that takes some discipline.
@nigredo-tori is correct. There [was a similar suggestion on gitter|https://gitter.im/sbt/sbt-native-packager?at=5d37a8fe437a3a134843d11d] and I'm totally fine with using the dockerAliases.
I'll reopen this. We may add this to the DockerPlugin docs.