From 19c50e122a423077ef6868b46caa977919454a28 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 2 Nov 2021 18:14:23 -0400 Subject: [PATCH] Implement docker build pipeline on Jenkins with corresponding scripts (#859) Signed-off-by: Peter Zhu Signed-off-by: Peter Zhu --- docker/ci/build-image-multi-arch.sh | 104 ++++++++++++++++++ docker/ci/build-image-single-arch.sh | 63 +++++++++++ .../dockerfiles/ci-runner.centos7.dockerfile | 3 + ...r.docker-builder.ubuntu2004.x64.dockerfile | 28 +++++ docker/release/build-image-multi-arch.sh | 4 +- jenkins/docker/Jenkinsfile | 78 +++++++++++++ 6 files changed, 278 insertions(+), 2 deletions(-) create mode 100755 docker/ci/build-image-multi-arch.sh create mode 100755 docker/ci/build-image-single-arch.sh create mode 100644 docker/ci/dockerfiles/ci-runner.docker-builder.ubuntu2004.x64.dockerfile create mode 100644 jenkins/docker/Jenkinsfile diff --git a/docker/ci/build-image-multi-arch.sh b/docker/ci/build-image-multi-arch.sh new file mode 100755 index 0000000000..1f5e78b053 --- /dev/null +++ b/docker/ci/build-image-multi-arch.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +# This script is to automate the docker multi arch image creation process + +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 Docker image with multi architecture (x64 + 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 TAG_NAME\tSpecify the image tag name such as 'centos7-x64-arm64-jdkmulti-node10.24.1-cypress6.9.1-20211019'" + echo -e "-f DOCKERFILE\tSpecify the dockerfile full path, e.g. dockerfile/opensearch.al2.dockerfile." + echo "" + echo "Optional arguments:" + 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 ":hv:f:" arg; do + case $arg in + h) + usage + exit 1 + ;; + v) + TAG_NAME=$OPTARG + ;; + f) + DOCKERFILE=$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 "$TAG_NAME" ] || [ -z "$DOCKERFILE" ] || [ -z "$REPOSITORY" ]; then + echo "You must specify '-v TAG_NAME', '-f DOCKERFILE', '-r REPOSITORY'" + usage + exit 1 +else + echo $TAG_NAME $DOCKERFILE $REPOSITORY +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 + +# Build multi-arch images +docker buildx build --platform linux/amd64,linux/arm64 -t opensearchstaging/ci-runner:${TAG_NAME} -f $DOCKERFILE --push . + diff --git a/docker/ci/build-image-single-arch.sh b/docker/ci/build-image-single-arch.sh new file mode 100755 index 0000000000..3e242a4346 --- /dev/null +++ b/docker/ci/build-image-single-arch.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +# This script is to automate the docker single arch image creation process + +set -e + +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 TAG_NAME\tSpecify the image tag name such as 'centos7-x64-arm64-jdkmulti-node10.24.1-cypress6.9.1-20211019'" + echo -e "-f DOCKERFILE\tSpecify the dockerfile full path, e.g. dockerfile/opensearch.al2.dockerfile." + echo "" + echo "Optional arguments:" + echo -e "-h\t\tPrint this message." + echo "--------------------------------------------------------------------------" +} + +while getopts ":hv:f:" arg; do + case $arg in + h) + usage + exit 1 + ;; + v) + TAG_NAME=$OPTARG + ;; + f) + DOCKERFILE=$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 "$TAG_NAME" ] || [ -z "$DOCKERFILE" ]; then + echo "You must specify '-v TAG_NAME', '-f DOCKERFILE'" + usage + exit 1 +else + echo $TAG_NAME $DOCKERFILE +fi + +# Docker build +docker build -f $DOCKERFILE $DIR -t opensearchstaging/ci-runner:$TAG_NAME . + diff --git a/docker/ci/dockerfiles/ci-runner.centos7.dockerfile b/docker/ci/dockerfiles/ci-runner.centos7.dockerfile index cb9158c27c..216d995012 100644 --- a/docker/ci/dockerfiles/ci-runner.centos7.dockerfile +++ b/docker/ci/dockerfiles/ci-runner.centos7.dockerfile @@ -13,6 +13,9 @@ FROM centos:7 ARG MAVEN_DIR=/usr/local/apache-maven +# Ensure localedef running correct with root permission +USER 0 + # Add AdoptOpenJDK Repo RUN echo -e "[AdoptOpenJDK]\nname=AdoptOpenJDK\nbaseurl=http://adoptopenjdk.jfrog.io/adoptopenjdk/rpm/centos/7/\$basearch\nenabled=1\ngpgcheck=1\ngpgkey=https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public" > /etc/yum.repos.d/adoptopenjdk.repo diff --git a/docker/ci/dockerfiles/ci-runner.docker-builder.ubuntu2004.x64.dockerfile b/docker/ci/dockerfiles/ci-runner.docker-builder.ubuntu2004.x64.dockerfile new file mode 100644 index 0000000000..45af093e58 --- /dev/null +++ b/docker/ci/dockerfiles/ci-runner.docker-builder.ubuntu2004.x64.dockerfile @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +# This is a docker image specifically for building docker images with single/multi-arch support +# It has binfmt_support package installed to run non-native arch binary, as well as +# qemu-user-static package to enable execution of different multi-arch containers + +# This can only be used on Ubuntu 2004 X64 version, as QEMU 5.0 is required to get buildx work properly without segfault +# https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1928075 + +FROM ubuntu:20.04 + +# Import necessary repository for installing qemu 5.0 +RUN apt-get update -y && apt-get install -y software-properties-common && add-apt-repository ppa:jacob/virtualisation -y + +# Install necessary packages +RUN apt-get update -y && apt-get upgrade -y && apt-get install -y binfmt-support qemu qemu-user qemu-user-static docker.io curl && apt clean -y + +# Install docker buildx +RUN mkdir -p ~/.docker/cli-plugins && \ + curl -SL https://github.com/docker/buildx/releases/download/v0.6.3/buildx-v0.6.3.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx && \ + chmod 775 ~/.docker/cli-plugins/docker-buildx && \ + docker buildx version + + diff --git a/docker/release/build-image-multi-arch.sh b/docker/release/build-image-multi-arch.sh index a06c8a5702..de7125b815 100755 --- a/docker/release/build-image-multi-arch.sh +++ b/docker/release/build-image-multi-arch.sh @@ -13,7 +13,7 @@ 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 "This script is used to build the OpenSearch Docker image with multi architecture (x64 + 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 "" @@ -22,7 +22,7 @@ function usage() { 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. The tag name will be pointed to `-v` value and `latest`" + 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. The tag name will be pointed to '-v' value and 'latest'" 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." diff --git a/jenkins/docker/Jenkinsfile b/jenkins/docker/Jenkinsfile new file mode 100644 index 0000000000..c18d934b46 --- /dev/null +++ b/jenkins/docker/Jenkinsfile @@ -0,0 +1,78 @@ +pipeline { + options { + timeout(time: 3, unit: 'HOURS') + } +// environment { +// CREDENTIAL_ID = "jenkins-staging-docker-staging-credential" +// } + agent none + stages { + stage('parameters') { + steps { + script { + properties([ + parameters([ + string( + defaultValue: 'https://github.com/opensearch-project/opensearch-build', + name: 'DOCKER_BUILD_GIT_REPOSITORY', + description: 'The git repository name that contains dockerfiles and the docker build script', + trim: true + ), + string( + defaultValue: 'main', + name: 'DOCKER_BUILD_GIT_REPOSITORY_REFERENCE', + description: 'The git reference (branch/tag/commit_id) of above repository', + trim: true + ), + string( + defaultValue: 'bash docker/ci/build-image-multi-arch.sh -v -f ', + name: 'DOCKER_BUILD_SCRIPT_WITH_COMMANDS', + description: 'The script path of the docker build script, assuming you are already in root dir of DOCKER_BUILD_GIT_REPOSITORY', + trim: true + ), + booleanParam( + defaultValue: true, + name: 'IS_STAGING', + description: 'Are we pushing docker images to staging (opensearchstaging) or production (opensearchproject) account' + ) + ]) + ]) + } + } + } + stage('docker-build') { + agent { + docker { + label 'Jenkins-Agent-Ubuntu2004-X64-m52xlarge-Docker-Builder' + image 'opensearchstaging/ci-runner:ubuntu2004-x64-docker-buildx0.6.3-qemu5.0' + args '-u root -v /var/run/docker.sock:/var/run/docker.sock' + alwaysPull true + } + } + steps { + script { + git url: "$DOCKER_BUILD_GIT_REPOSITORY", branch: "$DOCKER_BUILD_GIT_REPOSITORY_REFERENCE" + def CREDENTIAL_ID = "jenkins-staging-docker-staging-credential" + if (env.IS_STAGING == "false"){ + CREDENTIAL_ID = "jenkins-staging-docker-prod-token" + sh "echo Switch to Production" + } + sh "echo Account: $CREDENTIAL_ID" + withCredentials([usernamePassword(credentialsId: CREDENTIAL_ID, usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) { + sh ''' + set -ex + echo Login to $CREDENTIAL_ID + docker logout && docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD && eval $DOCKER_BUILD_SCRIPT_WITH_COMMANDS + ''' + } + } + } + post() { + always { + cleanWs disableDeferredWipeout: true, deleteDirs: true + sh "docker logout && docker image prune -f --all" + } + } + } + } +}