Просмотр исходного кода

ci: build binaries for each arch of docker image separately

to speed up the build process, we build the binaries for multi-arch
docker image on the instances with corresponding architecture first,
then assemble the final docker image
Ivan Dyachkov 1 год назад
Родитель
Сommit
a68cc8fde2

+ 1 - 1
.github/workflows/_pr_entrypoint.yaml

@@ -148,7 +148,7 @@ jobs:
         with:
         with:
           name: ${{ matrix.profile }}
           name: ${{ matrix.profile }}
           path: ${{ matrix.profile }}.zip
           path: ${{ matrix.profile }}.zip
-          retention-days: 1
+          retention-days: 7
 
 
   run_emqx_app_tests:
   run_emqx_app_tests:
     needs:
     needs:

+ 3 - 7
.github/workflows/_push-entrypoint.yaml

@@ -28,7 +28,6 @@ jobs:
       profile: ${{ steps.parse-git-ref.outputs.profile }}
       profile: ${{ steps.parse-git-ref.outputs.profile }}
       release: ${{ steps.parse-git-ref.outputs.release }}
       release: ${{ steps.parse-git-ref.outputs.release }}
       latest: ${{ steps.parse-git-ref.outputs.latest }}
       latest: ${{ steps.parse-git-ref.outputs.latest }}
-      version: ${{ steps.parse-git-ref.outputs.version }}
       ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
       ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
       ct-host: ${{ steps.matrix.outputs.ct-host }}
       ct-host: ${{ steps.matrix.outputs.ct-host }}
       ct-docker: ${{ steps.matrix.outputs.ct-docker }}
       ct-docker: ${{ steps.matrix.outputs.ct-docker }}
@@ -46,18 +45,16 @@ jobs:
         shell: bash
         shell: bash
         run: |
         run: |
           git config --global --add safe.directory "$GITHUB_WORKSPACE"
           git config --global --add safe.directory "$GITHUB_WORKSPACE"
-      - name: Detect emqx profile and version
+      - name: Detect emqx profile
         id: parse-git-ref
         id: parse-git-ref
         run: |
         run: |
           JSON="$(./scripts/parse-git-ref.sh $GITHUB_REF)"
           JSON="$(./scripts/parse-git-ref.sh $GITHUB_REF)"
           PROFILE=$(echo "$JSON" | jq -cr '.profile')
           PROFILE=$(echo "$JSON" | jq -cr '.profile')
           RELEASE=$(echo "$JSON" | jq -cr '.release')
           RELEASE=$(echo "$JSON" | jq -cr '.release')
           LATEST=$(echo "$JSON"  | jq -cr '.latest')
           LATEST=$(echo "$JSON"  | jq -cr '.latest')
-          VERSION="$(./pkg-vsn.sh "$PROFILE")"
           echo "profile=$PROFILE" | tee -a $GITHUB_OUTPUT
           echo "profile=$PROFILE" | tee -a $GITHUB_OUTPUT
           echo "release=$RELEASE" | tee -a $GITHUB_OUTPUT
           echo "release=$RELEASE" | tee -a $GITHUB_OUTPUT
           echo "latest=$LATEST"   | tee -a $GITHUB_OUTPUT
           echo "latest=$LATEST"   | tee -a $GITHUB_OUTPUT
-          echo "version=$VERSION" | tee -a $GITHUB_OUTPUT
       - name: Build matrix
       - name: Build matrix
         id: matrix
         id: matrix
         run: |
         run: |
@@ -91,7 +88,7 @@ jobs:
     uses: ./.github/workflows/build_packages.yaml
     uses: ./.github/workflows/build_packages.yaml
     with:
     with:
       profile: ${{ needs.prepare.outputs.profile }}
       profile: ${{ needs.prepare.outputs.profile }}
-      publish: ${{ needs.prepare.outputs.release }}
+      publish: true
       otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
       otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
       elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
       elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
       builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
       builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
@@ -104,8 +101,7 @@ jobs:
     uses: ./.github/workflows/build_and_push_docker_images.yaml
     uses: ./.github/workflows/build_and_push_docker_images.yaml
     with:
     with:
       profile: ${{ needs.prepare.outputs.profile }}
       profile: ${{ needs.prepare.outputs.profile }}
