docker-flutter-sdk/PLAN.md
Mathias Beaulieu-Duncan 301f8e7397 Add plan for custom minimal Flutter SDK distribution using apko/melange
Documents the multi-stage approach: build Flutter from source in
Debian, package as APK with melange, compose minimal runtime image
from Wolfi packages with apko. Phased rollout starting with web
variant PoC.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 01:14:31 -05:00

8.9 KiB

Custom Minimal Flutter SDK Distribution

Goal

Build Flutter SDK from source in a multi-stage Docker build, then copy only the compiled SDK and its runtime dependencies into a custom minimal Linux base image. The result is a secure, minimal container with zero build toolchain bloat.

Architecture

┌─────────────────────────────────────┐
│  Stage 1: BUILD (debian:bookworm)   │
│                                     │
│  - Full build toolchain             │
│  - Compile Flutter engine + Dart    │
│  - All build-time deps              │
│  - Discarded after build            │
└──────────────┬──────────────────────┘
               │ COPY artifacts
               ▼
┌─────────────────────────────────────┐
│  Stage 2: RUNTIME (custom base)     │
│                                     │
│  - Minimal glibc + runtime libs     │
│  - Flutter SDK (pre-compiled)       │
│  - Only what's needed to run        │
│    `flutter build` commands         │
└─────────────────────────────────────┘

Approach: apko + melange on Wolfi

Use Chainguard's open-source tooling to build the runtime base image from Wolfi packages. This avoids maintaining a full Linux distribution while achieving the same result.

