Sign inSign up

alihaidar199527/flutter-devcontainer

By alihaidar199527

•Updated about 1 month ago

Image
0

823

alihaidar199527/flutter-devcontainer repository overview

⁠flutter-devcontainer

Blank-canvas base Docker image for VS Code Dev Containers. One image, shared across all your Flutter projects.

Flutter (stable) · Dart · Android SDK 36 · Java 21 (Temurin) · Node.js 24 LTS · pnpm (Corepack) · Firebase CLI · FlutterFire CLI · Gradle 9.7.1 · GitHub CLI · Starship

Docker Build Docker Pulls Image Size License: MIT

docker pull alihaidar199527/flutter-devcontainer:latest

⁠Overview

Every Flutter project needs the same developer tooling: Flutter SDK, Android SDK, Dart, Java, Gradle, Firebase, and a productive terminal. Configuring all of this from scratch on every machine — or worse, on every project — wastes time and produces inconsistent environments.

This repository solves that problem with a single shared base image. Push a change here and all your Flutter projects get the upgrade on the next docker pull — without touching any project code.

This repo has one job: build and publish the base development Docker image to Docker Hub.

It contains no Flutter project files, no pubspec.yaml, no application code, and no app-level CI. Flutter packages, app configuration, and deployment workflows all belong in the project repositories that consume this image.


⁠Architecture

This image is one half of a two-repo system.

RepoResponsibility
flutter-devcontainer ← you are hereBuild and publish the base dev image
flutter-templateGitHub Template — the starting point for every new Flutter project

When you open a Flutter project that uses this image, the container starts via Docker Compose with your project folder mounted at /workspace and your Git identity and SSH keys available for pushing to GitHub.


⁠What's Inside

⁠Runtime & Language
ToolVersionPurpose
Flutter SDKstable channelFlutter framework + Dart SDK
Dart SDKbundled with FlutterLanguage runtime (included in Flutter)
Java (Eclipse Temurin)21Required by Android build toolchain and Gradle
Node.js24 LTS (bookworm-slim)Required by Firebase CLI and FlutterFire CLI
pnpm11.22.0 (via Corepack)Package manager for repo-level tooling (Husky, commitlint) in consuming projects
⁠Android
ToolVersionPurpose
Android SDKAPI 36Latest Android platform
Android Build Tools36.0.0APK/AAB compilation
Android Platform Toolslatestadb, fastboot
Android Cmdline Toolslatest (14742923)sdkmanager, avdmanager
Gradle9.7.1Android build system — pre-cached in image
⁠Web & Desktop
ToolVersionPurpose
Google Chromestable (amd64)flutter run -d web, flutter test --platform chrome
Chromiumlatest (arm64)Web target on Apple Silicon
Linux desktop deps—clang, cmake, ninja, GTK3 — for flutter build linux
⁠Developer Tools
ToolVersionPurpose
Firebase CLI15.27.0Firebase project management and deployment
FlutterFire CLIlatestConfigure Firebase in Flutter projects
pnpm11.22.0Fast, disk-efficient package manager, activated via Corepack at build time
GitHub CLIlatestgh pr create, gh run watch, gh auth login
openssh-client—git push via SSH from inside the container
StarshiplatestTerminal prompt — git branch, Flutter version, status
Utilities—curl, git, jq, nano, htop, tree, procps
⁠What is NOT inside

These are intentionally absent. Add them to your pubspec.yaml per project:

provider / riverpod / bloc    →  flutter pub add provider
go_router                     →  flutter pub add go_router
dio / http                    →  flutter pub add dio
hive / isar / drift           →  flutter pub add hive
firebase_core                 →  flutter pub add firebase_core
any_other_package             →  flutter pub add <package>

⁠Platform Support

PlatformBuild targetStatus
Android APK / AABflutter build apk, flutter build appbundle✅ Full support
Webflutter build web, flutter run -d web✅ Full support
Linux Desktopflutter build linux✅ Full support
iOSflutter build ipa❌ Requires macOS + Xcode — impossible in Linux containers
macOS Desktopflutter build macos❌ Requires macOS
Windows Desktopflutter build windows❌ Requires Windows host
⁠iOS Note

Apple's build toolchain (Xcode, codesign, xcodebuild) only runs on macOS by Apple's own enforcement — this is not a tooling gap. iOS is handled at the CI layer:

  • CI: Use a macos-latest GitHub Actions runner in your flutter-template CI workflow to build, sign, and upload to TestFlight automatically on every push to main.
  • When you get a Mac: The same devcontainer works identically. For iOS, also install Xcode on the Mac host — flutter doctor detects it automatically. No image changes needed.
  • No Mac at all: Rent one for $1–5/hour on Codemagic⁠ or MacInCloud⁠ for the one-time certificate and provisioning profile setup.