-      version: ${{ needs.prepare.outputs.version }}
-      publish: ${{ needs.prepare.outputs.release }}
+      publish: true
       latest: ${{ needs.prepare.outputs.latest }}
       latest: ${{ needs.prepare.outputs.latest }}
       # TODO: revert this back to needs.prepare.outputs.otp_vsn when OTP 26 bug is fixed
       # TODO: revert this back to needs.prepare.outputs.otp_vsn when OTP 26 bug is fixed
       otp_vsn: 25.3.2-2
       otp_vsn: 25.3.2-2

+ 125 - 51
.github/workflows/build_and_push_docker_images.yaml

@@ -10,15 +10,12 @@ on:
       profile:
       profile:
         required: true
         required: true
         type: string
         type: string
-      version:
-        required: true
-        type: string
       latest:
       latest:
         required: true
         required: true
         type: string
         type: string
       publish:
       publish:
         required: true
         required: true
-        type: string
+        type: boolean
       otp_vsn:
       otp_vsn:
         required: true
         required: true
         type: string
         type: string
@@ -45,8 +42,6 @@ on:
         required: false
         required: false
         type: string
         type: string
         default: 'emqx'
         default: 'emqx'
-      version:
-        required: true
       latest:
       latest:
         required: false
         required: false
         type: boolean
         type: boolean
@@ -72,8 +67,46 @@ permissions:
   contents: read
   contents: read
 
 
 jobs:
 jobs:
