Merge pull request #137 from vcon-dev/optimize-docker-images #83
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Push Docker images | |
| # CalVer Release Workflow | |
| # | |
| # Automatically creates a CalVer release on every push to main. | |
| # Version format: YYYY.MM.DD (e.g., 2026.01.16) | |
| # If multiple releases happen on the same day, adds sequence: YYYY.MM.DD.2, YYYY.MM.DD.3, etc. | |
| # | |
| # Two separate images are built and pushed for both linux/amd64 and linux/arm64: | |
| # vcon-server-api — lightweight FastAPI/uvicorn image (main deps only) | |
| # vcon-server-conserver — full processing image (main + links + storage deps) | |
| # | |
| # Build strategy: native runners (no QEMU) for maximum speed | |
| # amd64 builds on ubuntu-latest | |
| # arm64 builds on ubuntu-24.04-arm | |
| # | |
| # Docker tags created for each image: | |
| # - CalVer tag (e.g., 2026.01.16) [main only] | |
| # - latest [main only] | |
| # - Branch name (e.g., main) | |
| # - Branch + short sha (e.g., main-a1b2c3d) | |
| on: | |
| push: | |
| branches: [main, release-test, optimize-docker-images] | |
| tags: ['v*'] | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # needed to create git tags | |
| outputs: | |
| version: ${{ steps.calver.outputs.version }} | |
| short_sha: ${{ steps.git.outputs.short_sha }} | |
| build_time: ${{ steps.git.outputs.build_time }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Generate CalVer version | |
| id: calver | |
| run: | | |
| TODAY=$(date +"%Y.%m.%d") | |
| EXISTING_TAGS=$(git tag -l "${TODAY}*" | sort -V) | |
| if [ -z "$EXISTING_TAGS" ]; then | |
| VERSION="${TODAY}" | |
| else | |
| LAST_TAG=$(echo "$EXISTING_TAGS" | tail -1) | |
| if [[ "$LAST_TAG" == "$TODAY" ]]; then | |
| VERSION="${TODAY}.2" | |
| elif [[ "$LAST_TAG" =~ ^${TODAY}\.([0-9]+)$ ]]; then | |
| SEQ="${BASH_REMATCH[1]}" | |
| VERSION="${TODAY}.$((SEQ + 1))" | |
| else | |
| VERSION="${TODAY}.2" | |
| fi | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "Generated CalVer version: ${VERSION}" | |
| - name: Get git commit info | |
| id: git | |
| run: | | |
| echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | |
| echo "build_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT | |
| - name: Create git tag | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| if git rev-parse "${{ steps.calver.outputs.version }}" >/dev/null 2>&1; then | |
| echo "Tag ${{ steps.calver.outputs.version }} already exists, skipping" | |
| else | |
| git tag -a "${{ steps.calver.outputs.version }}" -m "Release ${{ steps.calver.outputs.version }}" | |
| git push origin "${{ steps.calver.outputs.version }}" | |
| echo "Created and pushed tag ${{ steps.calver.outputs.version }}" | |
| fi | |
| build: | |
| needs: prepare | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| include: | |
| - service: api | |
| dockerfile: ./docker/Dockerfile.api | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-api | |
| platform: linux/amd64 | |
| platform_tag: amd64 | |
| runner: ubuntu-latest | |
| - service: api | |
| dockerfile: ./docker/Dockerfile.api | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-api | |
| platform: linux/arm64 | |
| platform_tag: arm64 | |
| runner: ubuntu-24.04-arm | |
| - service: conserver | |
| dockerfile: ./docker/Dockerfile.conserver | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-conserver | |
| platform: linux/amd64 | |
| platform_tag: amd64 | |
| runner: ubuntu-latest | |
| - service: conserver | |
| dockerfile: ./docker/Dockerfile.conserver | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-conserver | |
| platform: linux/arm64 | |
| platform_tag: arm64 | |
| runner: ubuntu-24.04-arm | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Amazon ECR Public | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: public.ecr.aws | |
| username: ${{ secrets.AWS_ACCESS_KEY }} | |
| password: ${{ secrets.AWS_SECRET }} | |
| - name: Build and push ${{ matrix.service }} (${{ matrix.platform_tag }}) | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ${{ matrix.dockerfile }} | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| cache-from: type=gha,scope=${{ matrix.service }}-${{ matrix.platform_tag }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.service }}-${{ matrix.platform_tag }} | |
| tags: ${{ matrix.image }}:${{ github.ref_name }}-${{ matrix.platform_tag }} | |
| build-args: | | |
| VCON_SERVER_VERSION=${{ needs.prepare.outputs.version }} | |
| VCON_SERVER_GIT_COMMIT=${{ needs.prepare.outputs.short_sha }} | |
| VCON_SERVER_BUILD_TIME=${{ needs.prepare.outputs.build_time }} | |
| merge: | |
| needs: [prepare, build] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| include: | |
| - service: api | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-api | |
| - service: conserver | |
| image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-conserver | |
| steps: | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Amazon ECR Public | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: public.ecr.aws | |
| username: ${{ secrets.AWS_ACCESS_KEY }} | |
| password: ${{ secrets.AWS_SECRET }} | |
| - name: Create multi-arch manifest for ${{ matrix.service }} | |
| env: | |
| IMAGE: ${{ matrix.image }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| SHORT_SHA: ${{ needs.prepare.outputs.short_sha }} | |
| BRANCH: ${{ github.ref_name }} | |
| run: | | |
| AMD64="${IMAGE}:${BRANCH}-amd64" | |
| ARM64="${IMAGE}:${BRANCH}-arm64" | |
| # Branch tag (always) | |
| docker buildx imagetools create --tag "${IMAGE}:${BRANCH}" "${AMD64}" "${ARM64}" | |
| # Branch + sha tag (always) | |
| docker buildx imagetools create --tag "${IMAGE}:${BRANCH}-${SHORT_SHA}" "${AMD64}" "${ARM64}" | |
| # CalVer and latest (main only) | |
| if [ "${BRANCH}" = "main" ]; then | |
| docker buildx imagetools create --tag "${IMAGE}:${VERSION}" "${AMD64}" "${ARM64}" | |
| docker buildx imagetools create --tag "${IMAGE}:latest" "${AMD64}" "${ARM64}" | |
| fi | |
| release: | |
| needs: [prepare, merge] | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ needs.prepare.outputs.version }} | |
| name: Release ${{ needs.prepare.outputs.version }} | |
| body: | | |
| ## Release ${{ needs.prepare.outputs.version }} | |
| **Commit:** ${{ needs.prepare.outputs.short_sha }} | |
| **Build Time:** ${{ needs.prepare.outputs.build_time }} | |
| ### Docker Images | |
| Both images support `linux/amd64` and `linux/arm64`. | |
| **API service** (FastAPI/uvicorn, lightweight): | |
| ```bash | |
| docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-api:${{ needs.prepare.outputs.version }} | |
| docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-api:latest | |
| ``` | |
| **Conserver service** (processing pipeline, full dependencies): | |
| ```bash | |
| docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-conserver:${{ needs.prepare.outputs.version }} | |
| docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server-conserver:latest | |
| ``` | |
| draft: false | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Summary | |
| run: | | |
| echo "## Build Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Version** | ${{ needs.prepare.outputs.version }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Git Commit** | ${{ needs.prepare.outputs.short_sha }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Build Time** | ${{ needs.prepare.outputs.build_time }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Branch** | ${{ github.ref_name }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Docker Images Built (linux/amd64 + linux/arm64)" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`vcon-server-api\` — API service (main deps only)" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`vcon-server-conserver\` — Conserver service (main + links + storage)" >> $GITHUB_STEP_SUMMARY |