⁠Repository Structure

flutter-devcontainer/
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml                ← Structured bug report form
│   │   └── config.yml                    ← Disables blank issues, links to flutter-template
│   ├── workflows/
│   │   ├── docker.yml                    ← Builds + pushes image on push/PR to main/develop
│   │   ├── dockerhub-description.yml     ← Syncs README.md to Docker Hub on push to main
│   │   └── labels.yml                    ← Syncs labels.yml to GitHub labels
│   ├── CODEOWNERS                        ← Auto-requests reviewer on every PR
│   ├── PULL_REQUEST_TEMPLATE.md          ← PR checklist (versions, platforms, scope)
│   ├── dependabot.yml                    ← Weekly auto-updates for Actions + Docker base image → develop
│   └── labels.yml                        ← Label definitions — name, color, description
├── docker/
│   └── Dockerfile.dev                    ← The image recipe ← MAIN FILE
├── scripts/
│   └── shell_setup.sh                    ← Installs Starship + bakes aliases into the image
├── .dockerignore                         ← Excludes unnecessary files from the build context
├── .editorconfig                         ← Consistent indentation/line endings across editors
├── .gitignore                            ← Ensures secrets are never committed
├── LICENSE                               ← MIT — free to use, your name stays on it
├── README.md                             ← This file — also synced to Docker Hub
├── SECURITY.md                           ← Vulnerability reporting policy
└── repomix.config.json                   ← Config for generating the AI-readable repo snapshot

⁠GitHub Automation

⁠Workflow trigger summary
FileTriggerWhat happens
workflows/docker.ymlPush to main (docker/, scripts/ changed)Builds + pushes :latest + :sha-xxx to Docker Hub
workflows/docker.ymlPR targeting main or develop (same path filter)Builds only — validates Dockerfile, never pushes
workflows/docker.ymlManual dispatchBuilds + pushes, with force-rebuild and push toggle
workflows/dockerhub-description.ymlPush to main (README.md changed)Updates Docker Hub description
workflows/dockerhub-description.ymlPR targeting main or develop (README.md changed)Runs but skips update until merged
workflows/dockerhub-description.ymlManual dispatchForces immediate Docker Hub sync
workflows/labels.ymlPush to main (.github/labels.yml changed)Syncs all labels to GitHub
workflows/labels.ymlManual dispatchBootstrap all labels in one go
dependabot.ymlEvery Monday 09:00 UTCScans Actions + Docker base image, opens PRs against develop
⁠workflows/docker.yml

Builds the multi-platform Docker image (linux/amd64 + linux/arm64) and pushes it to Docker Hub. Path-filtered so a README change never triggers an unnecessary rebuild. PR builds — including Dependabot PRs opened against develop — validate the Dockerfile without pushing; only merged pushes to main publish to Docker Hub. Generates SBOM and provenance attestations on every build.

Note: On pull_request events (including Dependabot PRs), GitHub withholds repository secrets by design. The workflow handles this correctly — login and push are both skipped on PRs, so the build validates the Dockerfile without needing credentials. The IMAGE_NAME is hardcoded (not from a secret) so the tag is always valid.

⁠workflows/dockerhub-description.yml

Syncs README.md to the Docker Hub repository description page on every README.md change merged to main. PRs trigger the workflow for the GitHub check but skip the actual Docker Hub update until merged.

⁠workflows/labels.yml

Keeps GitHub repository labels in sync with .github/labels.yml. Labels are version-controlled — add or rename a label in the file, push, and GitHub reflects the change automatically. Run manually to bootstrap on a new repo.

⁠dependabot.yml

Automatically monitors two ecosystems and opens grouped PRs when updates are found:

  • github-actions — all action versions across every workflow file, grouped into one weekly PR
  • docker — every pinned dependency in the docker ecosystem except Node, which is intentionally frozen

All Dependabot PRs target develop, not main — they land on the integration branch first and are promoted to main (which triggers the publish workflow) once verified. Node.js is intentionally frozen at version 24 (all update types ignored). Firebase CLI, Gradle, and pnpm are pinned via ENV in Dockerfile.dev and updated manually — see Upgrading Firebase CLI⁠, Upgrading Gradle⁠, and Upgrading pnpm⁠ below.

Both ecosystems run every Monday at 09:00 UTC.


⁠How the Build Works

Push to main (Dockerfile or scripts changed)
  → GitHub Actions detects the change
  → Builds linux/amd64 + linux/arm64 in parallel using layer cache
  → Pushes :latest and :sha-<commit> to Docker Hub
  → Syncs README to Docker Hub description
  → Job summary written to Actions log