Why Wolfi (not Alpine, not from scratch)

  • glibc-based: Flutter/Dart require glibc (musl/Alpine won't work)
  • apk package format: Minimal, fast, composable
  • 15,000+ packages: glibc, libstdc++, git, curl, ca-certificates all available
  • Nightly CVE patching: Chainguard patches 80%+ of vulnerabilities within 24 hours
  • No distro maintenance burden: We consume their packages, not maintain them

Tools

Tool Purpose
melange Build custom APK packages (Flutter SDK, Android SDK) from source
apko Compose final OCI image from APK packages (Wolfi base + custom)

Stage 1: Build Flutter from Source

Flutter SDK source build requirements:

  • git (clone flutter/flutter and flutter/engine repos)
  • Python 3 (engine build scripts)
  • curl, unzip, xz-utils
  • clang/llvm (engine compilation)
  • ninja-build, gn (engine build system)
  • libstdc++-dev
  • Dart SDK (bootstrapped from prebuilt, then rebuilt)

Flutter engine build steps:

  1. Clone flutter/engine at the pinned revision from flutter/flutter/bin/internal/engine.version
  2. Run gclient sync to fetch dependencies
  3. Build with gn + ninja for target platform
  4. Dart SDK is built as part of the engine

Per-Variant Build Targets

Variant Engine build target Extra build deps Extra runtime deps
web host_release (dart2js/dart2wasm) None None
android android_release + android_release_arm64 Android NDK JDK 17, Android SDK cmdline-tools
linux linux_release_x64 GTK3-dev, CMake GTK3 runtime libs

Stage 2: Custom Runtime Base via apko

Web variant (minimal)

# apko.web.yaml
contents:
  keyring:
    - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
  repositories:
    - https://packages.wolfi.dev/os
    - @local /packages  # our melange-built Flutter SDK package
  packages:
    - wolfi-baselayout
    - glibc
    - libstdc++
    - git
    - ca-certificates-bundle
    - flutter-sdk-web@local
entrypoint:
  command: /bin/sh
environment:
  FLUTTER_HOME: /opt/flutter
  PATH: /opt/flutter/bin:/opt/flutter/bin/cache/dart-sdk/bin:/usr/bin:/bin
archs:
  - x86_64

Android variant

Same as web plus:

  • openjdk-17-jre (from Wolfi)
  • flutter-sdk-android@local (custom package including Android SDK components)

Linux desktop variant

Same as web plus:

  • gtk+3.0 runtime libs (from Wolfi, or custom melange package if not available)
  • flutter-sdk-linux@local

melange Package Definitions

flutter-sdk-web.melange.yaml (example structure)

package:
  name: flutter-sdk-web
  version: 3.38.9
  epoch: 0
  description: Flutter SDK for Web/WASM builds (compiled from source)

environment:
  contents:
    packages:
      - build-base
      - git
      - python3
      - curl
      - unzip
      - xz
      - clang
      - ninja
      - gn

pipeline:
  - uses: git-checkout
    with:
      repository: https://github.com/flutter/flutter.git
      tag: ${{package.version}}
      destination: flutter

  - runs: |
      # Bootstrap Dart SDK
      flutter/bin/flutter --version

      # Configure for web-only
      flutter/bin/flutter config --enable-web \
        --no-enable-android --no-enable-ios \
        --no-enable-linux-desktop --no-enable-macos-desktop \
        --no-enable-windows-desktop

      # Precache web artifacts
      flutter/bin/flutter precache --web \
        --no-android --no-ios --no-linux \
        --no-macos --no-windows --no-fuchsia --no-universal

      # Install to package destination
      mkdir -p ${{targets.destdir}}/opt
      mv flutter ${{targets.destdir}}/opt/flutter

      # Mark git safe directory
      git config --global --add safe.directory /opt/flutter      

Implementation Phases

Phase 1: Proof of Concept (web variant only)

  1. Install melange and apko locally
  2. Write flutter-sdk-web.melange.yaml to package Flutter SDK
  3. Build the APK: melange build flutter-sdk-web.melange.yaml
  4. Write apko.web.yaml to compose the final image
  5. Build the image: apko build apko.web.yaml flutter-sdk-web:test flutter-sdk-web.tar
  6. Load and test: docker load < flutter-sdk-web.tar
  7. Verify: docker run --rm flutter-sdk-web:test flutter doctor -v
  8. Compare image size vs current debian:bookworm-slim approach

Phase 2: CI Pipeline

  1. Add melange + apko build steps to publish.yaml
  2. Multi-stage: melange builds APK → apko composes image → push to registry
  3. Scout CVE scan on the final image
  4. SBOM generation (apko generates SBOMs natively)

Phase 3: Android + Linux Desktop Variants

  1. Write melange packages for Android SDK components
  2. Write apko YAML for Android variant (add JDK from Wolfi)
  3. Write apko YAML for Linux variant (add GTK3 from Wolfi)
  4. Test each variant with real Flutter project builds

Phase 4: Automated Updates

  1. Daily update-check detects new Flutter stable release
  2. Triggers melange rebuild of Flutter SDK package
  3. apko recomposes image with latest Wolfi packages (picks up CVE fixes)
  4. Push new images to registry

Expected Image Sizes

Variant Current (debian:bookworm-slim) Target (Wolfi/apko)
Web ~1.8 GB ~1.2-1.4 GB
Android ~3.5 GB ~2.5-3.0 GB
Linux ~2.2 GB ~1.5-1.8 GB

Note: Flutter SDK itself is ~1+ GB regardless of base. The savings come from the base OS layer (74 MB debian-slim → ~14 MB Wolfi base) and elimination of build-time packages.

File Structure (Target)

docker-flutter-sdk/
├── melange/
│   ├── flutter-sdk-web.melange.yaml
│   ├── flutter-sdk-android.melange.yaml
│   └── flutter-sdk-linux.melange.yaml
├── apko/
│   ├── web.apko.yaml
│   ├── android.apko.yaml
│   └── linux.apko.yaml
├── Dockerfile                    # Fallback: current debian approach (web)
├── Dockerfile.android            # Fallback: current debian approach (android)
├── Dockerfile.linux              # Fallback: current debian approach (linux)
├── .gitea/
│   └── workflows/
│       ├── publish.yaml          # Build with melange+apko, push to registry
│       ├── publish-dockerfile.yaml  # Fallback Dockerfile builds
│       ├── scout.yaml
│       └── update-check.yaml
└── PLAN.md

Risks and Mitigations

Risk Mitigation
GTK3 dev libs not in Wolfi Fall back to Dockerfile.linux with debian-slim for that variant
Flutter engine source build is complex Start with packaging prebuilt SDK, graduate to source build
melange/apko learning curve Well-documented by Chainguard, active community
Wolfi package availability changes Pin package versions, maintain fallback Dockerfiles
Build times for source compilation Cache melange build artifacts, only rebuild on new Flutter release

Dependencies

  • melange CLI: go install chainguard.dev/melange@latest
  • apko CLI: go install chainguard.dev/apko@latest
  • Docker (for testing)
  • Signing key pair (for APK package signing)

References