+  build:
+    runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.arch)) || 'ubuntu-22.04' }}
+    container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ inputs.otp_vsn }}-debian11"
+    outputs:
+      PKG_VSN: ${{ steps.build.outputs.PKG_VSN }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        profile:
+          - ${{ inputs.profile }}
+          - ${{ inputs.profile }}-elixir
+        arch:
+          - x64
+          - arm64
+
+    steps:
+      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+        with:
+          ref: ${{ github.event.inputs.ref }}
+      - run: git config --global --add safe.directory "$PWD"
+      - name: build release tarball
+        id: build
+        run: |
+          make ${{ matrix.profile }}-tgz
+      - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+        with:
+          name: "${{ matrix.profile }}-${{ matrix.arch }}.tar.gz"
+          path: "_packages/emqx*/emqx-*.tar.gz"
+          retention-days: 7
+          overwrite: true
+          if-no-files-found: error
+
   docker:
   docker:
     runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
     runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
+    needs:
+      - build
+    defaults:
+      run:
+        shell: bash
 
 
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
@@ -81,54 +114,95 @@ jobs:
         profile:
         profile:
           - ${{ inputs.profile }}
           - ${{ inputs.profile }}
           - ${{ inputs.profile }}-elixir
           - ${{ inputs.profile }}-elixir
-        registry:
-          - 'docker.io'
-          - 'public.ecr.aws'
-        exclude:
-          - profile: emqx-enterprise
-            registry: 'public.ecr.aws'
-          - profile: emqx-enterprise-elixir
-            registry: 'public.ecr.aws'
 
 
     steps:
     steps:
-    - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
-      with:
-        ref: ${{ github.event.inputs.ref }}
-        fetch-depth: 0
+      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+        with:
+          ref: ${{ github.event.inputs.ref }}
+      - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
+        with:
+          pattern: "${{ matrix.profile }}-*.tar.gz"
+          path: _packages
+          merge-multiple: true
+
+      - name: Move artifacts to root directory
+        env:
+          PROFILE: ${{ inputs.profile }}
+        run: |
+          ls -lR _packages/$PROFILE
+          mv _packages/$PROFILE/*.tar.gz ./
+      - name: Enable containerd image store on Docker Engine
+        run: |
+          echo "$(jq '. += {"features": {"containerd-snapshotter": true}}' /etc/docker/daemon.json)" > daemon.json
+          sudo mv daemon.json /etc/docker/daemon.json
+          sudo systemctl restart docker
+
+      - uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
+      - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
 
 
-    - uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
-    - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
+      - name: Login to hub.docker.com
+        uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
+        if: inputs.publish || github.repository_owner != 'emqx'
+        with:
+          username: ${{ secrets.DOCKER_HUB_USER }}
+          password: ${{ secrets.DOCKER_HUB_TOKEN }}
 
 
-    - name: Login to hub.docker.com
-      uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
-      if: matrix.registry == 'docker.io'
-      with:
-        username: ${{ secrets.DOCKER_HUB_USER }}
-        password: ${{ secrets.DOCKER_HUB_TOKEN }}
+      - name: Login to AWS ECR
+        uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
+        if: inputs.publish || github.repository_owner != 'emqx'
+        with:
+          registry: public.ecr.aws
+          username: ${{ secrets.AWS_ACCESS_KEY_ID }}
+          password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+          ecr: true
 
 
-    - name: Login to AWS ECR
-      uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
-      if: matrix.registry == 'public.ecr.aws'
-      with:
-        registry: public.ecr.aws
-        username: ${{ secrets.AWS_ACCESS_KEY_ID }}
-        password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
-        ecr: true
+      - name: Build docker image
+        env:
+          PROFILE: ${{ matrix.profile }}
+          DOCKER_REGISTRY: 'docker.io,public.ecr.aws'
+          DOCKER_ORG: ${{ github.repository_owner }}
+          DOCKER_LATEST: ${{ inputs.latest }}
+          DOCKER_PUSH: false
+          DOCKER_BUILD_NOCACHE: true
+          DOCKER_PLATFORMS: linux/amd64,linux/arm64
+          DOCKER_LOAD: true
+          EMQX_RUNNER: 'public.ecr.aws/debian/debian:11-slim@sha256:22cfb3c06a7dd5e18d86123a73405664475b9d9fa209cbedcf4c50a25649cc74'
+          EMQX_DOCKERFILE: 'deploy/docker/Dockerfile'
+          PKG_VSN: ${{ needs.build.outputs.PKG_VSN }}
+          EMQX_BUILDER_VERSION: ${{ inputs.builder_vsn }}
+          EMQX_BUILDER_OTP: ${{ inputs.otp_vsn }}
+          EMQX_BUILDER_ELIXIR: ${{ inputs.elixir_vsn }}
+          EMQX_SOURCE_TYPE: tgz
+        run: |
+          ./build ${PROFILE} docker
+          cat .emqx_docker_image_tags
+          echo "_EMQX_DOCKER_IMAGE_TAG=$(head -n 1 .emqx_docker_image_tags)" >> $GITHUB_ENV
 
 
-    - name: Build docker image
-      env:
-        PROFILE: ${{ matrix.profile }}
-        DOCKER_REGISTRY: ${{ matrix.registry }}
-        DOCKER_ORG: ${{ github.repository_owner }}
-        DOCKER_LATEST: ${{ inputs.latest }}
-        DOCKER_PUSH: ${{ inputs.publish == 'true' || inputs.publish || github.repository_owner != 'emqx' }}
-        DOCKER_BUILD_NOCACHE: true
-        DOCKER_PLATFORMS: linux/amd64,linux/arm64
-        EMQX_RUNNER: 'debian:11-slim'
-        EMQX_DOCKERFILE: 'deploy/docker/Dockerfile'
-        PKG_VSN: ${{ inputs.version }}
-        EMQX_BUILDER_VERSION: ${{ inputs.builder_vsn }}
-        EMQX_BUILDER_OTP: ${{ inputs.otp_vsn }}
-        EMQX_BUILDER_ELIXIR: ${{ inputs.elixir_vsn }}
-      run: |
-        ./build ${PROFILE} docker
+      - name: smoke test
+        timeout-minutes: 1
+        run: |
+          for tag in $(cat .emqx_docker_image_tags); do
+            CID=$(docker run -d -P $_EMQX_DOCKER_IMAGE_TAG)
+            HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
+            ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
+            docker rm -f $CID
+          done
+      - name: dashboard tests
+        working-directory: ./scripts/ui-tests
+        timeout-minutes: 5
+        run: |
+          set -eu
+          docker compose up --abort-on-container-exit --exit-code-from selenium
+          docker compose rm -fsv
+      - name: test node_dump
+        run: |
+          CID=$(docker run -d -P $_EMQX_DOCKER_IMAGE_TAG)
+          docker exec -t -u root -w /root $CID bash -c 'apt-get -y update && apt-get -y install net-tools'
+          docker exec -t -u root $CID node_dump
+          docker rm -f $CID
+      - name: push images
+        if: inputs.publish || github.repository_owner != 'emqx'
+        run: |
+          for tag in $(cat .emqx_docker_image_tags); do
+            docker push $tag
+          done

+ 3 - 3
.github/workflows/build_docker_for_test.yaml

@@ -47,16 +47,16 @@ jobs:
         id: build
         id: build
         run: |
         run: |
           make ${EMQX_NAME}-docker
           make ${EMQX_NAME}-docker
-          echo "EMQX_IMAGE_TAG=$(cat .docker_image_tag)" >> $GITHUB_ENV
+          echo "_EMQX_DOCKER_IMAGE_TAG=$(head -n 1 .emqx_docker_image_tags)" >> $GITHUB_ENV
       - name: smoke test
       - name: smoke test
         run: |
         run: |
-          CID=$(docker run -d --rm -P $EMQX_IMAGE_TAG)
+          CID=$(docker run -d --rm -P $_EMQX_DOCKER_IMAGE_TAG)
           HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
           HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
           ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
           ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
           docker stop $CID
           docker stop $CID
       - name: export docker image
       - name: export docker image
         run: |
         run: |
-          docker save $EMQX_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz
+          docker save $_EMQX_DOCKER_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz
       - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0
       - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0
         with:
         with:
           name: "${{ env.EMQX_NAME }}-docker"
           name: "${{ env.EMQX_NAME }}-docker"

+ 2 - 2
.github/workflows/build_packages.yaml

@@ -12,7 +12,7 @@ on:
         type: string
         type: string
       publish:
       publish:
         required: true
         required: true
-        type: string
+        type: boolean
       otp_vsn:
       otp_vsn:
         required: true
         required: true
         type: string
         type: string
@@ -203,7 +203,7 @@ jobs:
     needs:
     needs:
       - mac
       - mac
       - linux
       - linux
-    if: inputs.publish == 'true' || inputs.publish
+    if: inputs.publish
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:

+ 4 - 4
.github/workflows/run_docker_tests.yaml

@@ -43,8 +43,8 @@ jobs:
           path: /tmp
           path: /tmp
       - name: load docker image
       - name: load docker image
         run: |
         run: |
-          EMQX_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g')
-          echo "EMQX_IMAGE_TAG=$EMQX_IMAGE_TAG" >> $GITHUB_ENV
+          _EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g')
+          echo "_EMQX_DOCKER_IMAGE_TAG=$_EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
       - name: dashboard tests
       - name: dashboard tests
         working-directory: ./scripts/ui-tests
         working-directory: ./scripts/ui-tests
         run: |
         run: |
@@ -52,7 +52,7 @@ jobs:
           docker compose up --abort-on-container-exit --exit-code-from selenium
           docker compose up --abort-on-container-exit --exit-code-from selenium
       - name: test two nodes cluster with proto_dist=inet_tls in docker
       - name: test two nodes cluster with proto_dist=inet_tls in docker
         run: |
         run: |
-          ./scripts/test/start-two-nodes-in-docker.sh -P $EMQX_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG
+          ./scripts/test/start-two-nodes-in-docker.sh -P $_EMQX_DOCKER_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG
           HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy)
           HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy)
           ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
           ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
           ./scripts/test/start-two-nodes-in-docker.sh -c
           ./scripts/test/start-two-nodes-in-docker.sh -c
@@ -113,4 +113,4 @@ jobs:
       - name: test node_dump
       - name: test node_dump
         run: |
         run: |
           docker exec -t -u root node1.emqx.io bash -c 'apt-get -y update && apt-get -y install net-tools'
           docker exec -t -u root node1.emqx.io bash -c 'apt-get -y update && apt-get -y install net-tools'
-          docker exec node1.emqx.io node_dump
+          docker exec -t -u root node1.emqx.io node_dump

+ 30 - 10
build

@@ -394,7 +394,7 @@ make_docker() {
     local EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}}
     local EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}}
     local EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}"
     local EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}"
     local EMQX_DOCKERFILE="${EMQX_DOCKERFILE:-deploy/docker/Dockerfile}"
     local EMQX_DOCKERFILE="${EMQX_DOCKERFILE:-deploy/docker/Dockerfile}"
-    local PKG_VSN="${PKG_VSN:-$(./pkg-vsn.sh)}"
+    local EMQX_SOURCE_TYPE="${EMQX_SOURCE_TYPE:-src}"
     # shellcheck disable=SC2155
     # shellcheck disable=SC2155
     local VSN_MAJOR="$(scripts/semver.sh "$PKG_VSN" --major)"
     local VSN_MAJOR="$(scripts/semver.sh "$PKG_VSN" --major)"
     # shellcheck disable=SC2155
     # shellcheck disable=SC2155
@@ -406,8 +406,14 @@ make_docker() {
         SUFFIX="-elixir"
         SUFFIX="-elixir"
     fi
     fi
     local DOCKER_REGISTRY="${DOCKER_REGISTRY:-docker.io}"
     local DOCKER_REGISTRY="${DOCKER_REGISTRY:-docker.io}"
+    local DOCKER_REGISTRIES=( )
+    IFS=',' read -ra DOCKER_REGISTRY_ARR <<< "$DOCKER_REGISTRY"
+    for r in "${DOCKER_REGISTRY_ARR[@]}"; do
+        # append to DOCKER_REGISTRIES
+        DOCKER_REGISTRIES+=("$r")
+    done
     local DOCKER_ORG="${DOCKER_ORG:-emqx}"
     local DOCKER_ORG="${DOCKER_ORG:-emqx}"
-    local EMQX_BASE_DOCKER_TAG="${DOCKER_REGISTRY}/${DOCKER_ORG}/${PROFILE%%-elixir}"
+    local EMQX_BASE_DOCKER_TAG="${DOCKER_ORG}/${PROFILE%%-elixir}"
     local default_tag="${EMQX_BASE_DOCKER_TAG}:${PKG_VSN}${SUFFIX}"
     local default_tag="${EMQX_BASE_DOCKER_TAG}:${PKG_VSN}${SUFFIX}"
     local EMQX_IMAGE_TAG="${EMQX_IMAGE_TAG:-$default_tag}"
     local EMQX_IMAGE_TAG="${EMQX_IMAGE_TAG:-$default_tag}"
     local EDITION=Opensource
     local EDITION=Opensource
@@ -432,11 +438,14 @@ make_docker() {
     local DOCKER_BUILDX_ARGS=(
     local DOCKER_BUILDX_ARGS=(
        --build-arg BUILD_FROM="${EMQX_BUILDER}" \
        --build-arg BUILD_FROM="${EMQX_BUILDER}" \
        --build-arg RUN_FROM="${EMQX_RUNNER}" \
        --build-arg RUN_FROM="${EMQX_RUNNER}" \
-       --build-arg EMQX_NAME="${PROFILE}" \
+       --build-arg SOURCE_TYPE="${EMQX_SOURCE_TYPE}" \
+       --build-arg PROFILE="${PROFILE%%-elixir}" \
+       --build-arg IS_ELIXIR="$([[ "$PROFILE" = *-elixir ]] && echo yes || echo no)" \
+       --build-arg SUFFIX="${SUFFIX}" \
        --build-arg EXTRA_DEPS="${EXTRA_DEPS}" \
        --build-arg EXTRA_DEPS="${EXTRA_DEPS}" \
        --build-arg PKG_VSN="${PKG_VSN}" \
        --build-arg PKG_VSN="${PKG_VSN}" \
        --file "${EMQX_DOCKERFILE}" \
        --file "${EMQX_DOCKERFILE}" \
-       --label org.opencontainers.image.title="${PROFILE}" \
+       --label org.opencontainers.image.title="${PROFILE%%-elixir}" \
        --label org.opencontainers.image.edition="${EDITION}" \
        --label org.opencontainers.image.edition="${EDITION}" \
        --label org.opencontainers.image.version="${PKG_VSN}" \
        --label org.opencontainers.image.version="${PKG_VSN}" \
        --label org.opencontainers.image.revision="${GIT_REVISION}" \
        --label org.opencontainers.image.revision="${GIT_REVISION}" \
@@ -447,9 +456,13 @@ make_docker() {
        --label org.opencontainers.image.documentation="${DOCUMENTATION_URL}" \
        --label org.opencontainers.image.documentation="${DOCUMENTATION_URL}" \
        --label org.opencontainers.image.licenses="${LICENSE}" \
        --label org.opencontainers.image.licenses="${LICENSE}" \
        --label org.opencontainers.image.otp.version="${EMQX_BUILDER_OTP}" \
        --label org.opencontainers.image.otp.version="${EMQX_BUILDER_OTP}" \
-       --tag "${EMQX_IMAGE_TAG}" \
        --pull
        --pull
     )
     )
+    :> ./.emqx_docker_image_tags
+    for r in "${DOCKER_REGISTRIES[@]}"; do
+        DOCKER_BUILDX_ARGS+=(--tag "$r/${EMQX_IMAGE_TAG}")
+        echo "$r/${EMQX_IMAGE_TAG}" >> ./.emqx_docker_image_tags
+    done
     if [ "${DOCKER_BUILD_NOCACHE:-false}" = true ]; then
     if [ "${DOCKER_BUILD_NOCACHE:-false}" = true ]; then
         DOCKER_BUILDX_ARGS+=(--no-cache)
         DOCKER_BUILDX_ARGS+=(--no-cache)
     fi
     fi
@@ -457,9 +470,14 @@ make_docker() {
         DOCKER_BUILDX_ARGS+=(--label org.opencontainers.image.elixir.version="${EMQX_BUILDER_ELIXIR}")
         DOCKER_BUILDX_ARGS+=(--label org.opencontainers.image.elixir.version="${EMQX_BUILDER_ELIXIR}")
     fi
     fi
     if [ "${DOCKER_LATEST:-false}" = true ]; then
     if [ "${DOCKER_LATEST:-false}" = true ]; then
-        DOCKER_BUILDX_ARGS+=(--tag "${EMQX_BASE_DOCKER_TAG}:latest${SUFFIX}")
-        DOCKER_BUILDX_ARGS+=(--tag "${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}${SUFFIX}")
-        DOCKER_BUILDX_ARGS+=(--tag "${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}.${VSN_PATCH}${SUFFIX}")
+        for r in "${DOCKER_REGISTRIES[@]}"; do
+          DOCKER_BUILDX_ARGS+=(--tag "$r/${EMQX_BASE_DOCKER_TAG}:latest${SUFFIX}")
+          echo "$r/${EMQX_BASE_DOCKER_TAG}:latest${SUFFIX}" >> ./.emqx_docker_image_tags
+          DOCKER_BUILDX_ARGS+=(--tag "$r/${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}${SUFFIX}")
+          echo "$r/${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}${SUFFIX}" >> ./.emqx_docker_image_tags
+          DOCKER_BUILDX_ARGS+=(--tag "$r/${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}.${VSN_PATCH}${SUFFIX}")
+          echo "$r/${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}.${VSN_PATCH}${SUFFIX}" >> ./.emqx_docker_image_tags
+        done
     fi
     fi
     if [ "${DOCKER_PLATFORMS:-default}" != 'default' ]; then
     if [ "${DOCKER_PLATFORMS:-default}" != 'default' ]; then
         DOCKER_BUILDX_ARGS+=(--platform "${DOCKER_PLATFORMS}")
         DOCKER_BUILDX_ARGS+=(--platform "${DOCKER_PLATFORMS}")
@@ -467,6 +485,9 @@ make_docker() {
     if [ "${DOCKER_PUSH:-false}" = true ]; then
     if [ "${DOCKER_PUSH:-false}" = true ]; then
         DOCKER_BUILDX_ARGS+=(--push)
         DOCKER_BUILDX_ARGS+=(--push)
     fi
     fi
+    if [ "${DOCKER_LOAD:-false}" = true ]; then
+        DOCKER_BUILDX_ARGS+=(--load)
+    fi
     if [ -d "${REBAR_GIT_CACHE_DIR:-}" ]; then
     if [ -d "${REBAR_GIT_CACHE_DIR:-}" ]; then
         cache_tar="$(pwd)/rebar-git-cache.tar"
         cache_tar="$(pwd)/rebar-git-cache.tar"
         if [ ! -f "${cache_tar}" ]; then
         if [ ! -f "${cache_tar}" ]; then
@@ -492,9 +513,8 @@ make_docker() {
         echo 'lux_logs/'
         echo 'lux_logs/'
         echo '_upgrade_base/'
         echo '_upgrade_base/'
     } >> ./.dockerignore
     } >> ./.dockerignore
-    echo "Docker build args: ${DOCKER_BUILDX_ARGS[*]}"
+    echo "Docker buildx args: ${DOCKER_BUILDX_ARGS[*]}"
     docker buildx build "${DOCKER_BUILDX_ARGS[@]}" .
     docker buildx build "${DOCKER_BUILDX_ARGS[@]}" .
-    echo "${EMQX_IMAGE_TAG}" > ./.docker_image_tag
 }
 }
 
 
 function join {
 function join {

+ 35 - 27
deploy/docker/Dockerfile

@@ -1,35 +1,43 @@
 ARG BUILD_FROM=ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-debian11@sha256:48b62a5636bd6bc59688fc98a498401fccf456fa63d843aa0b7279f3bc20b22e
 ARG BUILD_FROM=ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-debian11@sha256:48b62a5636bd6bc59688fc98a498401fccf456fa63d843aa0b7279f3bc20b22e
 ARG RUN_FROM=public.ecr.aws/debian/debian:11-slim@sha256:22cfb3c06a7dd5e18d86123a73405664475b9d9fa209cbedcf4c50a25649cc74
 ARG RUN_FROM=public.ecr.aws/debian/debian:11-slim@sha256:22cfb3c06a7dd5e18d86123a73405664475b9d9fa209cbedcf4c50a25649cc74
-FROM ${BUILD_FROM} AS builder
-ARG DEBUG=0
+ARG SOURCE_TYPE=src # tgz
 
 
-COPY . /emqx
+FROM ${BUILD_FROM} as builder_src
+ONBUILD COPY . /emqx
 
 
-ARG EMQX_NAME=emqx
+FROM ${BUILD_FROM} as builder_tgz
+ARG PROFILE=emqx
 ARG PKG_VSN
 ARG PKG_VSN
+ARG SUFFIX
+ARG TARGETARCH
+ONBUILD COPY ${PROFILE}-${PKG_VSN}${SUFFIX}-debian11-$TARGETARCH.tar.gz /${PROFILE}.tar.gz
+
+FROM builder_${SOURCE_TYPE} as builder
+
+ARG PROFILE=emqx
+ARG IS_ELIXIR=no
+ARG DEBUG=0
 
 
 ENV EMQX_RELUP=false
 ENV EMQX_RELUP=false
-ENV DEBUG=${DEBUG}
 ENV EMQX_REL_FORM='docker'
 ENV EMQX_REL_FORM='docker'
 
 
 WORKDIR /emqx/
 WORKDIR /emqx/
 
 
-RUN git config --global --add safe.directory '*'
-
-RUN if [ -f rebar-git-cache.tar ]; then \
+RUN mkdir -p /emqx-rel/emqx && \
+    if [ -f "/${PROFILE}.tar.gz" ]; then \
+      tar zxf "/${PROFILE}.tar.gz" -C /emqx-rel/emqx; \
+    else \
+      if [ -f rebar-git-cache.tar ]; then \
         mkdir .cache && \
         mkdir .cache && \
         tar -xf rebar-git-cache.tar -C .cache && \
         tar -xf rebar-git-cache.tar -C .cache && \
         export REBAR_GIT_CACHE_DIR='/emqx/.cache' && \
         export REBAR_GIT_CACHE_DIR='/emqx/.cache' && \
-        export REBAR_GIT_CACHE_REF_AUTOFILL=0 ;\
-    fi \
-    && export PROFILE=${EMQX_NAME%%-elixir} \
-    && export EMQX_NAME1="${EMQX_NAME}" \
-    && export EMQX_NAME=${PROFILE} \
-    && export EMQX_REL_PATH="/emqx/_build/${EMQX_NAME}/rel/emqx" \
-    && make ${EMQX_NAME1} \
-    && rm -f ${EMQX_REL_PATH}/*.tar.gz \
-    && mkdir -p /emqx-rel \
-    && mv ${EMQX_REL_PATH} /emqx-rel
+        export REBAR_GIT_CACHE_REF_AUTOFILL=0; \
+      fi && \
+      export EMQX_REL_PATH="/emqx/_build/${PROFILE}/rel/emqx" && \
+      git config --global --add safe.directory '*' && \
+      make ${PROFILE}-tgz && \
+      tar zxf _packages/${PROFILE}/*.tar.gz -C /emqx-rel/emqx; \
+    fi
 
 
 FROM $RUN_FROM
 FROM $RUN_FROM
 ARG EXTRA_DEPS=''
 ARG EXTRA_DEPS=''
@@ -39,21 +47,21 @@ ENV LC_ALL=C.UTF-8
 ENV LANG=C.UTF-8
 ENV LANG=C.UTF-8
 
 
 COPY deploy/docker/docker-entrypoint.sh /usr/bin/
 COPY deploy/docker/docker-entrypoint.sh /usr/bin/
-COPY --from=builder /emqx-rel/emqx /opt/emqx
-
-RUN ln -s /opt/emqx/bin/* /usr/local/bin/
-
-RUN apt-get update; \
-    apt-get install -y --no-install-recommends ca-certificates procps $(echo "${EXTRA_DEPS}" | tr ',' ' '); \
-    rm -rf /var/lib/apt/lists/*
+COPY --from=builder /emqx-rel /opt/
 
 
 WORKDIR /opt/emqx
 WORKDIR /opt/emqx
 
 
-RUN groupadd -r -g 1000 emqx; \
+RUN set -eu; \
+    apt-get update; \
+    apt-get install -y --no-install-recommends ca-certificates procps $(echo "${EXTRA_DEPS}" | tr ',' ' '); \
+    find /opt/emqx -name 'swagger*.js.map' -exec rm {} +; \
+    groupadd -r -g 1000 emqx; \
     useradd -r -m -u 1000 -g emqx emqx; \
     useradd -r -m -u 1000 -g emqx emqx; \
     chgrp -Rf emqx /opt/emqx; \
     chgrp -Rf emqx /opt/emqx; \
     chmod -Rf g+w /opt/emqx; \
     chmod -Rf g+w /opt/emqx; \
-    chown -Rf emqx /opt/emqx
+    chown -Rf emqx /opt/emqx; \
+    ln -s /opt/emqx/bin/* /usr/local/bin/; \
+    rm -rf /var/lib/apt/lists/*
 
 
 USER emqx
 USER emqx
 
 

+ 1 - 1
deploy/docker/docker-entrypoint.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 #!/usr/bin/env bash
 
 
-## EMQ docker image start script
+## EMQX docker image start script
 
 
 if [[ -n "$DEBUG" ]]; then
 if [[ -n "$DEBUG" ]]; then
     set -ex
     set -ex

+ 1 - 1
scripts/ui-tests/docker-compose.yaml

@@ -2,7 +2,7 @@ version: '3.9'
 
 
 services:
 services:
   emqx:
   emqx:
-    image: ${EMQX_IMAGE_TAG:-emqx/emqx:latest}
+    image: ${_EMQX_DOCKER_IMAGE_TAG:-emqx/emqx:latest}
     environment:
     environment:
       EMQX_DASHBOARD__DEFAULT_PASSWORD: admin
       EMQX_DASHBOARD__DEFAULT_PASSWORD: admin