From 074a2fd8ed2de6f07be75b77c351e235959efff3 Mon Sep 17 00:00:00 2001 From: Denis Rechkunov Date: Thu, 4 Jul 2024 17:10:59 +0200 Subject: [PATCH] Make Wolfi a part of Docker packaging * New images with `-wolfi` suffix are created * The `-cloud` image is now based on Wolfi * Refactored the packaging spec for better readability --- dev-tools/packaging/packages.yml | 251 ++++++++++++------ .../docker/Dockerfile.elastic-agent.tmpl | 31 ++- 2 files changed, 190 insertions(+), 92 deletions(-) diff --git a/dev-tools/packaging/packages.yml b/dev-tools/packaging/packages.yml index 062e5f1164f..3fc122630a7 100644 --- a/dev-tools/packaging/packages.yml +++ b/dev-tools/packaging/packages.yml @@ -207,21 +207,55 @@ shared: 'data/{{.BeatName}}-{{ commit_short }}/otelcol.ps1': source: '{{ repo.RootDir }}/dev-tools/packaging/files/windows/otelcol.ps1' mode: 0755 - # windows not supported yet + # windows not supported yet # 'otel_samples': # source: '{{ repo.RootDir }}/internal/pkg/otel/samples/windows/' # mode: 0755 - - &agent_docker_spec - <<: *agent_binary_spec + - &docker_ubuntu_spec extra_vars: from: 'ubuntu:20.04' buildFrom: 'ubuntu:20.04' + image_name: '{{.BeatName}}' + - &docker_ubuntu_arm_spec + extra_vars: + from: 'arm64v8/ubuntu:20.04' + buildFrom: 'arm64v8/ubuntu:20.04' + image_name: '{{.BeatName}}' + + - &docker_ubi_spec + extra_vars: + from: 'docker.elastic.co/ubi9/ubi-minimal' + buildFrom: 'docker.elastic.co/ubi9/ubi-minimal' + image_name: '{{.BeatName}}-ubi' + - &docker_ubi_arm_spec + extra_vars: + from: 'arm64v8/docker.elastic.co/ubi9/ubi-minimal' + buildFrom: 'arm64v8/docker.elastic.co/ubi9/ubi-minimal' + image_name: '{{.BeatName}}-ubi' + + - &docker_wolfi_spec + extra_vars: + from: 'cgr.dev/chainguard/wolfi-base' + buildFrom: 'cgr.dev/chainguard/wolfi-base' + image_name: '{{.BeatName}}-wolfi' + - &docker_wolfi_arm_spec + extra_vars: + from: 'arm64v8/cgr.dev/chainguard/wolfi-base' + buildFrom: 'arm64v8/cgr.dev/chainguard/wolfi-base' + image_name: '{{.BeatName}}-wolfi' + + - &docker_elastic_spec + extra_vars: + repository: 'docker.elastic.co/beats' + + - &agent_docker_spec + <<: *agent_binary_spec + extra_vars: dockerfile: 'Dockerfile.elastic-agent.tmpl' docker_entrypoint: 'docker-entrypoint.elastic-agent.tmpl' user: '{{ .BeatName }}' linux_capabilities: '' - image_name: '' beats_install_path: "install" files: 'elastic-agent.yml': @@ -237,14 +271,10 @@ shared: {{ commit }} mode: 0644 - - &agent_docker_arm_spec - <<: *agent_docker_spec - extra_vars: - from: 'arm64v8/ubuntu:20.04' - buildFrom: 'arm64v8/ubuntu:20.04' - - &agent_docker_cloud_spec <<: *agent_docker_spec + # The cloud image is always based on Wolfi + <<: *docker_wolfi_spec extra_vars: image_name: '{{.BeatName}}-cloud' repository: 'docker.elastic.co/beats-ci' @@ -259,6 +289,7 @@ shared: source: '{{.AgentDropPath}}/archives/{{.GOOS}}-{{.AgentArchName}}.tar.gz/agentbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' mode: 0755 + # not different to the default image, kept for backwards-compatibility - &agent_docker_complete_spec <<: *agent_docker_spec extra_vars: @@ -408,8 +439,6 @@ shared: - &docker_spec <<: *binary_spec extra_vars: - from: 'ubuntu:20.04' - buildFrom: 'ubuntu:20.04' user: '{{ .BeatName }}' linux_capabilities: '' files: @@ -418,26 +447,6 @@ shared: mode: 0600 config: true - - &docker_arm_spec - <<: *docker_spec - extra_vars: - from: 'arm64v8/ubuntu:20.04' - buildFrom: 'arm64v8/ubuntu:20.04' - - - &docker_ubi_spec - extra_vars: - image_name: '{{.BeatName}}-ubi' - from: 'docker.elastic.co/ubi9/ubi-minimal' - - - &docker_arm_ubi_spec - extra_vars: - image_name: '{{.BeatName}}-ubi' - from: 'registry.access.redhat.com/ubi9/ubi-minimal:9.3' - - - &elastic_docker_spec - extra_vars: - repository: 'docker.elastic.co/beats' - # # License modifiers for Apache 2.0 # @@ -514,6 +523,13 @@ specs: types: [docker] spec: <<: *docker_spec + <<: *docker_ubuntu_spec + + - os: linux + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec - os: aix types: [tgz] @@ -555,7 +571,17 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_elastic_spec + <<: *apache_license_for_binaries + name: '{{.BeatName}}-oss' + + - os: linux + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_elastic_spec <<: *apache_license_for_binaries name: '{{.BeatName}}-oss' @@ -600,7 +626,16 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + - os: linux + arch: arm64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_ubuntu_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries - os: linux @@ -609,24 +644,32 @@ specs: spec: <<: *docker_spec <<: *docker_ubi_spec - <<: *elastic_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries - - os: linux arch: arm64 types: [docker] spec: - <<: *docker_arm_spec - <<: *elastic_docker_spec + <<: *docker_spec + <<: *docker_ubi_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries + - os: linux + arch: amd64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries - os: linux arch: arm64 types: [docker] spec: - <<: *docker_arm_spec - <<: *docker_arm_ubi_spec - <<: *elastic_docker_spec + <<: *docker_spec + <<: *docker_wolfi_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries - os: aix @@ -710,7 +753,19 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + files: + '{{.BeatName}}{{.BinaryExt}}': + source: ./{{.XPackDir}}/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} + - os: linux + arch: arm64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_ubuntu_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': @@ -722,30 +777,41 @@ specs: spec: <<: *docker_spec <<: *docker_ubi_spec - <<: *elastic_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./{{.XPackDir}}/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - os: linux arch: arm64 types: [docker] spec: - <<: *docker_arm_spec - <<: *elastic_docker_spec + <<: *docker_spec + <<: *docker_ubi_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./{{.XPackDir}}/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} + - os: linux + arch: amd64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + files: + '{{.BeatName}}{{.BinaryExt}}': + source: ./{{.XPackDir}}/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - os: linux arch: arm64 types: [docker] spec: - <<: *docker_arm_spec - <<: *docker_arm_ubi_spec - <<: *elastic_docker_spec + <<: *docker_spec + <<: *docker_wolfi_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': @@ -809,105 +875,123 @@ specs: <<: *deb_rpm_agent_spec <<: *elastic_license_for_deb_rpm + ######## Docker images ######### + #### Ubuntu-based images #### + # Complete image gets a 'complete' variant for synthetics and other large + # packages too big to fit in the main image - os: linux arch: amd64 types: [docker] spec: - <<: *agent_docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *agent_docker_complete_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - # Complete image gets a 'complete' variant for synthetics and other large - # packages too big to fit in the main image - os: linux - arch: amd64 + arch: arm64 types: [docker] spec: - <<: *agent_docker_spec + <<: *docker_ubuntu_arm_spec <<: *agent_docker_complete_spec - <<: *elastic_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - # Cloud specific docker image - os: linux arch: amd64 types: [docker] spec: - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec <<: *agent_docker_spec - <<: *agent_docker_cloud_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - os: linux - arch: amd64 + arch: arm64 types: [docker] spec: + <<: *docker_ubuntu_arm_spec <<: *agent_docker_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + files: + '{{.BeatName}}{{.BinaryExt}}': + source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} + #### ubi-based #### + - os: linux + arch: amd64 + types: [docker] + spec: <<: *docker_ubi_spec - <<: *elastic_docker_spec + <<: *agent_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - os: linux arch: arm64 types: [docker] spec: - <<: *agent_docker_arm_spec - <<: *elastic_docker_spec + <<: *docker_ubi_arm_spec + <<: *agent_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - # Complete image gets a 'complete' variant for synthetics and other large - # packages too big to fit in the main image + #### wolfi-based #### + #### Cloud specific docker images #### - os: linux - arch: arm64 + arch: amd64 types: [docker] spec: - <<: *agent_docker_arm_spec - <<: *agent_docker_complete_spec - <<: *elastic_docker_spec + <<: *docker_wolfi_spec + <<: *agent_docker_cloud_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - # Cloud specific docker image - os: linux arch: arm64 types: [docker] spec: - <<: *elastic_docker_spec - <<: *agent_docker_arm_spec + <<: *docker_wolfi_arm_spec <<: *agent_docker_cloud_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + files: + '{{.BeatName}}{{.BinaryExt}}': + source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} + - os: linux + arch: amd64 + types: [docker] + spec: + <<: *docker_wolfi_spec + <<: *agent_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} - - os: linux arch: arm64 types: [docker] spec: - <<: *agent_docker_arm_spec - <<: *docker_arm_ubi_spec - <<: *elastic_docker_spec + <<: *docker_wolfi_arm_spec + <<: *agent_docker_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} + ######## End Docker images ######## - os: aix types: [tgz] @@ -939,8 +1023,9 @@ specs: - os: linux types: [docker] spec: + <<: *docker_wolfi_spec <<: *agent_docker_spec - <<: *elastic_docker_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': diff --git a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl index 81fab29041a..5bf0c769f5f 100644 --- a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl +++ b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl @@ -8,6 +8,10 @@ FROM {{ .buildFrom }} AS home COPY beat {{ $beatHome }} +{{- if contains .buildFrom "ubi-minimal" }} +RUN for iter in {1..10}; do microdnf update -y && microdnf install -y findutils shadow-utils && microdnf clean all && exit_code=0 && break || exit_code=$? && echo "microdnf error: retry $iter in 10s" && sleep 10; done; (exit $exit_code) +{{- end }} + RUN true && \ # ECE needs to create config here under non-1000 user chmod 0777 {{ $beatHome}} && \ @@ -30,9 +34,11 @@ RUN true && \ (chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/pf-elastic-symbolizer || true) && \ (chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/pf-host-agent || true) && \ find {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components -name "*.yml*" -type f -exec chmod 0644 {} \; && \ + {{- range $i, $modulesd := .ModulesDirs }} chmod 0775 {{ $beatHome}}/{{ $modulesd }} && \ {{- end }} + {{- if contains .image_name "-cloud" }} mkdir -p /opt/agentbeat /opt/filebeat /opt/metricbeat && \ cp -f {{ $beatHome }}/data/cloud_downloads/filebeat.sh /opt/filebeat/filebeat && \ @@ -50,8 +56,9 @@ ENV BEAT_SETUID_AS={{ .user }} {{- if contains .from "ubi-minimal" }} RUN for iter in {1..10}; do microdnf update -y && microdnf install -y tar gzip findutils shadow-utils && microdnf clean all && exit_code=0 && break || exit_code=$? && echo "microdnf error: retry $iter in 10s" && sleep 10; done; (exit $exit_code) -{{- else }} +{{- end }} +{{- if contains .from "ubuntu" }} RUN for iter in {1..10}; do \ apt-get update -y && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes ca-certificates curl gawk libcap2-bin xz-utils && \ @@ -61,6 +68,16 @@ RUN for iter in {1..10}; do \ (exit $exit_code) {{- end }} +{{- if contains .from "wolfi" }} +RUN for iter in {1..10}; do \ + apk update && \ + apk add ca-certificates curl gawk shadow libcap-utils && \ + apk cache clean && \ + exit_code=0 && break || exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \ + done; \ + (exit $exit_code) +{{- end }} + LABEL \ org.label-schema.build-date="{{ date }}" \ org.label-schema.schema-version="1.0" \ @@ -135,26 +152,21 @@ COPY --from=home {{ $beatHome }}/NOTICE.txt /licenses {{- if contains .image_name "-cloud" }} COPY --from=home /opt /opt -{{- end }} - -{{- if contains .image_name "-cloud" }} # Generate folder for a stub command that will be overwritten at runtime RUN mkdir /app && \ chown {{ .user }}:{{ .user }} /app {{- end }} # Keep this after any chown command, chown resets any applied capabilities -RUN setcap cap_net_raw,cap_setuid+p {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components/heartbeat && \ {{- if .linux_capabilities }} # Since the beat is stored at the other end of a symlink we must follow the symlink first # For security reasons setcap does not support symlinks. This is smart in the general case # but in our specific case since we're building a trusted image from trusted binaries this is # fine. Thus, we use readlink to follow the link and setcap on the actual binary - setcap {{ .linux_capabilities }} $(readlink -f {{ $beatBinary }}) && \ +RUN setcap {{ .linux_capabilities }} $(readlink -f {{ $beatBinary }}) {{- end }} -true -{{- if (and (contains .image_name "-complete") (not (contains .from "ubi-minimal"))) }} +{{- if (and (contains .image_name "-complete") (contains .from "ubuntu")) }} USER root ENV NODE_PATH={{ $beatHome }}/.node RUN echo \ @@ -215,7 +227,9 @@ RUN for iter in {1..10}; do \ done; \ (exit $exit_code) +RUN setcap cap_net_raw,cap_setuid+p {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components/agentbeat {{- end }} + USER {{ .user }} @@ -240,4 +254,3 @@ RUN echo -e '#!/bin/sh\nexec /usr/local/bin/docker-entrypoint' > /app/apm.sh && {{- else }} ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/docker-entrypoint"] {{- end }} -