mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-26 16:30:50 +01:00
Docker multi-arch builds (#2021)
Replaces the current docker build with a multi arch build powered by buildx. The new build creates two scm-manager docker image variants. One based on alpine which uses the openjdk distribution and the other based on debian and eclipse temurin: scmmanager/scm-manager:<version>-alpine - linux/amd64 - linux/arm64 scmmanager/scm-manager:<version>-debian - linux/amd64 - linux/arm64 - linux/arm/v7 scmmanager/scm-manager:<version> - linux/amd64 alpine based - linux/arm64 alpine based - linux/arm/v7 debian based scmmanager/scm-manager:latest - linux/amd64 alpine based - linux/arm64 alpine based - linux/arm/v7 debian based The development build produces only a single amd64 image at cloudogu/scm-manager with a snapshot version. Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
7
Jenkinsfile
vendored
7
Jenkinsfile
vendored
@@ -8,7 +8,7 @@ pipeline {
|
||||
|
||||
agent {
|
||||
docker {
|
||||
image 'scmmanager/java-build:11.0.9.1_1-2'
|
||||
image 'scmmanager/java-build:11.0.15_10-2'
|
||||
args '-v /var/run/docker.sock:/var/run/docker.sock --group-add 998'
|
||||
label 'docker'
|
||||
}
|
||||
@@ -285,14 +285,15 @@ void withChromaticEnvironment(Closure<Void> closure) {
|
||||
void withPublishEnivronment(Closure<Void> closure) {
|
||||
withCredentials([
|
||||
usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'ORG_GRADLE_PROJECT_packagesScmManagerUsername', passwordVariable: 'ORG_GRADLE_PROJECT_packagesScmManagerPassword'),
|
||||
usernamePassword(credentialsId: 'hub.docker.com-cesmarvin', usernameVariable: 'ORG_GRADLE_PROJECT_dockerUsername', passwordVariable: 'ORG_GRADLE_PROJECT_dockerPassword'),
|
||||
usernamePassword(credentialsId: 'cesmarvin-github', usernameVariable: 'ORG_GRADLE_PROJECT_gitHubUsername', passwordVariable: 'ORG_GRADLE_PROJECT_gitHubApiToken'),
|
||||
string(credentialsId: 'cesmarvin_npm_token', variable: 'ORG_GRADLE_PROJECT_npmToken'),
|
||||
file(credentialsId: 'oss-gpg-secring', variable: 'GPG_KEY_RING'),
|
||||
usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'GPG_KEY_ID', passwordVariable: 'GPG_KEY_PASSWORD')
|
||||
]) {
|
||||
withEnv(["ORG_GRADLE_PROJECT_npmEmail=cesmarvin@cloudogu.com"]) {
|
||||
closure.call()
|
||||
docker.withRegistry('', 'hub.docker.com-cesmarvin') {
|
||||
closure.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ for example:
|
||||
docker run --name scm -p 8080:8080 -v scm-home:/var/lib/scm scmmanager/scm-manager:2.0.0
|
||||
```
|
||||
|
||||
|
||||
## Persistence
|
||||
|
||||
It is recommended to create a persistent volume for the scm-manager home directory.
|
||||
@@ -60,7 +59,6 @@ docker run -e JAVA_OPTS="-Dsome.property=value" scmmanager/scm-manager:<version>
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Docker Compose
|
||||
|
||||
If you want to use the image with docker-compose have a look at the example below.
|
||||
@@ -79,3 +77,33 @@ services:
|
||||
volumes:
|
||||
scmhome: {}
|
||||
```
|
||||
|
||||
## Variants
|
||||
|
||||
We are offer two variants of the SCM-Manager docker image one with OpenJDK on Alpine and the other with Eclipse Temurin on Debian.
|
||||
|
||||
### scmmanager/scm-manager:<version>-alpine
|
||||
|
||||
This image uses the Alpine operating system and the OpenJDK distribution from the official apk repository.
|
||||
The image is available for the following os/architectures:
|
||||
|
||||
* linux/amd64
|
||||
* linux/arm64
|
||||
|
||||
### scmmanager/scm-manager:<version>-debian
|
||||
|
||||
This image uses the Debian operating system and the Eclipse Temurin JDK.
|
||||
The image is available for the following os/architectures:
|
||||
|
||||
* linux/amd64
|
||||
* linux/arm64
|
||||
* linux/arm/v7
|
||||
|
||||
### scmmanager/scm-manager:<version>
|
||||
|
||||
The default image is mainly an alias for the alpine variant, but there is no alpine variant for arm/v7.
|
||||
For arm/v7 the debian variant is used.
|
||||
|
||||
* linux/amd64 uses the alpine variant
|
||||
* linux/arm64 uses the alpine variant
|
||||
* linux/arm/v7 uses the debian variant
|
||||
|
||||
2
gradle/changelog/docker_multiarch.yml
Normal file
2
gradle/changelog/docker_multiarch.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
- type: added
|
||||
description: Docker images for linux/arm/v7 and linux/arm64 ([#2021](https://github.com/scm-manager/scm-manager/pull/2021))
|
||||
@@ -22,11 +22,33 @@
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
FROM adoptopenjdk/openjdk11:jdk-11.0.14_9-alpine-slim
|
||||
ENV SCM_HOME=/var/lib/scm
|
||||
ENV CACHE_DIR=/var/cache/scm/work
|
||||
# Create minimal java version
|
||||
FROM alpine:3.15.4 as jre-build
|
||||
|
||||
COPY . /
|
||||
RUN set -x \
|
||||
&& apk add --no-cache openjdk11-jdk openjdk11-jmods \
|
||||
&& jlink \
|
||||
--add-modules ALL-MODULE-PATH \
|
||||
--strip-debug \
|
||||
--no-man-pages \
|
||||
--no-header-files \
|
||||
--compress=2 \
|
||||
--output /javaruntime
|
||||
|
||||
|
||||
# ---
|
||||
|
||||
# SCM-Manager runtime
|
||||
FROM alpine:3.15.4 as runtime
|
||||
|
||||
ENV SCM_HOME /var/lib/scm
|
||||
ENV CACHE_DIR /var/cache/scm/work
|
||||
ENV JAVA_HOME /opt/java/openjdk
|
||||
ENV PATH "${JAVA_HOME}/bin:${PATH}"
|
||||
|
||||
COPY --from=jre-build /javaruntime "${JAVA_HOME}"
|
||||
COPY build/docker/etc /etc
|
||||
COPY build/docker/opt /opt
|
||||
|
||||
RUN set -x \
|
||||
# ttf-dejavu graphviz are required for the plantuml plugin
|
||||
@@ -38,10 +60,11 @@ RUN set -x \
|
||||
&& chown 1000:0 ${SCM_HOME} ${CACHE_DIR} \
|
||||
&& chmod -R g=u ${SCM_HOME} ${CACHE_DIR}
|
||||
|
||||
USER 1000
|
||||
|
||||
WORKDIR "/opt/scm-server"
|
||||
VOLUME ["${SCM_HOME}", "${CACHE_DIR}"]
|
||||
EXPOSE 8080
|
||||
USER 1000
|
||||
|
||||
# we us a high relative high start period,
|
||||
# because the start time depends on the number of installed plugins
|
||||
73
scm-packaging/docker/Dockerfile.debian
Normal file
73
scm-packaging/docker/Dockerfile.debian
Normal file
@@ -0,0 +1,73 @@
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
# Create minimal java version
|
||||
FROM eclipse-temurin:11.0.14.1_1-jdk-focal as jre-build
|
||||
|
||||
RUN jlink \
|
||||
--add-modules ALL-MODULE-PATH \
|
||||
--strip-debug \
|
||||
--no-man-pages \
|
||||
--no-header-files \
|
||||
--compress=2 \
|
||||
--output /javaruntime
|
||||
|
||||
# ---
|
||||
|
||||
# SCM-Manager runtime
|
||||
FROM debian:11.3-slim as runtime
|
||||
|
||||
ENV SCM_HOME /var/lib/scm
|
||||
ENV CACHE_DIR /var/cache/scm/work
|
||||
ENV JAVA_HOME /opt/java/openjdk
|
||||
ENV PATH "${JAVA_HOME}/bin:${PATH}"
|
||||
|
||||
COPY --from=jre-build /javaruntime "${JAVA_HOME}"
|
||||
COPY build/docker/etc /etc
|
||||
COPY build/docker/opt /opt
|
||||
|
||||
RUN set -x \
|
||||
&& apt-get update \
|
||||
# libfreetype6 libfontconfig1 graphviz
|
||||
&& apt-get install -y --no-install-recommends libfreetype6 libfontconfig1 graphviz mercurial bash ca-certificates \
|
||||
# use gid 0 for openshift compatibility
|
||||
&& useradd -d "${SCM_HOME}" -u 1000 -g 0 -m -s /bin/bash scm \
|
||||
&& mkdir -p ${SCM_HOME} ${CACHE_DIR} \
|
||||
&& chmod +x /opt/scm-server/bin/scm-server \
|
||||
# set permissions to group 0 for openshift compatibility
|
||||
&& chown 1000:0 ${SCM_HOME} ${CACHE_DIR} \
|
||||
&& chmod -R g=u ${SCM_HOME} ${CACHE_DIR}
|
||||
|
||||
USER 1000
|
||||
|
||||
WORKDIR "/opt/scm-server"
|
||||
VOLUME ["${SCM_HOME}", "${CACHE_DIR}"]
|
||||
EXPOSE 8080
|
||||
|
||||
# we us a high relative high start period,
|
||||
# because the start time depends on the number of installed plugins
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/scm/api/v2 || exit 1
|
||||
|
||||
ENTRYPOINT [ "/opt/scm-server/bin/scm-server" ]
|
||||
@@ -23,13 +23,12 @@
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id 'com.bmuschko.docker-remote-api' version '6.6.1'
|
||||
id 'org.scm-manager.packaging'
|
||||
id 'org.scm-manager.license'
|
||||
}
|
||||
|
||||
import org.gradle.util.VersionNumber
|
||||
import com.bmuschko.gradle.docker.tasks.image.*
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
configurations {
|
||||
server
|
||||
@@ -70,45 +69,76 @@ task context(type: Copy) {
|
||||
}
|
||||
}
|
||||
|
||||
task dockerImage(type: DockerBuildImage) {
|
||||
inputDir = file('build/docker')
|
||||
images = images()
|
||||
task setupBuilder() {
|
||||
doLast {
|
||||
def inspect = exec {
|
||||
commandLine = ["docker", "buildx", "inspect", "scm-builder"]
|
||||
ignoreExitValue = true
|
||||
}
|
||||
if (inspect.exitValue != 0) {
|
||||
exec {
|
||||
commandLine = ["docker", "run", "--privileged", "--rm", "tonistiigi/binfmt", "--install", "arm,arm64"]
|
||||
}
|
||||
exec {
|
||||
commandLine = ["docker", "buildx", "create", "--name", "scm-builder", "--driver", "docker-container", "--platform", "linux/arm/v7,linux/arm64/v8,linux/amd64"]
|
||||
}
|
||||
exec {
|
||||
commandLine = ["docker", "buildx", "inspect", "scm-builder"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task build(type: Exec) {
|
||||
commandLine = ["docker", "buildx", "bake", "--builder", "scm-builder", isSnapshot ? "dev": "prod"]
|
||||
environment "VERSION", dockerTag
|
||||
environment "COMMIT_SHA", revision
|
||||
environment "IMAGE", dockerRepository
|
||||
|
||||
doLast {
|
||||
File file = new File(project.buildDir, 'docker.tag')
|
||||
file.text = dockerTag
|
||||
}
|
||||
dependsOn 'context'
|
||||
dependsOn 'context', 'setupBuilder'
|
||||
}
|
||||
|
||||
def images() {
|
||||
if (isSnapshot) {
|
||||
return [
|
||||
"${dockerRepository}:${dockerTag}"
|
||||
]
|
||||
} else {
|
||||
// What about patch releases?
|
||||
// It is a good idea to push always latest
|
||||
return [
|
||||
"${dockerRepository}:${dockerTag}",
|
||||
"${dockerRepository}:latest"
|
||||
]
|
||||
}
|
||||
task pushImages(type: Exec) {
|
||||
commandLine = ["docker", "buildx", "bake", "--builder", "scm-builder", isSnapshot ? "dev": "prod", "--push"]
|
||||
environment "VERSION", dockerTag
|
||||
environment "COMMIT_SHA", revision
|
||||
environment "IMAGE", dockerRepository
|
||||
|
||||
dependsOn 'build'
|
||||
}
|
||||
|
||||
task publish(type: DockerPushImage) {
|
||||
images = images()
|
||||
if (project.hasProperty("dockerUsername") && project.hasProperty("dockerPassword")) {
|
||||
registryCredentials {
|
||||
username = project.property("dockerUsername")
|
||||
password = project.property("dockerPassword")
|
||||
task publish() {
|
||||
doLast {
|
||||
if (!isSnapshot) {
|
||||
// get digest of debian arm v7 image
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = ["docker", "buildx", "imagetools", "inspect", "--raw", "${dockerRepository}:${dockerTag}-debian"]
|
||||
standardOutput = stdout
|
||||
}
|
||||
def inspect = new JsonSlurper().parseText(stdout.toString())
|
||||
def manifest = inspect.manifests.find { m -> m.platform.architecture == "arm" }
|
||||
|
||||
// append arm image to manifest with version and without os suffix
|
||||
exec {
|
||||
commandLine = ["docker", "buildx", "imagetools", "create", "--append", "-t", "${dockerRepository}:${dockerTag}", "${dockerRepository}:${dockerTag}-debian@${manifest.digest}"]
|
||||
}
|
||||
// append arm image to latest manifest
|
||||
exec {
|
||||
commandLine = ["docker", "buildx", "imagetools", "create", "--append", "-t", "${dockerRepository}:latest", "${dockerRepository}:${dockerTag}-debian@${manifest.digest}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
dependsOn dockerImage
|
||||
dependsOn 'pushImages'
|
||||
}
|
||||
|
||||
task distribution(type: PackageYaml) {
|
||||
type = 'docker'
|
||||
dependsOn dockerImage
|
||||
dependsOn build
|
||||
}
|
||||
|
||||
artifacts {
|
||||
|
||||
86
scm-packaging/docker/docker-bake.hcl
Normal file
86
scm-packaging/docker/docker-bake.hcl
Normal file
@@ -0,0 +1,86 @@
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
group "prod" {
|
||||
targets = [
|
||||
"alpine",
|
||||
"debian"
|
||||
]
|
||||
}
|
||||
|
||||
variable "VERSION" {
|
||||
default = "unknown"
|
||||
}
|
||||
|
||||
variable "COMMIT_SHA" {
|
||||
default = "unknown"
|
||||
}
|
||||
|
||||
variable "IMAGE" {
|
||||
default = "docker.io/cloudogu/scm-manager"
|
||||
}
|
||||
|
||||
target "base" {
|
||||
context = "."
|
||||
args = {
|
||||
VERSION = VERSION
|
||||
COMMIT_SHA = COMMIT_SHA
|
||||
}
|
||||
labels = {
|
||||
"org.opencontainers.image.vendor" = "Cloudogu GmbH"
|
||||
"org.opencontainers.image.title" = "Official SCM-Manager image"
|
||||
"org.opencontainers.image.description" = "The easiest way to share and manage your Git, Mercurial and Subversion repositories"
|
||||
"org.opencontainers.image.url" = "https://scm-manager.org/"
|
||||
"org.opencontainers.image.source" = "https://github.com/scm-manager/docker"
|
||||
"org.opencontainers.image.licenses" = "MIT"
|
||||
"org.opencontainers.image.version" = VERSION
|
||||
"org.opencontainers.image.revision" = COMMIT_SHA
|
||||
}
|
||||
}
|
||||
|
||||
target "dev" {
|
||||
inherits = ["base"]
|
||||
dockerfile = "Dockerfile.alpine"
|
||||
tags = ["${IMAGE}:${VERSION}"]
|
||||
}
|
||||
|
||||
target "alpine" {
|
||||
inherits = ["base"]
|
||||
dockerfile = "Dockerfile.alpine"
|
||||
tags = [
|
||||
"${IMAGE}:latest",
|
||||
"${IMAGE}:${VERSION}",
|
||||
"${IMAGE}:${VERSION}-alpine"
|
||||
]
|
||||
platforms = ["linux/amd64", "linux/arm64/v8"]
|
||||
}
|
||||
|
||||
target "debian" {
|
||||
inherits = ["base"]
|
||||
dockerfile = "Dockerfile.debian"
|
||||
tags = [
|
||||
"${IMAGE}:${VERSION}-debian"
|
||||
]
|
||||
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"]
|
||||
}
|
||||
Reference in New Issue
Block a user