PR targeting main or develop (Dockerfile or scripts changed)
  → GitHub Actions detects the change
  → Builds linux/amd64 + linux/arm64 to validate
  → Does NOT push — PR check goes green or red
  → Merge when green

The first build takes ~15–20 minutes (Flutter SDK + Android SDK are large). Subsequent builds complete in 3–5 minutes thanks to GitHub Actions layer caching. Each job carries an explicit timeout-minutes so a stuck runner fails fast instead of hanging.


⁠Platforms

PlatformArchitecture
Windows · Linux · GCPlinux/amd64
Apple Silicon Maclinux/arm64

Docker pulls the correct platform automatically.


⁠Tags

TagPublished when
latestEvery push to main
sha-xxxxxxxEvery build — pin to this for rollback

⁠Shell Aliases

All aliases are defined in scripts/shell_setup.sh and baked into the image.

⁠Flutter
AliasExpands toNotes
flflutterShort flutter prefix
fgetflutter pub getInstall all dependencies
faddflutter pub addAdd a package
frmflutter pub removeRemove a package
fupgradeflutter pub upgradeUpgrade packages
foutdatedflutter pub outdatedCheck for outdated packages
frunflutter runRun on connected device
frunwflutter run -d web-server ...Run web server (Docker-friendly, port 8080)
fruncflutter run -d chromeRun in Chrome
fbuildflutter buildBuild prefix
fbuildapkflutter build apk --releaseRelease APK
fbuildaabflutter build appbundle --releaseRelease App Bundle
fbuildwebflutter build web --releaseRelease web build
fbuildlinuxflutter build linux --releaseRelease Linux desktop
ftestflutter testRun tests
ftestcflutter test --coverageRun tests with coverage
fanalyzeflutter analyzeStatic analysis
fformatdart format .Format all Dart files
fformatcheckdart format --set-exit-if-changed .Format check (CI mode)
fdoctorflutter doctor -vVerbose environment check
fcleanflutter cleanClean build cache
fcreateflutter createCreate new project
fdevicesflutter devicesList connected devices
fupgrade_sdkflutter upgradeUpgrade Flutter SDK
⁠Dart
AliasExpands to
dpubdart pub
dgetdart pub get
dauditdart pub audit
dformatdart format .
danalyzedart analyze
dtestdart test
drundart run
dcompiledart compile
dglobaldart pub global
⁠Firebase
AliasExpands to
fbloginfirebase login
fbdeployfirebase deploy
fbservefirebase serve
fbusefirebase use
fblistfirebase projects:list
ffinitflutterfire configure
⁠Android / ADB
AliasExpands to
adbdevicesadb devices
adblogadb logcat
adbinstalladb install
adbrestartadb kill-server && adb start-server
⁠Git
AliasExpands to
gsgit status
gagit add
gcgit commit -m
gpgit push
gplgit pull
glgit log --oneline --graph --decorate
gcogit checkout
gbgit branch
gdgit diff

⁠Updating the Image

⁠Upgrading Flutter

Flutter is installed via git clone -b stable, so it always tracks the latest stable release at build time. To get a new Flutter version, trigger a manual rebuild from the Actions tab or push any change to docker/ or scripts/.

⁠Upgrading Node.js

Node.js is intentionally frozen at 24 LTS via ARG NODE_VERSION=24 in docker/Dockerfile.dev. Dependabot is configured to ignore all Node update types so it will not open PRs for Node upgrades. To upgrade Node, update the ARG manually:

ARG NODE_VERSION=26

Verify the tag exists at hub.docker.com/_/node/tags⁠ first. Commit, push to a branch off develop, open a PR. The PR build validates the new version. Merge to develop, then promote to main when ready to publish.

⁠Upgrading Firebase CLI

Firebase CLI is pinned via ENV FIREBASE_TOOLS_VERSION in docker/Dockerfile.dev and is updated manually — Dependabot does not track it. To upgrade:

  1. Check the latest version at npmjs.com/package/firebase-tools⁠
  2. Update the env in docker/Dockerfile.dev:
ENV GRADLE_VERSION=9.7.1 \
    FIREBASE_TOOLS_VERSION=15.27.0 \
  1. Open a PR against develop, let the build validate, merge.
⁠Upgrading Gradle

Update ENV GRADLE_VERSION in docker/Dockerfile.dev:

ENV GRADLE_VERSION=9.8.0 \

Check the latest stable release at gradle.org/releases⁠. Do not use release candidates.

⁠Upgrading pnpm

