elasticsearch/distribution/docker
Rene Groeschke 90cf9cd4f8
Fix IronBank hardening_manifest CI test (#124579) (#124589)
This commit fix the IronBank hardening_manifest CI test that expect the
hardening_manifest.yaml values to match `'^(?!\\s*$)[ -~|]*$'` regex:

```
| hardening_manifest           | ERROR    | Hardening Manifest failed jsonschema validation
| hardening_manifest           | ERROR    | Verify Hardening Manifest content
| hardening_manifest           | ERROR    | 'Rene Gröschke' does not match '^(?!\\s*$)[ -~|]*$'
```

43219286

cc @breskeby

<!-- Thank you for your interest in and contributing to Elasticsearch!
There are a few simple things to check before submitting your pull
request that can help with the review process. You should delete these
items from your submission, but they are here to help bring them to your
attention. -->

- Have you signed the [contributor license agreement](https://www.elastic.co/contributor-agreement)?
- Have you followed the [contributor guidelines](https://github.com/elastic/elasticsearch/blob/main/CONTRIBUTING.md)?
- If submitting code, have you built your formula locally prior to submission with `gradle check`?
- If submitting code, is your pull request against main? Unless there is a good reason otherwise, we prefer pull requests against main and will backport as needed.
- If submitting code, have you checked that your submission is for an [OS and architecture that we support](https://www.elastic.co/support/matrix#show_os)?
- If you are submitting this code for a class then read our [policy](https://github.com/elastic/elasticsearch/blob/main/CONTRIBUTING.md#contributing-as-part-of-a-class) for that.

(cherry picked from commit e5cf597782)

# Conflicts:
#	distribution/docker/src/docker/iron_bank/hardening_manifest.yaml

Co-authored-by: Julien Mailleret <8582351+jmlrt@users.noreply.github.com>
2025-03-12 07:52:00 +11:00
..
cloud-docker-aarch64-export Introduce Cloud docker variant (#74980) 2021-08-20 20:11:05 +01:00
cloud-docker-export Introduce Cloud docker variant (#74980) 2021-08-20 20:11:05 +01:00
cloud-ess-docker-aarch64-export Introduce Cloud docker variant (#74980) 2021-08-20 20:11:05 +01:00
cloud-ess-docker-export Introduce Cloud docker variant (#74980) 2021-08-20 20:11:05 +01:00
docker-aarch64-export Rename some Docker projects for consistency (#55150) 2020-04-14 22:07:42 +01:00
docker-export Introduce packaging tests for Docker (#46599) 2019-10-05 15:40:42 +01:00
ironbank-docker-aarch64-export Use architecture specific tag for building cloud-ess image (#90074) 2022-09-15 16:19:30 -07:00
ironbank-docker-export Build Docker images from exported contexts and test them (#70088) 2021-03-26 13:58:03 +00:00
src Fix IronBank hardening_manifest CI test (#124579) (#124589) 2025-03-12 07:52:00 +11:00
ubi-docker-aarch64-export Add UBI docker builds (#60742) 2020-08-18 09:27:23 +01:00
ubi-docker-export Add UBI docker builds (#60742) 2020-08-18 09:27:23 +01:00
wolfi-docker-aarch64-export Add chainguard docker image (#112103) 2024-09-06 10:32:42 -07:00
wolfi-docker-export Add chainguard docker image (#112103) 2024-09-06 10:32:42 -07:00
wolfi-ess-docker-aarch64-export Add wolfi ess docker image (#113810) (#114111) 2024-10-04 13:44:42 +02:00
wolfi-ess-docker-export Add wolfi ess docker image (#113810) (#114111) 2024-10-04 13:44:42 +02:00
build.gradle [8.16] Update Gradle wrapper to 8.13 (#122421) (#123876) 2025-03-06 02:08:55 +11:00
docker-compose.yml Disable deprecation log indexing in docker test (#85150) 2022-03-21 12:05:49 +01:00
docker-test-entrypoint.sh Ensure CI is run in FIPS 140 approved only mode (#64024) 2020-12-23 21:00:49 +02:00
README.md [8.17] Revert cloud wolfi migration (#119068) (#119103) 2024-12-20 03:22:05 +11:00

Elasticsearch Docker Distribution

The ES build can generate several types of Docker image. These are enumerated in the DockerBase enum.

  • Default - this is what most people use, and is based on Ubuntu

  • UBI - the same as the default image, but based upon RedHat's UBI images, specifically their minimal flavour.

  • Wolfi - the same as the default image, but based upon Wolfi

  • 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 another UBI build, this time on the regular UBI image, with extra hardening. See below for more details.

  • Cloud - this is mostly the same as the default image, with some notable differences:

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

The long-term goal is for both Cloud images to be retired in favour of the default image.

Build strategy

For all image flavours, the ES build implements a pipeline:

  1. Construct a Docker build context
  2. Transform the build context so that it is possible to build it locally
  3. Build the Docker image locally

Some images use (1) as the releasable artifact, some use (3).

NOTE: "Pipeline" isn't actually the correct term - in reality, each Gradle task depends on the one before it. Notably, it is the transform tasks that depend on a locally build .tar.gz Elasticsearch archive.

Releasing on Docker Hub

Elasticsearch is an official image on Docker Hub. On release day, we build the ES Docker image and upload it to Elastic's Docker registry. Separately, we submit a build context to Docker via the elastic/dockerfiles repository. Docker then builds the image, and uploads it to Docker Hub. Unfortunately, this is an asynchronous process, and we don't hear back if there's a failure, so even when everything works, there's a lag between releasing a new version of Elasticsearch, and the image being available on Docker Hub.

Being an official image puts additional constraints on how the Elasticsearch image is built.

  • It must extend another official image
  • It must fetch any required artifacts - they cannot be supplied in the build context.
  • It must be platform-independent i.e. it can build on ARM and x64

The transform step in the build strategy above replaces the curl command in the Dockerfile that fetches an Elasticsearch .tar.gz distribution with a COPY command, so that it is possible to build the ES image locally.

Iron Bank release process

Elastic does not release an Iron Bank image. Rather, for each release we provide a Docker build context, and Iron Bank build the image themselves using a custom build process.

The ES build still has a task to build an Iron Bank image, in order to test something close to what Iron Bank build. The ES build does this by transforming the files in the Docker build context slightly, and passing usable values for the build variables (we use the regular UBI image instead of the DoD one).

The important takeaway here is that the releasable artifact is the Iron Bank build context, not the image.

Multi-architecture images

We publish multi-architecture images images, for use on both x86_64 (Intel) and aarch64 (ARM). This works by essentially building two images, and combining them with a Docker manifest. The Elasticsearch Delivery team aren't responsible for this - rather, it happens during our unified release process.

To build multi-architecture images on x86_64 hosts using Docker1, you'll need buildx and ensure that it supports both linux/amd64 and linux/arm64 targets.

You can verify the supported targets using docker buildx ls. For example, the following output indicates that support for linux/arm64 is missing:

$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default * docker
  default default         running 20.10.21 linux/amd64, linux/386

On Linux x86_64 hosts, to enable linux-arm64 you need to install qemu-user-static-binfmt. Installation details depend on the Linux distribution but, as described in the getting started docs, running docker run --rm --privileged multiarch/qemu-user-static --reset -p yes will add the necessary support (but will not persist across reboots):

$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default * docker
  default default         running 20.10.21 linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

Testing

We have a suite of tests in the qa/os subproject. Most of the Docker tests are in the DockerTests class, but there are tests that use Docker in other test classes.

The tests are mostly concerned with ensuring that the image has been built correctly e.g. contents and permissions are correct. We also check that the custom behaviour in the docker-entrypoint.sh works as intended.

Reliability

We go to some lengths to try and make the Docker build resilient to transient network errors. This is why, when browsing the Dockerfile, you'll see many commands wrapped in looping logic, so that if e.g. package installation fails, we try again. We also perform explicit docker pull commands instead of relying on docker run to pull an image down automatically, so that we can wrap the pull part in a retry.

What are the export project for?

Our integration tests are set up so that the test task depends on the project that creates the required artifacts. Note, it doesn't depend on a task, but a project! Also, we used to use Vagrant for testing (this has largely since been abandoned), which meant we needed to be able to build an image locally, export it, and load it again inside a Vagrant VM.

Ideally this import / export stuff should be completely removed.