Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions docker/Dockerfile.console
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,31 @@ RUN /usr/local/cargo/bin/flmadm install \
--skip-build \
--force

# Install Python 3.12 via uv to match runtime (ubuntu:24.04)
# Then pre-warm uv cache for flamepy dependencies in the builder
# This avoids network access during runtime container startup
RUN /usr/bin/uv python install 3.12 && \
UV_CACHE_DIR=/usr/local/flame/data/cache/uv \
UV_LINK_MODE=copy \
/usr/bin/uv run --python 3.12 \
--find-links /usr/local/flame/wheels \
--with pip \
--with flamepy \
python -c "import flamepy; print('flamepy cache warmed in builder')"

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y wget vim iputils-ping ssh curl python3 python3-pip && rm -rf /var/lib/apt/lists/*

# Copy the entire installation from builder (including uv in bin/)
# Copy the entire installation from builder (including uv in bin/ and pre-warmed cache)
COPY --from=builder /usr/local/flame /usr/local/flame

# Add flame binaries to PATH (includes uv)
ENV PATH="/usr/local/flame/bin:${PATH}"
ENV FLAME_HOME=/usr/local/flame

# Install flamepy and pytest for test client using uv from FLAME_HOME
RUN /usr/local/flame/bin/uv pip install --system --break-system-packages --no-cache /usr/local/flame/sdk/python pytest
# Use UV_LINK_MODE=copy for cross-filesystem compatibility
RUN UV_LINK_MODE=copy /usr/local/flame/bin/uv pip install --system --break-system-packages --no-cache /usr/local/flame/sdk/python pytest

CMD ["service", "ssh", "start", "-D"]
14 changes: 13 additions & 1 deletion docker/Dockerfile.fem
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,25 @@ RUN /usr/local/cargo/bin/flmadm install \
--skip-build \
--force

# Install Python 3.12 via uv to match runtime (ubuntu:24.04)
# Then pre-warm uv cache for flamepy dependencies in the builder
# This avoids network access during runtime container startup
RUN /usr/bin/uv python install 3.12 && \
UV_CACHE_DIR=/usr/local/flame/data/cache/uv \
UV_LINK_MODE=copy \
/usr/bin/uv run --python 3.12 \
--find-links /usr/local/flame/wheels \
--with pip \
--with flamepy \
python -c "import flamepy; print('flamepy cache warmed in builder')"

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y python3-pip git && rm -rf /var/lib/apt/lists/*

WORKDIR /usr/local/flame/work

# Copy the entire installation from builder (including uv in bin/)
# Copy the entire installation from builder (including uv in bin/ and pre-warmed cache)
COPY --from=builder /usr/local/flame /usr/local/flame

ENV FLAME_HOME=/usr/local/flame
Expand Down
9 changes: 7 additions & 2 deletions executor_manager/src/shims/host_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,14 @@ impl HostShim {
};

let work_dir = cur_dir.clone();
// Setup working directory and get environment overrides
// Setup working directory and get environment defaults
// Use entry().or_insert() so application-specific envs take precedence over defaults
// This allows applications like flmrun to specify UV_CACHE_DIR pointing to
// the pre-cached directory instead of using a per-instance empty cache
let wd_envs = Self::setup_working_directory(&work_dir)?;
envs.extend(wd_envs);
for (key, value) in wd_envs {
envs.entry(key).or_insert(value);
}

let log_out = OpenOptions::new()
.create(true)
Expand Down
45 changes: 40 additions & 5 deletions flmadm/src/managers/installation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,11 @@ impl InstallationManager {

let uv_cache_dir = paths.cache.join("uv");

// Install flamepy and dependencies to populate the cache
// Using --target to a temp directory avoids needing a venv
// Phase 1: Cache flamepy and all its dependencies (grpcio, protobuf, cloudpickle, etc.)
// Using --target to a temp directory to populate the cache without needing a venv
let cache_target = paths.work.join(".flamepy-cache-target");
fs::create_dir_all(&cache_target).context("Failed to create temporary directory for caching")?;
fs::create_dir_all(&cache_target)
.context("Failed to create temporary directory for caching")?;

let install_output = std::process::Command::new(&uv_path)
.arg("pip")
Expand All @@ -255,7 +256,7 @@ impl InstallationManager {
.arg("--find-links")
.arg(&paths.wheels)
.arg("flamepy")
.arg("pip") // Also cache pip as it's used by flmrun
.arg("pip") // Also cache pip as it's used by flmrun for user packages
.env("UV_CACHE_DIR", &uv_cache_dir)
.output()
.context("Failed to execute uv pip install")?;
Expand All @@ -271,7 +272,41 @@ impl InstallationManager {
stderr.lines().next().unwrap_or(&stderr)
);
} else {
println!(" ✓ Cached dependencies to: {}", uv_cache_dir.display());
println!(
" ✓ Cached flamepy and dependencies to: {}",
uv_cache_dir.display()
);
}

// Phase 2: Pre-warm uv's ephemeral environment cache by running the exact command
// that flmrun uses at startup. This ensures all packages are cached in the format
// that 'uv run --with' expects (which differs from 'uv pip install').
println!(" 🔄 Pre-warming uv run cache...");

// Create a simple Python script that just exits successfully
let run_output = std::process::Command::new(&uv_path)
.arg("run")
.arg("--find-links")
.arg(&paths.wheels)
.arg("--with")
.arg("pip")
.arg("--with")
.arg("flamepy")
.arg("python")
.arg("-c")
.arg("import sys; sys.exit(0)")
.env("UV_CACHE_DIR", &uv_cache_dir)
.output()
.context("Failed to execute uv run warmup")?;

if !run_output.status.success() {
let stderr = String::from_utf8_lossy(&run_output.stderr);
println!(
" ⚠️ Failed to pre-warm uv run cache (will warm at runtime): {}",
stderr.lines().next().unwrap_or(&stderr)
);
} else {
println!(" ✓ Pre-warmed uv run cache");
}

Ok(())
Expand Down
Loading