pnpm is activated via Corepack and pinned via ENV PNPM_VERSION in docker/Dockerfile.dev, updated manually — Dependabot does not track it (Corepack-managed tools aren't detected by the docker ecosystem scanner). To upgrade:

  1. Check the latest version at npmjs.com/package/pnpm⁠
  2. Update the env in docker/Dockerfile.dev:
ENV PNPM_VERSION=11.22.0
  1. Open a PR against develop, let the build validate corepack prepare pnpm@${PNPM_VERSION} --activate succeeds, merge.

Corepack is enabled and pnpm is activated as root, before the image switches to the non-root developer user — /usr/local/bin (where the Corepack shim lives) is root-owned, so this step cannot run later as developer without sudo.

⁠Upgrading Android SDK

Update the sdkmanager call in docker/Dockerfile.dev:

&& sdkmanager \
   "platform-tools" \
   "platforms;android-37" \
   "build-tools;37.0.0" \
   "cmdline-tools;latest"

Check new API levels at developer.android.com/tools/releases/platforms⁠.

⁠Upgrading Android Cmdline Tools

The cmdline-tools zip URL contains a build number (14742923). When Google releases a new version, update the URL in docker/Dockerfile.dev:

https://dl.google.com/android/repository/commandlinetools-linux-NEW_BUILD_latest.zip

Find the latest build number on the Android Studio download page⁠.

⁠Adding a system package
RUN apt-get update && apt-get install -y --no-install-recommends \
    your-new-tool \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

⁠Troubleshooting

⁠Build fails — authentication error

Symptom: denied: requested access to the resource is denied

  1. Go to Settings → Secrets and variables → Actions
  2. Confirm both DOCKERHUB_USERNAME and DOCKERHUB_TOKEN are present
  3. Confirm the token has Read, Write & Delete scope — Read-only tokens cannot push
  4. If expired: Docker Hub → Account Settings → Personal access tokens → delete → create new → update secret
  5. Re-run from the Actions tab
⁠Build fails — invalid image tag on pull_request

Symptom: ERROR: invalid tag "/flutter-devcontainer:sha-xxx": invalid reference format

Cause: On pull_request events, GitHub withholds all repository secrets. If the image name were built from the DOCKERHUB_USERNAME secret it would resolve to an empty string.

Fix: IMAGE_NAME in docker.yml is hardcoded directly — the Docker Hub username is not sensitive:

env:
  IMAGE_NAME: alihaidar199527/flutter-devcontainer
⁠flutter doctor shows Android licenses not accepted

Inside the container, run:

yes | flutter doctor --android-licenses

This is already handled at image build time but may be needed after an sdkmanager update.

⁠pnpm: command not found in a project's postCreateCommand

This means the image was built before Corepack/pnpm activation was added, or the container is running against a stale cached image. Pull the latest image (docker pull alihaidar199527/flutter-devcontainer:latest) and rebuild the dev container. If it's still missing, run corepack --version inside the container to confirm Corepack itself is present before filing an issue.

⁠ADB cannot find device (connecting to host emulator)

Run the Android emulator on your host machine, then inside the container:

adb connect host.docker.internal:5555
adbdevices

If shown as unauthorized, accept the prompt on the emulator screen. If shown as offline:

adbrestart
adb connect host.docker.internal:5555

On Windows, ensure your firewall allows inbound TCP on ports 5037 and 5555 from the Docker network.

⁠Chrome not found for web builds

Chrome is only installed on linux/amd64. On linux/arm64 (Apple Silicon), flutter run -d web uses the web server target instead:

frunw   # flutter run -d web-server --web-port 8080 --web-hostname 0.0.0.0

Then open http://localhost:8080 on your host browser.

⁠git push fails — permission denied (publickey)
ssh-add -l          # check loaded keys
ssh -T [email protected]   # verify auth

On Windows, ensure the SSH agent is running and your key is loaded before opening VS Code:

sc config ssh-agent start= auto
net start ssh-agent
ssh-add "$env:USERPROFILE\.ssh\id_ed25519"
⁠Out of disk space during build

Flutter SDK + Android SDK together are ~4–5 GB. Ensure Docker Desktop has at least 20 GB of disk image space allocated: Docker Desktop → Settings → Resources → Disk image size


⁠Contributing

  • Open PRs against develop, not main — main is the publish branch and merges from it trigger a live Docker Hub push.
  • Follow the checklist in .github/PULL_REQUEST_TEMPLATE.md⁠.
  • Found a vulnerability? See SECURITY.md⁠ — do not open a public issue.

RepoPurpose
flutter-devcontainer⁠← You are here — builds the Docker image
flutter-template⁠Flutter project template — pulls this image for development

Flutter stable · Dart · Android API 36 · Java 21 Temurin · Node.js 24 LTS · pnpm 11.22.0 · Gradle 9.7.1 · Debian 12 Bookworm · 2026

Tag summary

Content type

Image

Digest

sha256:70b33d2d9…

Size

2.6 GB

Last updated

about 1 month ago

docker pull alihaidar199527/flutter-devcontainer