Skip to content

Commit

Permalink
Add wolfi ess docker image (elastic#113810)
Browse files Browse the repository at this point in the history
(cherry picked from commit 54c83d7)
  • Loading branch information
breskeby committed Oct 4, 2024
1 parent c5d8e96 commit 7a6ffb7
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .buildkite/pipelines/periodic-packaging.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ steps:
steps:
- label: "{{matrix.image}} / packaging-tests-unix"
command: ./.ci/scripts/packaging-test.sh destructivePackagingTest
timeout_in_minutes: 300
timeout_in_minutes: 420
matrix:
setup:
image:
Expand Down
2 changes: 1 addition & 1 deletion .buildkite/pipelines/periodic-packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ steps:
steps:
- label: "{{matrix.image}} / packaging-tests-unix"
command: ./.ci/scripts/packaging-test.sh destructivePackagingTest
timeout_in_minutes: 300
timeout_in_minutes: 420
matrix:
setup:
image:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ public enum DockerBase {
"docker.elastic.co/wolfi/chainguard-base:latest@sha256:c16d3ad6cebf387e8dd2ad769f54320c4819fbbaa21e729fad087c7ae223b4d0",
"-wolfi",
"apk"
);
),

// Based on WOLFI above, with more extras. We don't set a base image because
// we programmatically extend from the Wolfi image.
WOLFI_ESS(null, "-wolfi-ess", "apk");

