blob: dfb579b779a59fbbcc7acdea53bc7a8b5d12e201 [file]
# Copyright 2022 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This is a highly opinionated docker container aimed at getting a developer
# up and running with antigravity in a sandbox, instantly.
# Build:
# x86: docker build -t flutter_docker .
# Apple Silicon: podman build --platform linux/amd64 -t flutter_docker .
# Different version of fluttr: podman build --platform linux/amd64 --build-arg FLUTTER_VERSION=3.45.0 -t flutter_docker:3.45.0 .
#
# Run:
# Apple Silicon: podman run --platform linux/amd64 -it -v "${PWD}:/app" -v "dart_tool_cache:/app/.dart_tool" -v "dart_build_cache:/app/build" -v "$USER/.gemini:/home/coder/.gemini" flutter_docker:latest
# x86: docker run -it -v ".:/app" -v 'dart_tool_cache:/app/.dart_tool' -v "dart_build_cache:/app/build" -v "$USER/.gemini:/home/coder/.gemini" flutter_docker:latest
#
# Doing something work worktrees - work in progress?
# 1. Make sure you have relative paths setup.
# git config --global worktree.useRelativePaths true
# git worktree repair
# 2. Run one of the commands above, but from the worktree folder.
#
# Versions:
# * latest: 3.44.2
# * previous: permissions on ~/.gemini to fix tool calling
# * previous: better handling of .dart_tool - see run commands above! flutter 3.44.1. allow my user to sudo
# * previous: fix tmux key bindings. add less and rsync
# * previous: `agyolo`!, -homebrew, +vim dart plugin, native yq/gh/jq, less RUN steps
# * previous: zsh, omyzsh, homebrew.
# * previous: multi-stage build for flutter tooling. byobu/tmux, git, jq.
# ==========================================
# STAGE 1: The Heavy Downloader - flutter and its tools are heavy
# ==========================================
FROM ubuntu:24.04 AS flutter-fetcher
# 1. Define the ARG with a fallback default version
ARG FLUTTER_VERSION="3.44.2"
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl ca-certificates xz-utils git unzip && \
rm -rf /var/lib/apt/lists/*
RUN useradd -m builder && \
mkdir -p /opt && \
chown builder:builder /opt
USER builder
WORKDIR /opt
# This layer caches permanently until you change the URL.
# It is completely immune to changes in your main image.
RUN curl -fsSL https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz | tar -xJ
# 2. Lock in configuration and force the massive SDK downloads
ENV PATH="/opt/flutter/bin:${PATH}"
RUN flutter config \
--enable-web \
--no-enable-linux-desktop \
--no-enable-macos-desktop \
--no-enable-windows-desktop \
--no-enable-android \
--no-enable-ios \
--no-enable-fuchsia && \
# Precache pulls down the engine binaries, Dart SDK, and web tools
flutter precache --web && \
flutter --version
# ==========================================
# STAGE 2: The OS - which should mostly have an OCI layer already.
# ==========================================
FROM ubuntu:24.04
# 1. Environment Variables (Rarely change, define early)
ENV TZ="America/Los_Angeles" \
DEBIAN_FRONTEND=noninteractive \
FLUTTER_ROOT="/opt/flutter" \
PATH="/opt/flutter/bin:/home/coder/.local/bin:${PATH}" \
LANG="en_US.UTF-8" \
LANGUAGE="en_US:en" \
LC_ALL="en_US.UTF-8" \
TERM="xterm-256color" \
COLORTERM="truecolor" \
SHELL="/usr/bin/zsh"
# 2. OS Dependencies (Heavy layer, cache as much as possible)
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates curl dnsutils dos2unix openssh-client unzip \
tmux byobu vim sudo xz-utils tzdata locales jq ripgrep \
fd-find fzf bat btop zsh build-essential procps file wget \
less rsync software-properties-common lrzsz; \
# Install trzsz via PPA
add-apt-repository ppa:trzsz/ppa -y; \
add-apt-repository ppa:git-core/ppa -y; \
apt-get update; \
apt-get install -y trzsz git; \
# install github
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg; \
chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg; \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null; \
apt-get update && apt-get install -y gh; \
# binary yq
wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64; \
chmod a+x /usr/local/bin/yq; \
locale-gen en_US.UTF-8; \
ln -s $(which fdfind) /usr/local/bin/fd; \
ln -s $(which batcat) /usr/local/bin/bat; \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone; \
rm -rf /var/lib/apt/lists/*; \
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# 3. User setup and directory creation
# Evict the default ubuntu user to free up UID/GID 1000
# Using -m automatically creates the home directory securely.
RUN (userdel -r ubuntu 2>/dev/null || true) && \
groupadd -g 1000 coder && \
useradd -u 1000 -g 1000 -m coder && \
mkdir -p /app /opt/flutter /home/linuxbrew/.linuxbrew && \
chown -R coder:coder /app /opt /home/linuxbrew
# 4. Import the FULLY HYDRATED Flutter SDK from Stage 1
# This takes about 1 second and skips all network traffic.
COPY --from=flutter-fetcher --chown=coder:coder /opt/flutter /opt/flutter
# Switch context to the non-root user for the remaining installations
USER coder
# or --disable-analytics if running as CICD
RUN flutter --enable-analytics && dart --enable-analytics
# 5. Install Oh My Zsh unattended so it doesn't halt the Docker build
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
# Set these after USER
ENV PATH="/home/coder/.pub-cache/bin:${PATH}"
# 6. User-specific CLI tools
RUN curl -fsSL https://antigravity.google/cli/install.sh | bash
# 7. User Configuration (Highly volatile, keep at the very bottom)
RUN mkdir -p /home/coder/.config/byobu && \
touch /home/coder/.config/byobu/.welcome-displayed && \
{ \
echo "unbind-key -n C-a"; \
echo "set -g prefix C-a"; \
echo "set -g prefix2 F12"; \
echo "bind a send-prefix"; \
echo "# Ensure tmux handles control modifiers correctly for xterm"; \
echo "set-window-option -g xterm-keys on"; \
echo "# Clear any existing bindings for these keys";\
echo "unbind-key -n C-Left";\
echo "unbind-key -n C-Right";\
echo "# Map Ctrl + Left/Right to switch bottom tabs (windows)";\
echo "bind-key -n C-Left select-window -t :-";\
echo "bind-key -n C-Right select-window -t :+";\
echo "set -g mouse on"; \
} > /home/coder/.config/byobu/keybindings.tmux && \
{ \
echo "set -g default-terminal \"tmux-256color\""; \
echo "set -ag terminal-overrides \",xterm-256color:RGB\""; \
echo "set -g default-shell /usr/bin/zsh"; \
echo "# Automatically fix named volume permissions on startup"; \
echo 'run-shell "sudo mkdir -p /app/.dart_tool && sudo chown -R coder:coder /app/.dart_tool"'; \
echo 'run-shell "sudo mkdir -p /app/build && sudo chown -R coder:coder /app/build"'; \
echo 'run-shell "sudo mkdir -p /home/coder/.gemini && sudo chown -R coder:coder /home/coder/.gemini"'; \
} > /home/coder/.config/byobu/profile.tmux && \
touch /home/coder/.zsh_history && \
{ \
echo ": 1000000000:0;dart pub global activate melos; melos pub-get"; \
echo ": 1000000000:0;flutter pub get"; \
echo ": 1000000000:0;flutter analyze ."; \
echo ": 1000000000:0;dart pub get"; \
echo ": 1000000000:0;dart format ."; \
echo ": 1000000000:0;dart analyze ."; \
} >> /home/coder/.zsh_history && \
touch /home/coder/.zshrc && \
{ \
echo 'alias agyolo="agy --dangerously-skip-permissions"'; \
} >> /home/coder/.zshrc
RUN mkdir -p /home/coder/.vim/pack/dart-lang/start && \
git clone https://github.com/dart-lang/dart-vim-plugin /home/coder/.vim/pack/dart-lang/start/dart-vim-plugin
RUN git config --global --add safe.directory /app && \
git config --global core.editor vim && \
git config --global pull.rebase true && \
git config --global worktree.useRelativePaths true
WORKDIR /app
ENTRYPOINT [ "/usr/bin/byobu" ]