sbt-native-packager icon indicating copy to clipboard operation
sbt-native-packager copied to clipboard

publishing one container to multiple docker registries

Open nefilim opened this issue 6 years ago • 3 comments

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?

nefilim avatar Aug 16 '19 17:08 nefilim

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 avatar Aug 17 '19 04:08 nigredo-tori

@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.

muuki88 avatar Aug 21 '19 08:08 muuki88

I'll reopen this. We may add this to the DockerPlugin docs.

muuki88 avatar Aug 21 '19 08:08 muuki88