ci(docker): support layered overlay images in release-docker-dev (#28206)
This commit is contained in:
@@ -15,6 +15,18 @@ on:
|
|||||||
description: "Docker Hub repo to push to. Use lmsysorg/sglang-staging for testing."
|
description: "Docker Hub repo to push to. Use lmsysorg/sglang-staging for testing."
|
||||||
required: false
|
required: false
|
||||||
default: "lmsysorg/sglang"
|
default: "lmsysorg/sglang"
|
||||||
|
overlay_dockerfile:
|
||||||
|
description: "Optional extra Dockerfile lines appended after FROM <base> to build a layered image (e.g. 'RUN pip install ...'). Note: this job has no repo checkout, so only FROM + RUN work — you cannot COPY files from this repo. Leave empty to skip overlay."
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
overlay_cudas:
|
||||||
|
description: "Comma-separated cuda variants to overlay onto (cu12, cu13). Default 'cu13'."
|
||||||
|
required: false
|
||||||
|
default: "cu13"
|
||||||
|
overlay_tag_suffix:
|
||||||
|
description: "Overlay output suffix appended to the base tag. EMPTY = overwrite the base tag(s); non-empty = append (e.g. 'msa')."
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *"
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
@@ -30,9 +42,17 @@ jobs:
|
|||||||
checkout_ref: ${{ steps.config.outputs.checkout_ref }}
|
checkout_ref: ${{ steps.config.outputs.checkout_ref }}
|
||||||
extra_build_args: ${{ steps.config.outputs.extra_build_args }}
|
extra_build_args: ${{ steps.config.outputs.extra_build_args }}
|
||||||
tag_config: ${{ steps.config.outputs.tag_config }}
|
tag_config: ${{ steps.config.outputs.tag_config }}
|
||||||
|
overlay_cudas_json: ${{ steps.config.outputs.overlay_cudas_json }}
|
||||||
|
overlay_tags_json: ${{ steps.config.outputs.overlay_tags_json }}
|
||||||
steps:
|
steps:
|
||||||
- name: Compute build configuration
|
- name: Compute build configuration
|
||||||
id: config
|
id: config
|
||||||
|
env:
|
||||||
|
# Inject multi-line/free-text inputs via env to avoid ${{ }} injection
|
||||||
|
# breaking the bash script on quotes or $ in the Dockerfile snippet.
|
||||||
|
OVERLAY_DOCKERFILE_INPUT: ${{ inputs.overlay_dockerfile }}
|
||||||
|
OVERLAY_CUDAS_INPUT: ${{ inputs.overlay_cudas }}
|
||||||
|
OVERLAY_SUFFIX_INPUT: ${{ inputs.overlay_tag_suffix }}
|
||||||
run: |
|
run: |
|
||||||
# Determine checkout ref
|
# Determine checkout ref
|
||||||
if [ -n "${{ inputs.pr_number }}" ]; then
|
if [ -n "${{ inputs.pr_number }}" ]; then
|
||||||
@@ -67,6 +87,52 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "tag_config=${TAG_CONFIG}" >> $GITHUB_OUTPUT
|
echo "tag_config=${TAG_CONFIG}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Overlay configuration (optional). When overlay_dockerfile is set,
|
||||||
|
# build one or more layered images on top of the just-built base.
|
||||||
|
# SUFFIX was computed above from inputs.tag / inputs.pr_number.
|
||||||
|
if [ -n "${OVERLAY_DOCKERFILE_INPUT}" ]; then
|
||||||
|
# Refuse to overlay without a tag/pr_number: SUFFIX would be empty,
|
||||||
|
# so base would point at the moving 'dev'/'dev-cu12'/'dev-cu13'
|
||||||
|
# latest tags and overwrite mode would clobber them.
|
||||||
|
if [ -z "${SUFFIX}" ]; then
|
||||||
|
echo "overlay_dockerfile is set but neither 'tag' nor 'pr_number' was given." >&2
|
||||||
|
echo "Set one so the overlay targets a specific tag, not the moving 'dev' latest." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
CUDAS_INPUT="${OVERLAY_CUDAS_INPUT}"
|
||||||
|
[ -z "${CUDAS_INPUT}" ] && CUDAS_INPUT="cu13"
|
||||||
|
OVERLAY_TAGS='{}'
|
||||||
|
IFS=',' read -ra CUDAS <<< "${CUDAS_INPUT}"
|
||||||
|
for C in "${CUDAS[@]}"; do
|
||||||
|
C="$(echo "${C}" | xargs)"
|
||||||
|
if [ "${C}" = "cu13" ]; then
|
||||||
|
BASES='["dev'"${SUFFIX}"'","dev-cu13'"${SUFFIX}"'"]'
|
||||||
|
elif [ "${C}" = "cu12" ]; then
|
||||||
|
BASES='["dev-cu12'"${SUFFIX}"'"]'
|
||||||
|
else
|
||||||
|
echo "Unknown overlay cuda variant: ${C} (expected cu12 or cu13)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -n "${OVERLAY_SUFFIX_INPUT}" ]; then
|
||||||
|
# Append mode: primary base tag + suffix.
|
||||||
|
PRIMARY="$(echo "${BASES}" | jq -r '.[0]')"
|
||||||
|
OUTS='["'"${PRIMARY}-${OVERLAY_SUFFIX_INPUT}"'"]'
|
||||||
|
else
|
||||||
|
# Overwrite mode: replace every base alias.
|
||||||
|
OUTS="${BASES}"
|
||||||
|
fi
|
||||||
|
OVERLAY_TAGS="$(echo "${OVERLAY_TAGS}" | jq -c \
|
||||||
|
--arg c "${C}" --argjson b "${BASES}" --argjson o "${OUTS}" \
|
||||||
|
'.[$c] = {bases:$b, outs:$o}')"
|
||||||
|
done
|
||||||
|
CUDAS_JSON="$(echo "${CUDAS_INPUT}" | jq -c -R 'split(",") | map(gsub("^\\s+|\\s+$";""))')"
|
||||||
|
echo "overlay_cudas_json=${CUDAS_JSON}" >> $GITHUB_OUTPUT
|
||||||
|
echo "overlay_tags_json=${OVERLAY_TAGS}" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "overlay_cudas_json=[]" >> $GITHUB_OUTPUT
|
||||||
|
echo "overlay_tags_json={}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
build-and-publish:
|
build-and-publish:
|
||||||
needs: prepare
|
needs: prepare
|
||||||
uses: ./.github/workflows/_docker-build-and-publish.yml
|
uses: ./.github/workflows/_docker-build-and-publish.yml
|
||||||
@@ -86,3 +152,47 @@ jobs:
|
|||||||
tag_prefixes: '["nightly-dev", "nightly-dev-cu12", "nightly-dev-cu13"]'
|
tag_prefixes: '["nightly-dev", "nightly-dev-cu12", "nightly-dev-cu13"]'
|
||||||
image_repo: ${{ inputs.image_repo || 'lmsysorg/sglang' }}
|
image_repo: ${{ inputs.image_repo || 'lmsysorg/sglang' }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
build-overlay:
|
||||||
|
needs: [prepare, build-and-publish]
|
||||||
|
if: ${{ inputs.overlay_dockerfile != '' && github.repository == 'sgl-project/sglang' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cuda: ${{ fromJson(needs.prepare.outputs.overlay_cudas_json) }}
|
||||||
|
steps:
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push overlay image (amd64 + arm64)
|
||||||
|
env:
|
||||||
|
REPO: ${{ inputs.image_repo || 'lmsysorg/sglang' }}
|
||||||
|
TAGS: ${{ needs.prepare.outputs.overlay_tags_json }}
|
||||||
|
CUDA: ${{ matrix.cuda }}
|
||||||
|
# Injected via env to keep Dockerfile quotes/$ verbatim.
|
||||||
|
SNIPPET: ${{ inputs.overlay_dockerfile }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
BASE="$(printf '%s' "$TAGS" | jq -r --arg c "$CUDA" '.[$c].bases[0]')"
|
||||||
|
mapfile -t OUTS < <(printf '%s' "$TAGS" | jq -r --arg c "$CUDA" '.[$c].outs[]')
|
||||||
|
{
|
||||||
|
printf 'FROM %s:%s\n' "$REPO" "$BASE"
|
||||||
|
printf '%s\n' "$SNIPPET"
|
||||||
|
} > Dockerfile.overlay
|
||||||
|
echo "::group::overlay Dockerfile ($CUDA)"
|
||||||
|
cat Dockerfile.overlay
|
||||||
|
echo "::endgroup::"
|
||||||
|
OUT_ARGS=""
|
||||||
|
for o in "${OUTS[@]}"; do OUT_ARGS="$OUT_ARGS -t $REPO:$o"; done
|
||||||
|
docker buildx build \
|
||||||
|
--platform linux/amd64,linux/arm64 \
|
||||||
|
-f Dockerfile.overlay \
|
||||||
|
$OUT_ARGS \
|
||||||
|
--push .
|
||||||
|
|||||||
Reference in New Issue
Block a user