diff --git a/changelog/fragments/1720208209-add-docker-wolfi.yaml b/changelog/fragments/1720208209-add-docker-wolfi.yaml new file mode 100644 index 00000000000..da27eab5a4f --- /dev/null +++ b/changelog/fragments/1720208209-add-docker-wolfi.yaml @@ -0,0 +1,3 @@ +kind: security +summary: Add Wolfi docker image to packaging, the cloud image is now based on Wolfi +component: "elastic-agent" diff --git a/dev-tools/packaging/packages.yml b/dev-tools/packaging/packages.yml index 062e5f1164f..4de22f95195 100644 --- a/dev-tools/packaging/packages.yml +++ b/dev-tools/packaging/packages.yml @@ -207,21 +207,58 @@ 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 + # This image is used only for preparing the file tree before actually building the image + - &docker_builder_spec + extra_vars: + buildFrom: '--platform=linux/amd64 cgr.dev/chainguard/wolfi-base' + + - &docker_builder_arm_spec + extra_vars: + buildFrom: '--platform=linux/arm64 cgr.dev/chainguard/wolfi-base' + + - &docker_ubuntu_spec + extra_vars: + from: '--platform=linux/amd64 ubuntu:20.04' + image_name: '{{.BeatName}}' + - &docker_ubuntu_arm_spec + extra_vars: + from: '--platform=linux/arm64 ubuntu:20.04' + image_name: '{{.BeatName}}' + + - &docker_ubi_spec + extra_vars: + from: '--platform=linux/amd64 docker.elastic.co/ubi9/ubi-minimal' + image_name: '{{.BeatName}}-ubi' + - &docker_ubi_arm_spec + extra_vars: + from: '--platform=linux/arm64 docker.elastic.co/ubi9/ubi-minimal' + image_name: '{{.BeatName}}-ubi' + + - &docker_wolfi_spec + extra_vars: + from: '--platform=linux/amd64 cgr.dev/chainguard/wolfi-base' + image_name: '{{.BeatName}}-wolfi' + - &docker_wolfi_arm_spec + extra_vars: + from: '--platform=linux/arm64 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: - from: 'ubuntu:20.04' - buildFrom: 'ubuntu:20.04' 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 +274,7 @@ 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 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,15 @@ specs: types: [docker] spec: <<: *docker_spec + <<: *docker_ubuntu_spec + <<: *docker_builder_spec + + - os: linux + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_builder_spec - os: aix types: [tgz] @@ -555,7 +573,19 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_builder_spec + <<: *docker_elastic_spec + <<: *apache_license_for_binaries + name: '{{.BeatName}}-oss' + + - os: linux + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_builder_spec + <<: *docker_elastic_spec <<: *apache_license_for_binaries name: '{{.BeatName}}-oss' @@ -600,7 +630,18 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_builder_spec + <<: *docker_elastic_spec + <<: *elastic_license_for_binaries + - os: linux + arch: arm64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_ubuntu_arm_spec + <<: *docker_builder_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries - os: linux @@ -609,24 +650,36 @@ specs: spec: <<: *docker_spec <<: *docker_ubi_spec - <<: *elastic_docker_spec + <<: *docker_builder_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_builder_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries + - os: linux + arch: amd64 + types: [docker] + spec: + <<: *docker_spec + <<: *docker_wolfi_spec + <<: *docker_builder_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_builder_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries - os: aix @@ -710,7 +763,21 @@ specs: types: [docker] spec: <<: *docker_spec - <<: *elastic_docker_spec + <<: *docker_ubuntu_spec + <<: *docker_builder_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_builder_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': @@ -722,30 +789,45 @@ specs: spec: <<: *docker_spec <<: *docker_ubi_spec - <<: *elastic_docker_spec + <<: *docker_builder_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_builder_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_builder_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_builder_arm_spec + <<: *docker_elastic_spec <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': @@ -809,105 +891,136 @@ 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 + <<: *docker_builder_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 + <<: *docker_builder_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 + <<: *docker_builder_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 + <<: *docker_builder_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 + <<: *docker_builder_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 + <<: *docker_builder_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 + <<: *agent_docker_spec + # The cloud image is always based on Wolfi + <<: *docker_wolfi_spec + <<: *docker_builder_spec + <<: *agent_docker_cloud_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 + <<: *agent_docker_spec + # The cloud image is always based on Wolfi + <<: *docker_wolfi_arm_spec + <<: *docker_builder_arm_spec <<: *agent_docker_cloud_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 + <<: *docker_builder_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 + <<: *docker_builder_arm_spec + <<: *agent_docker_spec + <<: *docker_elastic_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 +1052,10 @@ specs: - os: linux types: [docker] spec: + <<: *docker_wolfi_spec + <<: *docker_builder_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 da8b145bfed..e737e21f699 100644 --- a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl +++ b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl @@ -6,13 +6,14 @@ # the final image because of permission changes. FROM {{ .buildFrom }} AS home +{{- if contains .buildFrom "wolfi" }} RUN for iter in {1..10}; do \ - apt-get update -y && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes libcap2-bin && \ - apt-get clean all && \ - exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ + apk update && \ + apk add --no-cache shadow libcap-utils && \ + exit_code=0 && break || exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \ done; \ (exit $exit_code) +{{- end }} COPY beat {{ $beatHome }} @@ -38,9 +39,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 && \ @@ -69,8 +72,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 xz-utils && \ @@ -80,6 +84,15 @@ 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 --no-cache ca-certificates curl gawk shadow bash && \ + 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" \ @@ -134,8 +147,14 @@ RUN set -e ; \ chmod +x /usr/bin/tini COPY docker-entrypoint /usr/local/bin/docker-entrypoint + +# We do not want to add the agent user to the root group and because of backwards compatibility we can do it only for the new Wolfi image RUN groupadd --gid 1000 {{ .BeatName }} && \ +{{- if contains .from "wolfi" }} + useradd -M --uid 1000 --gid 1000 {{ .user }} && \ +{{- else }} useradd -M --uid 1000 --gid 1000 --groups 0 {{ .user }} && \ +{{- end }} chmod 755 /usr/local/bin/docker-entrypoint && \ true @@ -154,15 +173,12 @@ 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 }} -{{- 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 \ @@ -222,8 +238,8 @@ RUN for iter in {1..10}; do \ exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ done; \ (exit $exit_code) - {{- end }} + USER {{ .user }}