From aed77949fd097a4e0d182a147ded36cfac3626c2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 19 Aug 2021 18:25:57 -0400 Subject: [PATCH] Add OpenSearch/Dashboards Multi-Arch Docker Images (#98) * Add JAVA_HOME fixes for the docker opensearch images Signed-off-by: Peter Zhu * Docker multi-arch script setup 1st commit Signed-off-by: Peter Zhu * Tweak arch retrieval methods in dockerfiles here Signed-off-by: Peter Zhu * Resolve the param checks and complete the README Signed-off-by: Peter Zhu * Update comments by removing duplicate ones Signed-off-by: Peter Zhu * Replace || with && for arch and product checks Signed-off-by: Peter Zhu --- release/docker/README.md | 62 +++++++ release/docker/build-image-multi-arch.sh | 152 ++++++++++++++++++ ...ld-image.sh => build-image-single-arch.sh} | 50 ++++-- .../opensearch-dashboards.al2.dockerfile | 8 +- .../dockerfiles/opensearch.al2.dockerfile | 8 +- 5 files changed, 258 insertions(+), 22 deletions(-) create mode 100644 release/docker/README.md create mode 100755 release/docker/build-image-multi-arch.sh rename release/docker/{build-image.sh => build-image-single-arch.sh} (61%) diff --git a/release/docker/README.md b/release/docker/README.md new file mode 100644 index 0000000000..3ae5960beb --- /dev/null +++ b/release/docker/README.md @@ -0,0 +1,62 @@ +## OpenSearch/Dashboards Docker Build README + +### Summary +We support building OpenSearch/Dashboards docker images with [multi-CPU architecture support](https://docs.docker.com/desktop/multi-arch/). +We also support old school single CPU architecture build as well. +Users are welcome to choose either type of the image to build on their local development environment, or directly pulling existing images published on Docker Hub: + +[OpenSearch Docker Repository](https://hub.docker.com/r/opensearchproject/opensearch/) + +[OpenSearch-Dashboards Docker Repository](https://hub.docker.com/r/opensearchproject/opensearch-dashboards/) + +``` +docker pull opensearchproject/opensearch:latest +docker pull opensearchproject/opensearch-dashboards:latest +``` + +### Building docker images +We provide two scripts to build docker images. +For single-arch image you need to install just the Docker Engine on your host machine. +For multi-arch image (currently support x64/arm64) you need to install Docker Desktop. + +* Install Docker through the official docker webpage: https://docs.docker.com/get-docker/ + +* After installation, verify whether or not you have Docker Engine by running: + ``` + docker build --help + ``` + +* Verify if you have Docker Desktop by running: + ``` + docker buildx --help + ``` + +* You need to run both script within the `opensearch-build/release/docker` folder. Running them + within other path would cause the scripts to fail. + +* Build single-arch image with these command: + * OpenSearch 1.0.0 x64: + ``` + ./build-image-single-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch.al2.dockerfile -p opensearch -a x64 + ``` + * OpenSearch 1.0.0 arm64 with local tarball: + ``` + ./build-image-single-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch.al2.dockerfile -p opensearch -a arm64 -t opensearch-1.0.0.tar.gz + ``` + * OpenSearch-Dashboards 1.0.0 x64: + ``` + ./build-image-single-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch-dashboards.al2.dockerfile -p opensearch-dashboards -a x64 + ``` + * OpenSearch-Dashboards 1.0.0 arm64 with local tarball: + ``` + ./build-image-single-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch-dashboards.al2.dockerfile -p opensearch-dashboards -a arm64 -t opensearch-dashboards-1.0.0.tar.gz + ``` +* Build multi-arch image with this commands (only support x64 + arm64 in one image for now), the image will immediately uploaded to a docker registry so you need to provide docker repo name: + * OpenSearch 1.0.0: + ``` + ./build-image-multi-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch.al2.dockerfile -p opensearch -a "x64,arm64" -r "/:" + ``` + * OpenSearch-Dashboards 1.0.0 with local tarball(s): + ``` + ./build-image-multi-arch.sh -v 1.0.0 -f ./dockerfiles/opensearch-dashboards.al2.dockerfile -p opensearch-dashboards -a "x64,arm64" -r "/:" -t "opensearch-1.0.0.tar.gz,opensearch-dashboards-1.0.0.tar.gz" + ``` diff --git a/release/docker/build-image-multi-arch.sh b/release/docker/build-image-multi-arch.sh new file mode 100755 index 0000000000..38c318cad6 --- /dev/null +++ b/release/docker/build-image-multi-arch.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +set -e + +# Import libs +. ../../lib/shell/file_management.sh + +# Variable +OLDIFS=$IFS +BUILDER_NUM=`date +%s` +BUILDER_NAME="multiarch_${BUILDER_NUM}" +DIR="" + +function usage() { + echo "" + echo "This script is used to build the OpenSearch Docker image with single architecture (x64 or arm64). It prepares the files required by the Dockerfile in a temporary directory, then builds and tags the Docker image." + echo "--------------------------------------------------------------------------" + echo "Usage: $0 [args]" + echo "" + echo "Required arguments:" + echo -e "-v VERSION\tSpecify the OpenSearch version number that you are building, e.g. '1.0.0' or '1.0.0-beta1'. This will be used to label the Docker image. If you do not use the '-o' option then this tool will download a public OPENSEARCH release matching this version." + echo -e "-f DOCKERFILE\tSpecify the dockerfile full path, e.g. dockerfile/opensearch.al2.dockerfile." + echo -e "-p PRODUCT\tSpecify the product, e.g. opensearch or opensearch-dashboards, make sure this is the name of your config folder and the name of your .tgz defined in dockerfile." + echo -e "-a ARCHITECTURE\tSpecify the multiple architecture you want to add to the multi-arch image, separate by comma, e.g. 'x64,arm64'." + echo -e "-r REPOSITORY\tSpecify the docker repository name in the format of '/:', due to multi-arch image either save in cache or directly upload to Docker Hub Repo, no local copies." + echo "" + echo "Optional arguments:" + echo -e "-t TARBALL\tSpecify multiple opensearch or opensearch-dashboards tarballs, use the same order as the input for '-a' param, e.g. 'opensearch-1.0.0-linux-x64.tar.gz,opensearch-1.0.0-linux-arm64.tar.gz'. You still need to specify the version - this tool does not attempt to parse the filename." + echo -e "-h\t\tPrint this message." + echo "--------------------------------------------------------------------------" +} + +function cleanup_docker_buildx() { + # Cleanup docker buildx + echo -e "\n* Cleanup docker buildx" + docker buildx use default + docker buildx rm $BUILDER_NAME > /dev/null 2>&1 +} + +function cleanup_all() { + cleanup_docker_buildx + File_Delete $DIR +} +while getopts ":ht:v:f:p:a:r:" arg; do + case $arg in + h) + usage + exit 1 + ;; + t) + TARBALL=`realpath $OPTARG` + ;; + v) + VERSION=$OPTARG + ;; + f) + DOCKERFILE=$OPTARG + ;; + p) + PRODUCT=$OPTARG + ;; + a) + ARCHITECTURE=$OPTARG + ;; + r) + REPOSITORY=$OPTARG + ;; + :) + echo "-${OPTARG} requires an argument" + usage + exit 1 + ;; + ?) + echo "Invalid option: -${arg}" + exit 1 + ;; + esac +done + +# Validate the required parameters to present +if [ -z "$VERSION" ] || [ -z "$DOCKERFILE" ] || [ -z "$PRODUCT" ] || [ -z "$ARCHITECTURE" ] || [ -z "$REPOSITORY" ]; then + echo "You must specify '-v VERSION', '-f DOCKERFILE', '-p PRODUCT', '-a ARCHITECTURE', '-r REPOSITORY'" + usage + exit 1 +else + echo $VERSION $DOCKERFILE $PRODUCT $ARCHITECTURE + IFS=', ' read -r -a ARCHITECTURE_ARRAY <<< "$ARCHITECTURE" + IFS=', ' read -r -a TARBALL_ARRAY <<< "$TARBALL" +fi + +if [ "$PRODUCT" != "opensearch" ] && [ "$PRODUCT" != "opensearch-dashboards" ] +then + echo "Enter either 'opensearch' or 'opensearch-dashboards' as product name for -p parameter" + exit 1 +fi + +if [ "$ARCHITECTURE" != "x64" ] && [ "$ARCHITECTURE" != "arm64" ] +then + echo "We only support 'x64' and 'arm64' as architecture name for -a parameter" + exit 1 +fi + +# Warning docker desktop +if (! docker buildx version) +then + echo -e "\n* You MUST have Docker Desktop to use buildx for multi-arch images." + exit 1 +fi + +# Prepare docker buildx +trap cleanup_all TERM INT EXIT +DIR=`Temp_Folder_Create` +echo New workspace $DIR +echo -e "\n* Prepare docker buildx" +docker buildx use default +docker buildx create --name $BUILDER_NAME --use +docker buildx inspect --bootstrap + +# Check buildx status +echo -e "\n* Check buildx status" +docker buildx ls | grep $BUILDER_NAME +docker ps | grep $BUILDER_NAME + + +# Copy configs +cp -v config/${PRODUCT}/* $DIR/ +cp -v ../../scripts/opensearch-onetime-setup.sh $DIR/ + +# Copy TGZ +if [ -z "$TARBALL" ]; then + for index in ${!ARCHITECTURE_ARRAY[@]} + do + arch_uname=`echo ${ARCHITECTURE_ARRAY[$index]} | sed 's/x64/x86_64/g;s/arm64/aarch64/g'` + URL="https://artifacts.opensearch.org/releases/bundle/${PRODUCT}/${VERSION}/${PRODUCT}-${VERSION}-linux-${ARCHITECTURE_ARRAY[$index]}.tar.gz" + echo -e "\nDownloading ${PRODUCT} arch ${ARCHITECTURE_ARRAY[$index]} version ${VERSION} from ${URL}" + curl -f $URL -o ${DIR}/${PRODUCT}-${arch_uname}.tgz || exit 1 + done + ls -l $DIR +else + for index in ${!ARCHITECTURE_ARRAY[@]} + do + arch_uname=`echo ${ARCHITECTURE_ARRAY[$index]} | sed 's/x64/x86_64/g;s/arm64/aarch64/g'` + echo -e "\nCopying ${PRODUCT} arch ${ARCHITECTURE_ARRAY[$index]} version ${VERSION} from ${TARBALL_ARRAY[$index]}" + cp -v ${TARBALL_ARRAY[$index]} ${DIR}/${PRODUCT}-${arch_uname}.tgz + done + ls -l $DIR +fi + +# Build multi-arch images +PLATFORMS=`echo "${ARCHITECTURE_ARRAY[@]/#/linux/}" | sed 's/x64/amd64/g;s/ /,/g'` && echo PLATFORMS $PLATFORMS +docker buildx build --platform $PLATFORMS --build-arg VERSION=$VERSION --build-arg BUILD_DATE=`date -u +%Y-%m-%dT%H:%M:%SZ` -t $REPOSITORY -f $DOCKERFILE --push $DIR + diff --git a/release/docker/build-image.sh b/release/docker/build-image-single-arch.sh similarity index 61% rename from release/docker/build-image.sh rename to release/docker/build-image-single-arch.sh index 41c645a30c..3e9b4cacae 100755 --- a/release/docker/build-image.sh +++ b/release/docker/build-image-single-arch.sh @@ -7,9 +7,12 @@ set -e +# Import libs +. ../../lib/shell/file_management.sh + function usage() { echo "" - echo "This script is used to build the OpenSearch Docker image. It prepares the files required by the Dockerfile in a temporary directory, then builds and tags the Docker image." + echo "This script is used to build the OpenSearch Docker image with single architecture (x64 or arm64). It prepares the files required by the Dockerfile in a temporary directory, then builds and tags the Docker image." echo "--------------------------------------------------------------------------" echo "Usage: $0 [args]" echo "" @@ -17,20 +20,21 @@ function usage() { echo -e "-v VERSION\tSpecify the OpenSearch version number that you are building, e.g. '1.0.0' or '1.0.0-beta1'. This will be used to label the Docker image. If you do not use the '-o' option then this tool will download a public OPENSEARCH release matching this version." echo -e "-f DOCKERFILE\tSpecify the dockerfile full path, e.g. dockerfile/opensearch.al2.dockerfile." echo -e "-p PRODUCT\tSpecify the product, e.g. opensearch or opensearch-dashboards, make sure this is the name of your config folder and the name of your .tgz defined in dockerfile." + echo -e "-a ARCHITECTURE\tSpecify one and only one architecture, e.g. x64 or arm64." echo "" echo "Optional arguments:" - echo -e "-o FILENAME\tSpecify a local OPENSEARCH tarball. You still need to specify the version - this tool does not attempt to parse the filename." + echo -e "-t TARBALL\tSpecify a local opensearch or opensearch-dashboards tarball. You still need to specify the version - this tool does not attempt to parse the filename." echo -e "-h\t\tPrint this message." echo "--------------------------------------------------------------------------" } -while getopts ":ho:v:f:p:" arg; do +while getopts ":ht:v:f:p:a:" arg; do case $arg in h) usage exit 1 ;; - o) + t) TARBALL=`realpath $OPTARG` ;; v) @@ -42,6 +46,9 @@ while getopts ":ho:v:f:p:" arg; do p) PRODUCT=$OPTARG ;; + a) + ARCHITECTURE=$OPTARG + ;; :) echo "-${OPTARG} requires an argument" usage @@ -55,32 +62,47 @@ while getopts ":ho:v:f:p:" arg; do done # Validate the required parameters to present -if [ -z "$VERSION" ] || [ -z "$DOCKERFILE" ] || [ -z "$PRODUCT" ]; then - echo "You must specify '-v VERSION', '-f DOCKERFILE', '-p PRODUCT'" +if [ -z "$VERSION" ] || [ -z "$DOCKERFILE" ] || [ -z "$PRODUCT" ] || [ -z "$ARCHITECTURE" ]; then + echo "You must specify '-v VERSION', '-f DOCKERFILE', '-p PRODUCT', '-a ARCHITECTURE'" usage exit 1 else - echo $VERSION $DOCKERFILE $PRODUCT + echo $VERSION $DOCKERFILE $PRODUCT $ARCHITECTURE +fi + +if [ "$PRODUCT" != "opensearch" ] && [ "$PRODUCT" != "opensearch-dashboards" ] +then + echo "Enter either 'opensearch' or 'opensearch-dashboards' as product name for -p parameter" + exit 1 +fi + +if [ "$ARCHITECTURE" != "x64" ] && [ "$ARCHITECTURE" != "arm64" ] +then + echo "We only support 'x64' and 'arm64' as architecture name for -a parameter" + exit 1 fi # Create temp workdirectory -DIR=`mktemp -d` -echo "Creating Docker workspace in $DIR" -trap '{ echo Removing Docker workspace in "$DIR"; rm -rf -- "$DIR"; }' TERM INT EXIT +DIR=`Temp_Folder_Create` +Trap_File_Delete_No_Sigchld $DIR +echo New workspace $DIR # Copy configs cp -v config/${PRODUCT}/* $DIR/ cp -v ../../scripts/opensearch-onetime-setup.sh $DIR/ # Copy TGZ +arch_uname=`echo ${ARCHITECTURE} | sed 's/x64/x86_64/g;s/arm64/aarch64/g'` if [ -z "$TARBALL" ]; then # No tarball file specified so download one - URL="https://artifacts.opensearch.org/releases/bundle/${PRODUCT}/${VERSION}/${PRODUCT}-${VERSION}-linux-x64.tar.gz" - echo "Downloading ${PRODUCT} version ${VERSION} from ${URL}" - curl -f $URL -o $DIR/$PRODUCT.tgz || exit 1 + URL="https://artifacts.opensearch.org/releases/bundle/${PRODUCT}/${VERSION}/${PRODUCT}-${VERSION}-linux-${ARCHITECTURE}.tar.gz" + echo -e "\nDownloading ${PRODUCT} arch ${ARCHITECTURE} version ${VERSION} from ${URL}" + curl -f $URL -o $DIR/$PRODUCT-$arch_uname.tgz || exit 1 ls -l $DIR else - cp -v $TARBALL $DIR/$PRODUCT.tgz + echo -e "\nCopying ${PRODUCT} arch ${ARCHITECTURE} version ${VERSION} from ${TARBALL}" + cp -v $TARBALL $DIR/$PRODUCT-$arch_uname.tgz + ls -l $DIR fi # Docker build diff --git a/release/docker/dockerfiles/opensearch-dashboards.al2.dockerfile b/release/docker/dockerfiles/opensearch-dashboards.al2.dockerfile index 372f46bb55..711fe3f0d3 100644 --- a/release/docker/dockerfiles/opensearch-dashboards.al2.dockerfile +++ b/release/docker/dockerfiles/opensearch-dashboards.al2.dockerfile @@ -32,7 +32,7 @@ # OPENSEARCH_DASHBOARDS_HOME: Optional. Specify the opensearch-dashboards root directory. Defaults to /usr/share/opensearch-dashboards. ########################### Stage 0 ######################## -FROM amazonlinux:2 AS linux_x64_stage_0 +FROM amazonlinux:2 AS linux_stage_0 ARG UID=1000 ARG GID=1000 @@ -48,8 +48,8 @@ RUN groupadd -g $GID opensearch-dashboards && \ mkdir /tmp/opensearch-dashboards # Prepare working directory -COPY opensearch-dashboards.tgz /tmp/opensearch-dashboards/opensearch-dashboards.tgz -RUN tar -xzf /tmp/opensearch-dashboards/opensearch-dashboards.tgz -C $OPENSEARCH_DASHBOARDS_HOME --strip-components=1 && rm -rf /tmp/opensearch-dashboards +COPY opensearch-dashboards-*.tgz /tmp/opensearch-dashboards/ +RUN tar -xzf /tmp/opensearch-dashboards/opensearch-dashboards-`uname -p`.tgz -C $OPENSEARCH_DASHBOARDS_HOME --strip-components=1 && rm -rf /tmp/opensearch-dashboards COPY opensearch-dashboards-docker-entrypoint.sh $OPENSEARCH_DASHBOARDS_HOME/ COPY opensearch_dashboards.yml opensearch.example.org.* $OPENSEARCH_DASHBOARDS_HOME/config/ @@ -75,7 +75,7 @@ RUN yum install -y libnss3.so xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x1 RUN groupadd -g $GID opensearch-dashboards && \ adduser -u $UID -g $GID -d $OPENSEARCH_DASHBOARDS_HOME opensearch-dashboards -COPY --from=linux_x64_stage_0 --chown=$UID:$GID $OPENSEARCH_DASHBOARDS_HOME $OPENSEARCH_DASHBOARDS_HOME +COPY --from=linux_stage_0 --chown=$UID:$GID $OPENSEARCH_DASHBOARDS_HOME $OPENSEARCH_DASHBOARDS_HOME # Change user USER $UID diff --git a/release/docker/dockerfiles/opensearch.al2.dockerfile b/release/docker/dockerfiles/opensearch.al2.dockerfile index 30f9b7a2fe..0003766176 100644 --- a/release/docker/dockerfiles/opensearch.al2.dockerfile +++ b/release/docker/dockerfiles/opensearch.al2.dockerfile @@ -33,7 +33,7 @@ ########################### Stage 0 ######################## -FROM amazonlinux:2 AS linux_x64_stage_0 +FROM amazonlinux:2 AS linux_stage_0 ARG UID=1000 ARG GID=1000 @@ -49,8 +49,8 @@ RUN groupadd -g $GID opensearch && \ mkdir /tmp/opensearch # Prepare working directory -COPY opensearch.tgz /tmp/opensearch/opensearch.tgz -RUN tar -xzf /tmp/opensearch/opensearch.tgz -C $OPENSEARCH_HOME --strip-components=1 && rm -rf /tmp/opensearch +COPY opensearch-*.tgz /tmp/opensearch/ +RUN tar -xzf /tmp/opensearch/opensearch-`uname -p`.tgz -C $OPENSEARCH_HOME --strip-components=1 && rm -rf /tmp/opensearch COPY opensearch-docker-entrypoint.sh opensearch-onetime-setup.sh $OPENSEARCH_HOME/ COPY log4j2.properties opensearch.yml $OPENSEARCH_HOME/config/ COPY performance-analyzer.properties $OPENSEARCH_HOME/plugins/opensearch-performance-analyzer/pa_config/ @@ -73,7 +73,7 @@ RUN groupadd -g $GID opensearch && \ adduser -u $UID -g $GID -d $OPENSEARCH_HOME opensearch # Copy from Stage0 -COPY --from=linux_x64_stage_0 --chown=$UID:$GID $OPENSEARCH_HOME $OPENSEARCH_HOME +COPY --from=linux_stage_0 --chown=$UID:$GID $OPENSEARCH_HOME $OPENSEARCH_HOME WORKDIR $OPENSEARCH_HOME # Set $JAVA_HOME