name: Docker Build + Push description: Build and push Docker images with buildx and layer caching for Gitea Actions author: eric inputs: dockerfile: description: Path to Dockerfile (relative to build_context) default: Dockerfile context: description: Build context path (relative to repo root) default: . image-name: description: Full image name (e.g. registry/image or image) required: true tags: description: Additional tags as CSV appended to defaults default: "" cache-from: description: Cache source (e.g. type=gha, or image:tag) default: type=local,src=/tmp/buildx-cache cache-to: description: Cache destination for buildx (type=gha or type=local) default: type=local,dest=/tmp/buildx-cache,mode=max registry: description: Docker registry for login (e.g. ghcr.io) default: "" registry-username: description: Docker registry username default: "" registry-password: description: Docker registry password (use secrets.DOCKER_PASSWORD) default: "" platforms: description: Target platforms as CSV (e.g. linux/amd64,linux/arm64) default: linux/amd64 push: description: Push images to registry after build default: "false" build-args: description: Build args as CSV KEY=VALUE default: "" outputs: image: description: Full image name with tag value: ${{ steps.meta.outputs.image }} tag: description: The primary tag used (date-SHA) value: ${{ steps.meta.outputs.tag }} digest: description: Image digest (only available after push) value: ${{ steps.push-digest.outputs.digest }} runs: using: composite env: DOCKER_HOST: tcp://docker.local:2375 DOCKER_BUILDKIT: "1" BUILDKIT_HOST: tcp://docker.local:2375 steps: - name: Set up QEMU for multi-platform builds shell: bash if: inputs.platforms != 'linux/amd64' run: | docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 2>/dev/null || true - name: Set up Docker Buildx id: buildx shell: bash run: | mkdir -p $HOME/.docker/cli-plugins curl -fsSL https://github.com/docker/buildx/releases/download/v0.12.1/buildx-v0.12.1.linux-amd64 \ -o $HOME/.docker/cli-plugins/docker-buildx chmod +x $HOME/.docker/cli-plugins/docker-buildx docker buildx version # Try docker-container driver first (for multi-platform), fall back to docker driver BUILDER_SETUP=false if docker buildx create \ --name gitea-builder \ --driver docker-container \ --driver-opt image=moby/buildkit:buildx-stable-1 \ --driver-opt network=host \ --use 2>&1; then if docker buildx inspect --bootstrap 2>&1; then BUILDER_SETUP=true fi fi if [ "$BUILDER_SETUP" != "true" ]; then docker buildx rm -f gitea-builder 2>/dev/null || true docker buildx create --name gitea-builder --driver docker --use docker buildx inspect --bootstrap fi - name: Compute metadata id: meta shell: bash run: | # Generate tags TAGS="latest" if [ -n "${{ inputs.tags }}" ]; then TAGS="$TAGS,${{ inputs.tags }}" fi SHORT_SHA="$(git rev-parse --short HEAD 2>/dev/null || echo 'local')" DATE_TAG="$(date +%Y-%m-%d)" TAG="$DATE_TAG-$SHORT_SHA" TAGS="$TAGS,$TAG" # Add git tag if this is a tag push if [[ "${{ github.ref }}" == refs/tags/* ]]; then TAG_NAME="${{ github.ref_name }}" TAGS="$TAGS,$TAG_NAME" fi echo "image=${{ inputs.image-name }}" >> $GITHUB_OUTPUT echo "tag=$TAG" >> $GITHUB_OUTPUT echo "tags=$TAGS" >> $GITHUB_OUTPUT - name: Log in to Docker registry shell: bash run: | if [ -n "${{ inputs.registry }}" ] && [ -n "${{ inputs.registry-password }}" ]; then echo "${{ inputs.registry-password }}" | docker login ${{ inputs.registry }} -u ${{ inputs.registry-username }} --password-stdin fi - name: Build image id: build shell: bash env: DOCKER_BUILDKIT: "1" run: | CACHE_FROM_FLAG="" if [ -n "${{ inputs.cache-from }}" ]; then CACHE_FROM_FLAG="--cache-from=${{ inputs.cache-from }}" fi BUILD_ARGS_FLAG="" if [ -n "${{ inputs.build-args }}" ]; then for arg in $(echo "${{ inputs.build-args }}" | tr ',' ' '); do BUILD_ARGS_FLAG="$BUILD_ARGS_FLAG --build-arg=$arg" done fi PLATFORM_FLAG="" if [ "${{ inputs.platforms }}" != "linux/amd64" ]; then PLATFORM_FLAG="--platform=${{ inputs.platforms }}" fi # Choose output mode if [ "${{ inputs.push }}" = "true" ]; then OUTPUT_FLAG="--push --output=type=registry" else OUTPUT_FLAG="--load --output=type=docker" fi set -x docker buildx build \ $PLATFORM_FLAG \ --tag "${{ inputs.image-name }}:${{ steps.meta.outputs.tag }}" \ --tag "${{ inputs.image-name }}:latest" \ $(for t in $(echo ${{ steps.meta.outputs.tags }} | tr ',' ' '); do echo -n "--tag ${{ inputs.image-name }}:$t "; done) \ --file ${{ inputs.context }}/${{ inputs.dockerfile }} \ --cache-to=${{ inputs.cache-to }} \ $CACHE_FROM_FLAG \ $BUILD_ARGS_FLAG \ --progress=plain \ $OUTPUT_FLAG \ ${{ inputs.context }} - name: Get image digest id: push-digest shell: bash if: inputs.push == 'true' run: | DIGEST="$(docker inspect "${{ inputs.image-name }}:${{ steps.meta.outputs.tag }}" --format '{{.Digest}}' 2>/dev/null)" echo "digest=$DIGEST" >> $GITHUB_OUTPUT echo "digest_full=${{ inputs.image-name }}@$DIGEST" >> $GITHUB_OUTPUT