From 8a868400a2703f220403a8e46ccee65630fad118 Mon Sep 17 00:00:00 2001 From: Pierre Tessier Date: Sun, 24 Nov 2024 12:49:26 -0500 Subject: [PATCH] [chore] add multi platform build support (#1785) * multiplatform build * multiplatform build instructions * fix tests * multi-platform build support * fix failed linting * stop tests properly * fix grammar * fix multi-platform builds * align with cartservice steps * remove buildx warnings * add create-multiplatform-builder target * support Linux to create multiplaform builder * update multiplatform build instructions * add multiplatform build support * add multiplatform build support * add multiplatform build support * create and remove multi-platform builder * clarify multi-platform build instructions * clarify multi-platform build instructions * use shell directly for env var subst * Update CONTRIBUTING.md --------- Co-authored-by: Juliano Costa --- CHANGELOG.md | 2 ++ CONTRIBUTING.md | 46 +++++++++++++++++++++++++-- Makefile | 44 +++++++++++++++----------- buildkitd.toml | 5 +++ src/accountingservice/Dockerfile | 47 ++++++++++++---------------- src/adservice/Dockerfile | 2 +- src/cartservice/src/Dockerfile | 8 ++--- src/currencyservice/Dockerfile | 6 ++-- src/emailservice/Dockerfile | 6 ++-- src/frauddetectionservice/Dockerfile | 2 +- src/frontend/Dockerfile | 5 +-- src/loadgenerator/Dockerfile | 6 ++-- src/paymentservice/Dockerfile | 2 +- src/quoteservice/Dockerfile | 7 ++--- src/recommendationservice/Dockerfile | 8 ++--- src/shippingservice/Dockerfile | 19 ++++++++--- 16 files changed, 137 insertions(+), 78 deletions(-) create mode 100644 buildkitd.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index 9566411768..f40fed854b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ the release. to 1.9.0 ([#1780](https://github.com/open-telemetry/opentelemetry-demo/pull/1780)) * [chore] update memory limits for flagd, flagdui, and loadgenerator ([#1786](https://github.com/open-telemetry/opentelemetry-demo/pull/1786)) +* [chore] Add multi-platform build support + ([#1785](https://github.com/open-telemetry/opentelemetry-demo/pull/1785)) ## 1.12.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68ea5c2d2a..96b8433949 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,11 +80,10 @@ cd .\src\adservice\ ### Run Docker Compose -- Start the demo (It can take ~20min the first time the command is executed as -all the images will be build): +- Start the demo: ```shell -docker compose up -d +make start ``` ### Verify the Webstore & the Telemetry @@ -197,6 +196,47 @@ on each other), the owner should try to get people aligned by: the owner should bring it to the OpenTelemetry Community Demo SIG [meeting](README.md#contributing). +## Multi-platform Builds + +Creating multi-platform builds requires docker buildx to be installed. This +is part of Docker Desktop for macOS, or can be installed using +`apt install docker-buildx` on Ubuntu. + +To build and load the multi-platform images locally you will need to configure +docker to use `containerd`. This can be done in Docker Desktop settings on MacOS +or Windows. Please follow +[these instructions](https://docs.docker.com/engine/storage/containerd/#enable-containerd-image-store-on-docker-engine) +to configure Docker Engine on Linux/Ubuntu. + +You will need a multi-platform capable builder with a limiter set on parallelism +to avoid errors while building the images. It is recommended to limit the +parallelism to 4. This can be done by specifying a configuration file when +creating the builder. The `buildkitd.toml` file in this repository can be used +as the builder configuration file. + +To create a multi-platform builder with a parallelism limit of 4, use the +following command: + +```shell +make create-multiplatform-builder +``` + +A builder will be created and set as the active builder. You can check the +builder status with `docker buildx inspect`. To build multi-platform images for +linux/amd64 and linux/arm64, use the following command: + +```shell +make build-multiplatform +``` + +To build and push multi-platform images to a registry, ensure to set +`IMAGE_NAME` to the name of the registry and image repository to use in the +`.env.override` file and run: + +```shell +make build-multiplatform-and-push +``` + ## Making a new release Maintainers can create a new release when desired by following these steps. diff --git a/Makefile b/Makefile index 09ca5f350d..fc768d2680 100644 --- a/Makefile +++ b/Makefile @@ -79,24 +79,32 @@ install-tools: $(MISSPELL) build: $(DOCKER_COMPOSE_CMD) build -.PHONY: build-and-push-dockerhub -build-and-push-dockerhub: - $(DOCKER_COMPOSE_CMD) --env-file .dockerhub.env -f docker-compose.yml build - $(DOCKER_COMPOSE_CMD) --env-file .dockerhub.env -f docker-compose.yml push - -.PHONY: build-and-push-ghcr -build-and-push-ghcr: - $(DOCKER_COMPOSE_CMD) --env-file .ghcr.env -f docker-compose.yml build - $(DOCKER_COMPOSE_CMD) --env-file .ghcr.env -f docker-compose.yml push - -.PHONY: build-env-file -build-env-file: - cp .env .dockerhub.env - sed -i '/IMAGE_VERSION=.*/c\IMAGE_VERSION=${RELEASE_VERSION}' .dockerhub.env - sed -i '/IMAGE_NAME=.*/c\IMAGE_NAME=${DOCKERHUB_REPO}' .dockerhub.env - cp .env .ghcr.env - sed -i '/IMAGE_VERSION=.*/c\IMAGE_VERSION=${RELEASE_VERSION}' .ghcr.env - sed -i '/IMAGE_NAME=.*/c\IMAGE_NAME=${GHCR_REPO}' .ghcr.env +.PHONY: build-and-push +build-and-push: + $(DOCKER_COMPOSE_CMD) $(DOCKER_COMPOSE_ENV) build --push + +# Create multiplatform builder for buildx +.PHONY: create-multiplatform-builder +create-multiplatform-builder: + docker buildx create --name otel-demo-builder --bootstrap --use --driver docker-container --config ./buildkitd.toml + +# Remove multiplatform builder for buildx +.PHONY: remove-multiplatform-builder +remove-multiplatform-builder: + docker buildx rm otel-demo-builder + +# Build and push multiplatform images (linux/amd64, linux/arm64) using buildx. +# Requires docker with buildx enabled and a multi-platform capable builder in use. +# Docker needs to be configured to use containerd storage for images to be loaded into the local registry. +.PHONY: build-multiplatform +build-multiplatform: + # Because buildx bake does not support --env-file yet, we need to load it into the environment first. + set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --load --set "*.platform=linux/amd64,linux/arm64" + +.PHONY: build-multiplatform-and-push +build-multiplatform-and-push: + # Because buildx bake does not support --env-file yet, we need to load it into the environment first. + set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --push --set "*.platform=linux/amd64,linux/arm64" .PHONY: run-tests run-tests: diff --git a/buildkitd.toml b/buildkitd.toml new file mode 100644 index 0000000000..ef2690a4d1 --- /dev/null +++ b/buildkitd.toml @@ -0,0 +1,5 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +[worker.oci] +max-parallelism = 4 diff --git a/src/accountingservice/Dockerfile b/src/accountingservice/Dockerfile index f9166879ca..a6b0e9bfb9 100644 --- a/src/accountingservice/Dockerfile +++ b/src/accountingservice/Dockerfile @@ -1,32 +1,25 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -USER app -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -ARG BUILD_CONFIGURATION=Release -WORKDIR /src -COPY ["/src/accountingservice/", "AccountingService/"] -COPY ["/pb/demo.proto", "AccountingService/proto/"] -RUN dotnet restore "./AccountingService/AccountingService.csproj" -WORKDIR "/src/AccountingService" - -RUN dotnet build "./AccountingService.csproj" -c $BUILD_CONFIGURATION -o /app/build - -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./AccountingService.csproj" --use-current-runtime -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . - -USER root -RUN mkdir -p "/var/log/opentelemetry/dotnet" -RUN chown app "/var/log/opentelemetry/dotnet" -RUN chown app "/app/instrument.sh" -USER app +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/dotnet/sdk:8.0 AS builder +ARG TARGETARCH + +WORKDIR /usr/src/app/ + +COPY ./src/accountingservice/ ./ +COPY ./pb/ ./proto/ + +RUN dotnet restore "./AccountingService.csproj" -r linux-musl-$TARGETARCH + +RUN dotnet publish "./AccountingService.csproj" -r linux-musl-$TARGETARCH --no-restore -o /accountingservice + +# ----------------------------------------------------------------------------- + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +WORKDIR /usr/src/app/ +COPY --from=builder /accountingservice/ ./ + +ENV DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE=false ENTRYPOINT ["./instrument.sh", "dotnet", "AccountingService.dll"] diff --git a/src/adservice/Dockerfile b/src/adservice/Dockerfile index 369af01a05..36c6b207fb 100644 --- a/src/adservice/Dockerfile +++ b/src/adservice/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM eclipse-temurin:21-jdk as builder +FROM --platform=${BUILDPLATFORM} eclipse-temurin:21-jdk AS builder WORKDIR /usr/src/app/ diff --git a/src/cartservice/src/Dockerfile b/src/cartservice/src/Dockerfile index 812213bd5b..bf9ebcac19 100644 --- a/src/cartservice/src/Dockerfile +++ b/src/cartservice/src/Dockerfile @@ -15,7 +15,7 @@ # limitations under the License. # https://mcr.microsoft.com/v2/dotnet/sdk/tags/list -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0.403 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS builder ARG TARGETARCH WORKDIR /usr/src/app/ @@ -23,14 +23,14 @@ WORKDIR /usr/src/app/ COPY ./src/cartservice/ ./ COPY ./pb/ ./pb/ -RUN dotnet restore ./src/cartservice.csproj -v d -r linux-musl-$TARGETARCH +RUN dotnet restore ./src/cartservice.csproj -r linux-musl-$TARGETARCH -RUN dotnet publish ./src/cartservice.csproj -v d -r linux-musl-$TARGETARCH --no-restore -o /cartservice +RUN dotnet publish ./src/cartservice.csproj -r linux-musl-$TARGETARCH --no-restore -o /cartservice # ----------------------------------------------------------------------------- # https://mcr.microsoft.com/v2/dotnet/runtime-deps/tags/list -FROM mcr.microsoft.com/dotnet/runtime-deps:8.0.10-alpine3.20 +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine3.20 WORKDIR /usr/src/app/ COPY --from=builder /cartservice/ ./ diff --git a/src/currencyservice/Dockerfile b/src/currencyservice/Dockerfile index 3c26de728a..e84057f3d1 100644 --- a/src/currencyservice/Dockerfile +++ b/src/currencyservice/Dockerfile @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.18 as builder +FROM alpine:3.18 AS builder RUN apk update && apk add git cmake make g++ grpc-dev protobuf-dev linux-headers @@ -39,10 +39,10 @@ RUN cd /currencyservice \ && make -j$(nproc || sysctl -n hw.ncpu || echo 1) install -FROM alpine:3.18 as release +FROM alpine:3.18 AS release RUN apk update && apk add grpc-dev protobuf-dev COPY --from=builder /usr/local /usr/local EXPOSE ${CURRENCY_SERVICE_PORT} -ENTRYPOINT ./usr/local/bin/currencyservice ${CURRENCY_SERVICE_PORT} +ENTRYPOINT ["sh", "-c", "./usr/local/bin/currencyservice ${CURRENCY_SERVICE_PORT}"] diff --git a/src/emailservice/Dockerfile b/src/emailservice/Dockerfile index b3bb161afe..d6090905e5 100644 --- a/src/emailservice/Dockerfile +++ b/src/emailservice/Dockerfile @@ -2,9 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 -FROM ruby:3.2.2-slim as base +FROM ruby:3.2.2-slim AS base -FROM base as builder +FROM base AS builder WORKDIR /tmp @@ -12,7 +12,7 @@ COPY ./src/emailservice/Gemfile ./src/emailservice/Gemfile.lock ./ #RUN apk update && apk add make gcc musl-dev gcompat && bundle install RUN apt-get update && apt-get install build-essential -y && bundle install -FROM base as release +FROM base AS release WORKDIR /email_server diff --git a/src/frauddetectionservice/Dockerfile b/src/frauddetectionservice/Dockerfile index f3f62401da..1d2a9b58da 100644 --- a/src/frauddetectionservice/Dockerfile +++ b/src/frauddetectionservice/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM gradle:8-jdk17 AS builder +FROM --platform=${BUILDPLATFORM} gradle:8-jdk17 AS builder WORKDIR /usr/src/app/ diff --git a/src/frontend/Dockerfile b/src/frontend/Dockerfile index a1f441bb4c..ae27d932b9 100644 --- a/src/frontend/Dockerfile +++ b/src/frontend/Dockerfile @@ -40,7 +40,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs -ENV PORT 8080 +ENV PORT=8080 EXPOSE ${PORT} -ENTRYPOINT npm start +ENTRYPOINT ["npm", "start"] + diff --git a/src/loadgenerator/Dockerfile b/src/loadgenerator/Dockerfile index 5c8427f597..92d09977b8 100644 --- a/src/loadgenerator/Dockerfile +++ b/src/loadgenerator/Dockerfile @@ -2,9 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 -FROM python:3.12-slim-bookworm as base +FROM python:3.12-slim-bookworm AS base -FROM base as builder +FROM base AS builder RUN apt-get -qq update \ && apt-get install -y --no-install-recommends g++ \ && rm -rf /var/lib/apt/lists/* @@ -20,4 +20,4 @@ COPY ./src/loadgenerator/people.json . ENV LOCUST_PLAYWRIGHT=1 ENV PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers RUN playwright install --with-deps chromium -ENTRYPOINT locust --skip-log-setup +ENTRYPOINT ["locust", "--skip-log-setup"] diff --git a/src/paymentservice/Dockerfile b/src/paymentservice/Dockerfile index c82e0e70a5..c67672b651 100644 --- a/src/paymentservice/Dockerfile +++ b/src/paymentservice/Dockerfile @@ -16,7 +16,7 @@ FROM node:21-alpine USER node WORKDIR /usr/src/app/ -ENV NODE_ENV production +ENV NODE_ENV=production COPY --chown=node:node --from=build /usr/src/app/node_modules/ ./node_modules/ COPY ./src/paymentservice/ ./ diff --git a/src/quoteservice/Dockerfile b/src/quoteservice/Dockerfile index f1ab3956be..f26f192b84 100644 --- a/src/quoteservice/Dockerfile +++ b/src/quoteservice/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM php:8.3-cli as base +FROM php:8.3-cli AS base ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ RUN chmod +x /usr/local/bin/install-php-extensions \ @@ -13,7 +13,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions \ opentelemetry WORKDIR /var/www -CMD php public/index.php +CMD ["php", "public/index.php"] USER www-data EXPOSE ${QUOTE_SERVICE_PORT} @@ -30,7 +30,6 @@ RUN composer install \ --no-dev \ --prefer-dist -FROM base as final +FROM base AS final COPY --from=vendor /tmp/vendor/ ./vendor/ COPY ./src/quoteservice/ /var/www - diff --git a/src/recommendationservice/Dockerfile b/src/recommendationservice/Dockerfile index 4a3d2e72b7..8e02f42662 100644 --- a/src/recommendationservice/Dockerfile +++ b/src/recommendationservice/Dockerfile @@ -2,12 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 -FROM python:3.12-slim-bookworm as base +FROM python:3.12-slim-bookworm AS base # # Fetch requirements # -FROM base as builder +FROM base AS builder RUN apt-get -qq update \ && apt-get install -y --no-install-recommends g++ \ && rm -rf /var/lib/apt/lists/* @@ -21,7 +21,7 @@ RUN pip install --prefix="/reqs" -r requirements.txt # # Build gRPC files # -FROM base as grpc-builder +FROM base AS grpc-builder WORKDIR /usr/src/app/ COPY ./pb/ ./proto/ @@ -31,7 +31,7 @@ RUN python -m grpc_tools.protoc -I=./proto/ --python_out=./ --grpc_python_out=./ # # Runtime # -FROM base as runtime +FROM base AS runtime WORKDIR /usr/src/app/ COPY --from=builder /reqs /usr/local COPY --from=grpc-builder /usr/src/app/ . diff --git a/src/shippingservice/Dockerfile b/src/shippingservice/Dockerfile index 60e338cbc8..8ff400ff3e 100644 --- a/src/shippingservice/Dockerfile +++ b/src/shippingservice/Dockerfile @@ -2,9 +2,10 @@ # SPDX-License-Identifier: Apache-2.0 -FROM --platform=${BUILDPLATFORM} rust:1.76 as builder - -ARG TARGETARCH TARGETPLATFORM BUILDPLATFORM +FROM --platform=${BUILDPLATFORM} rust:1.76 AS builder +ARG TARGETARCH +ARG TARGETPLATFORM +ARG BUILDPLATFORM RUN echo Building on ${BUILDPLATFORM} for ${TARGETPLATFORM} @@ -15,6 +16,10 @@ RUN if [ "${TARGETPLATFORM}" = "${BUILDPLATFORM}" ] ; then \ apt-get update && apt-get install --no-install-recommends -y g++-aarch64-linux-gnu libc6-dev-arm64-cross libprotobuf-dev protobuf-compiler ca-certificates && \ rustup target add aarch64-unknown-linux-gnu && \ rustup toolchain install stable-aarch64-unknown-linux-gnu; \ + elif [ "${TARGETPLATFORM}" = "linux/amd64" ] ; then \ + apt-get update && apt-get install --no-install-recommends -y g++-x86-64-linux-gnu libc6-amd64-cross libprotobuf-dev protobuf-compiler ca-certificates && \ + rustup target add x86_64-unknown-linux-gnu && \ + rustup toolchain install stable-x86_64-unknown-linux-gnu; \ else \ echo "${TARGETPLATFORM} is not supported"; \ exit 1; \ @@ -34,6 +39,12 @@ RUN if [ "${TARGETPLATFORM}" = "${BUILDPLATFORM}" ] ; then \ CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ \ cargo build -r --features="dockerproto" --target aarch64-unknown-linux-gnu && \ cp /app/target/aarch64-unknown-linux-gnu/release/shippingservice /app/target/release/shippingservice; \ + elif [ "${TARGETPLATFORM}" = "linux/amd64" ] ; then \ + env CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc \ + CC_x86_64_unknown_linux_gnu=x86_64-linux-gnu-gcc \ + CXX_x86_64_unknown_linux_gnu=x86_64-linux-gnu-g++ \ + cargo build -r --features="dockerproto" --target x86_64-unknown-linux-gnu && \ + cp /app/target/x86_64-unknown-linux-gnu/release/shippingservice /app/target/release/shippingservice; \ else \ echo "${TARGETPLATFORM} is not supported"; \ exit 1; \ @@ -44,7 +55,7 @@ ENV GRPC_HEALTH_PROBE_VERSION=v0.4.24 RUN wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-${TARGETARCH} && \ chmod +x /bin/grpc_health_probe -FROM debian:bookworm-slim as release +FROM debian:bookworm-slim AS release WORKDIR /app COPY --from=builder /app/target/release/shippingservice /app/shippingservice