private final String image;
private final String suffix;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ private static String distributionProjectName(ElasticsearchDistribution distribu
if (distribution.getType() == InternalElasticsearchDistributionTypes.DOCKER_WOLFI) {
return projectName + "wolfi-docker" + archString + "-export";
}
if (distribution.getType() == InternalElasticsearchDistributionTypes.DOCKER_WOLFI_ESS) {
return projectName + "wolfi-ess-docker" + archString + "-export";
}
return projectName + distribution.getType().getName();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.gradle.internal.distribution;

import org.elasticsearch.gradle.ElasticsearchDistributionType;

public class DockerWolfiEssElasticsearchDistributionType implements ElasticsearchDistributionType {

DockerWolfiEssElasticsearchDistributionType() {}

@Override
public String getName() {
return "dockerWolfiEss";
}

@Override
public boolean isDocker() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class InternalElasticsearchDistributionTypes {
public static ElasticsearchDistributionType DOCKER_CLOUD = new DockerCloudElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_CLOUD_ESS = new DockerCloudEssElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_WOLFI = new DockerWolfiElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_WOLFI_ESS = new DockerWolfiEssElasticsearchDistributionType();

public static List<ElasticsearchDistributionType> ALL_INTERNAL = List.of(
DEB,
Expand All @@ -31,6 +32,7 @@ public class InternalElasticsearchDistributionTypes {
DOCKER_IRONBANK,
DOCKER_CLOUD,
DOCKER_CLOUD_ESS,
DOCKER_WOLFI
DOCKER_WOLFI,
DOCKER_WOLFI_ESS
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_IRONBANK;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_UBI;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_WOLFI;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_WOLFI_ESS;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.RPM;

/**
Expand Down Expand Up @@ -152,6 +153,7 @@ private static Map<ElasticsearchDistributionType, TaskProvider<?>> lifecycleTask
lifecyleTasks.put(DOCKER_CLOUD, project.getTasks().register(taskPrefix + ".docker-cloud"));
lifecyleTasks.put(DOCKER_CLOUD_ESS, project.getTasks().register(taskPrefix + ".docker-cloud-ess"));
lifecyleTasks.put(DOCKER_WOLFI, project.getTasks().register(taskPrefix + ".docker-wolfi"));
lifecyleTasks.put(DOCKER_WOLFI_ESS, project.getTasks().register(taskPrefix + ".docker-wolfi-ess"));
lifecyleTasks.put(ARCHIVE, project.getTasks().register(taskPrefix + ".archives"));
lifecyleTasks.put(DEB, project.getTasks().register(taskPrefix + ".packages"));
lifecyleTasks.put(RPM, lifecyleTasks.get(DEB));
Expand Down
13 changes: 12 additions & 1 deletion distribution/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ the [DockerBase] enum.
* UBI - the same as the default image, but based upon [RedHat's UBI
images][ubi], specifically their minimal flavour.
* Wolfi - the same as the default image, but based upon [Wolfi](https://github.com/wolfi-dev)
* Wolfi ESS - this directly extends the Wolfi image, and adds all ES plugins
that the ES build generates in an archive directory. It also sets an
environment variable that points at this directory. This allows plugins to
be installed from the archive instead of the internet, speeding up
deployment times. Furthermore this image has
* `filebeat` and `metricbeat` included
* `wget` included
* The `ENTRYPOINT` is just `/sbin/tini`, and the `CMD` is
`/app/elasticsearch.sh`. In normal use this file would be bind-mounted
in, but the image ships a stub version of this file so that the image
can still be tested.
* Iron Bank - this is the US Department of Defence's repository of digitally
signed, binary container images including both Free and Open-Source
software (FOSS) and Commercial off-the-shelf (COTS). In practice, this is
Expand All @@ -17,7 +28,7 @@ the [DockerBase] enum.
* `filebeat` and `metricbeat` are included
* `wget` is included
* The `ENTRYPOINT` is just `/bin/tini`, and the `CMD` is
`/app/elasticsearc.sh`. In normal use this file would be bind-mounted
`/app/elasticsearch.sh`. In normal use this file would be bind-mounted
in, but the image ships a stub version of this file so that the image
can still be tested.
* Cloud ESS - this directly extends the Cloud image, and adds all ES plugins
Expand Down
101 changes: 72 additions & 29 deletions distribution/docker/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import org.elasticsearch.gradle.Architecture
import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.internal.DockerBase
Expand All @@ -8,8 +7,10 @@ import org.elasticsearch.gradle.internal.docker.DockerSupportPlugin
import org.elasticsearch.gradle.internal.docker.DockerSupportService
import org.elasticsearch.gradle.internal.docker.ShellRetry
import org.elasticsearch.gradle.internal.docker.TransformLog4jConfigFilter
import org.elasticsearch.gradle.internal.docker.*
import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.util.GradleUtils
import org.elasticsearch.gradle.Architecture
import java.nio.file.Path
import java.time.temporal.ChronoUnit

Expand Down Expand Up @@ -99,9 +100,9 @@ String tiniArch = Architecture.current() == Architecture.AARCH64 ? 'arm64' : 'am

dependencies {
aarch64DockerSource project(":distribution:archives:linux-aarch64-tar")
aarch64DockerSourceTar project(path: ":distribution:archives:linux-aarch64-tar", configuration:"default")
aarch64DockerSourceTar project(path: ":distribution:archives:linux-aarch64-tar", configuration: "default")
dockerSource project(":distribution:archives:linux-tar")
dockerSourceTar project(path: ":distribution:archives:linux-tar", configuration:"default")
dockerSourceTar project(path: ":distribution:archives:linux-tar", configuration: "default")
log4jConfig project(path: ":distribution", configuration: 'log4jConfig')
tini "krallin:tini:0.19.0:${tiniArch}"
allPlugins project(path: ':plugins', configuration: 'allPlugins')
Expand All @@ -112,7 +113,7 @@ dependencies {
}

ext.expansions = { Architecture architecture, DockerBase base ->
def (major,minor) = VersionProperties.elasticsearch.split("\\.")
def (major, minor) = VersionProperties.elasticsearch.split("\\.")

// We tag our Docker images with various pieces of information, including a timestamp
// for when the image was built. However, this makes it impossible completely cache
Expand Down Expand Up @@ -216,7 +217,8 @@ elasticsearch_distributions {
}

interface Injected {
@Inject FileSystemOperations getFs()
@Inject
FileSystemOperations getFs()
}

tasks.named("preProcessFixture").configure {
Expand Down Expand Up @@ -300,7 +302,10 @@ void addBuildDockerContextTask(Architecture architecture, DockerBase base) {
// For some reason, the artifact name can differ depending on what repository we used.
rename ~/((?:file|metric)beat)-.*\.tar\.gz$/, "\$1-${VersionProperties.elasticsearch}.tar.gz"
}
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(project.gradle.sharedServices, DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME
)
onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) }
}

Expand Down Expand Up @@ -337,9 +342,9 @@ void addTransformDockerContextTask(Architecture architecture, DockerBase base) {
into "${project.buildDir}/docker-context/${archiveName}"

// Since we replaced the remote URL in the Dockerfile, copy in the required file
if(base == DockerBase.IRON_BANK) {
if (base == DockerBase.IRON_BANK) {
from(architecture == Architecture.AARCH64 ? configurations.aarch64DockerSourceTar : configurations.dockerSourceTar)
from (configurations.tini) {
from(configurations.tini) {
rename { _ -> 'tini' }
}
} else {
Expand All @@ -349,7 +354,10 @@ void addTransformDockerContextTask(Architecture architecture, DockerBase base) {
expansions(architecture, base).findAll { it.key != 'build_date' }.each { k, v ->
inputs.property(k, { v.toString() })
}
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(project.gradle.sharedServices, DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME
)
onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) }
}

Expand All @@ -373,7 +381,7 @@ private static List<String> generateTags(DockerBase base, Architecture architect
String image = "elasticsearch${base.suffix}"

String namespace = 'elasticsearch'
if (base == DockerBase.CLOUD || base == DockerBase.CLOUD_ESS) {
if (base == DockerBase.CLOUD || base == DockerBase.CLOUD_ESS || base == DockerBase.WOLFI_ESS) {
namespace += '-ci'
}

Expand Down Expand Up @@ -423,7 +431,10 @@ void addBuildDockerImageTask(Architecture architecture, DockerBase base) {
baseImages = [base.image]
}

Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(project.gradle.sharedServices, DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME
)
onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) }

}
Expand All @@ -435,13 +446,12 @@ void addBuildDockerImageTask(Architecture architecture, DockerBase base) {
}
}

void addBuildEssDockerImageTask(Architecture architecture) {
DockerBase base = DockerBase.CLOUD_ESS
void addBuildEssDockerImageTask(Architecture architecture, DockerBase dockerBase) {
String arch = architecture == Architecture.AARCH64 ? '-aarch64' : ''
String contextDir = "${project.buildDir}/docker-context/elasticsearch${base.suffix}-${VersionProperties.elasticsearch}-docker-build-context${arch}"
String contextDir = "${project.buildDir}/docker-context/elasticsearch${dockerBase.suffix}-${VersionProperties.elasticsearch}-docker-build-context${arch}"

final TaskProvider<Sync> buildContextTask =
tasks.register(taskName('build', architecture, base, 'DockerContext'), Sync) {
tasks.register(taskName('build', architecture, dockerBase, 'DockerContext'), Sync) {
into contextDir

final Path projectDir = project.projectDir.toPath()
Expand All @@ -450,28 +460,54 @@ void addBuildEssDockerImageTask(Architecture architecture) {
from configurations.allPlugins
}

from(projectDir.resolve("src/docker/Dockerfile.cloud-ess")) {
expand([
base_image: "elasticsearch${DockerBase.CLOUD.suffix}:${architecture.classifier}"
])
if (dockerBase == DockerBase.WOLFI_ESS) {
// If we're performing a release build, but `build.id` hasn't been set, we can
// infer that we're not at the Docker building stage of the build, and therefore
// we should skip the beats part of the build.
String buildId = providers.systemProperty('build.id').getOrNull()
boolean includeBeats = VersionProperties.isElasticsearchSnapshot() == true || buildId != null || useDra

if (includeBeats) {
from configurations.getByName("filebeat_${architecture.classifier}")
from configurations.getByName("metricbeat_${architecture.classifier}")
}
// For some reason, the artifact name can differ depending on what repository we used.
rename ~/((?:file|metric)beat)-.*\.tar\.gz$/, "\$1-${VersionProperties.elasticsearch}.tar.gz"
}

String baseSuffix = dockerBase == DockerBase.CLOUD_ESS ? DockerBase.CLOUD.suffix : DockerBase.WOLFI.suffix
from(projectDir.resolve("src/docker/Dockerfile.ess")) {
expand(
[
base_image: "elasticsearch${baseSuffix}:${architecture.classifier}",
docker_base: "${dockerBase.name().toLowerCase()}",
version: "${VersionProperties.elasticsearch}",
retry: ShellRetry
]
)
filter SquashNewlinesFilter
rename ~/Dockerfile\.cloud-ess$/, 'Dockerfile'
rename ~/Dockerfile\.ess$/, 'Dockerfile'
}
}

final TaskProvider<DockerBuildTask> buildDockerImageTask =
tasks.register(taskName("build", architecture, base, "DockerImage"), DockerBuildTask) {
tasks.register(taskName("build", architecture, dockerBase, "DockerImage"), DockerBuildTask) {

TaskProvider<DockerBuildTask> buildCloudTask = tasks.named(taskName("build", architecture, DockerBase.CLOUD, "DockerImage"))
inputs.files(buildCloudTask)
DockerBase base = dockerBase == DockerBase.CLOUD_ESS ? DockerBase.CLOUD : DockerBase.WOLFI

TaskProvider<DockerBuildTask> buildBaseTask = tasks.named(taskName("build", architecture, base, "DockerImage"))
inputs.files(buildBaseTask)

dockerContext.fileProvider(buildContextTask.map { it.getDestinationDir() })

noCache = BuildParams.isCi()
baseImages = []
tags = generateTags(base, architecture)
tags = generateTags(dockerBase, architecture)
platforms.add(architecture.dockerPlatform)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(project.gradle.sharedServices, DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME
)
onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) }

}
Expand All @@ -483,15 +519,16 @@ void addBuildEssDockerImageTask(Architecture architecture) {

for (final Architecture architecture : Architecture.values()) {
for (final DockerBase base : DockerBase.values()) {
if (base == DockerBase.CLOUD_ESS) {
if (base == DockerBase.CLOUD_ESS || base == DockerBase.WOLFI_ESS) {
continue
}
addBuildDockerContextTask(architecture, base)
addTransformDockerContextTask(architecture, base)
addBuildDockerImageTask(architecture, base)
}

addBuildEssDockerImageTask(architecture)
addBuildEssDockerImageTask(architecture, DockerBase.CLOUD_ESS)
addBuildEssDockerImageTask(architecture, DockerBase.WOLFI_ESS)
}

def exportDockerImages = tasks.register("exportDockerImages")
Expand All @@ -515,6 +552,8 @@ subprojects { Project subProject ->
base = DockerBase.CLOUD_ESS
} else if (subProject.name.contains('cloud-')) {
base = DockerBase.CLOUD
} else if (subProject.name.contains('wolfi-ess')) {
base = DockerBase.WOLFI_ESS
} else if (subProject.name.contains('wolfi-')) {
base = DockerBase.WOLFI
}
Expand All @@ -525,7 +564,8 @@ subprojects { Project subProject ->
(base == DockerBase.CLOUD ? 'cloud.tar' :
(base == DockerBase.CLOUD_ESS ? 'cloud-ess.tar' :
(base == DockerBase.WOLFI ? 'wolfi.tar' :
'docker.tar'))))
(base == DockerBase.WOLFI_ESS ? 'wolfi-ess.tar' :
'docker.tar')))))
final String artifactName = "elasticsearch${arch}${base.suffix}_test"

final String exportTaskName = taskName("export", architecture, base, 'DockerImage')
Expand All @@ -541,7 +581,10 @@ subprojects { Project subProject ->
tarFile,
"elasticsearch${base.suffix}:${architecture.classifier}"
dependsOn(parent.path + ":" + buildTaskName)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(project.gradle.sharedServices, DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME)
Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME
)
onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) }
}

Expand Down
13 changes: 0 additions & 13 deletions distribution/docker/src/docker/Dockerfile.cloud-ess

This file was deleted.

Loading

0 comments on commit 7a6ffb7

Please sign in to comment.