|  | 
| 1 |  | -FROM pytorch/pytorch:2.7.0-cuda12.8-cudnn9-runtime@sha256:7db0e1bf4b1ac274ea09cf6358ab516f8a5c7d3d0e02311bed445f7e236a5d80 | 
|  | 1 | +### | 
|  | 2 | +### docker build --ssh default=/path/to/private.key -f Dockerfile . | 
| 2 | 3 | 
 | 
| 3 |  | -RUN apt update | 
| 4 |  | -RUN apt install -y libpq-dev ffmpeg libsm6 libxext6 git wget | 
|  | 4 | +ARG BASE=ubuntu:22.04 | 
|  | 5 | +ARG BASE_PYTORCH=pytorch/pytorch:2.7.0-cuda12.8-cudnn9-runtime@sha256:7db0e1bf4b1ac274ea09cf6358ab516f8a5c7d3d0e02311bed445f7e236a5d80 | 
|  | 6 | +ARG PLATFORM=linux/amd64 | 
| 5 | 7 | 
 | 
| 6 |  | -# Install Go (used for Satlas smooth_point_labels_viterbi.go). | 
| 7 |  | -RUN wget https://go.dev/dl/go1.22.12.linux-amd64.tar.gz | 
| 8 |  | -RUN rm -rf /usr/local/go && tar -C /usr/local -xzf go1.22.12.linux-amd64.tar.gz | 
| 9 |  | -ENV PATH="${PATH}:/usr/local/go/bin" | 
|  | 8 | +FROM --platform=${PLATFORM} ${BASE} AS tippecanoe | 
| 10 | 9 | 
 | 
| 11 |  | -# Install tippecanoe (used by forest loss driver). | 
| 12 |  | -RUN apt install -y build-essential libsqlite3-dev zlib1g-dev | 
| 13 |  | -RUN git clone https://github.com/mapbox/tippecanoe /opt/tippecanoe | 
| 14 |  | -WORKDIR /opt/tippecanoe | 
|  | 10 | +RUN apt-get update && apt-get install -y --no-install-recommends build-essential ca-certificates curl libsqlite3-dev zlib1g-dev | 
|  | 11 | + | 
|  | 12 | +RUN mkdir -p /tmp/tippecanoe && curl -L https://github.com/mapbox/tippecanoe/archive/refs/tags/1.36.0.tar.gz | tar -xz --strip 1 -C /tmp/tippecanoe | 
|  | 13 | +WORKDIR /tmp/tippecanoe | 
| 15 | 14 | RUN make -j | 
| 16 |  | -RUN make install | 
|  | 15 | +RUN PREFIX=/opt/tippecanoe make install | 
|  | 16 | + | 
|  | 17 | +# To use this: | 
|  | 18 | +#  COPY --from=tippecanoe /opt/tippecanoe /opt/tippecanoe | 
|  | 19 | +#  ENV PATH="/opt/tippecanoe/bin:${PATH}" | 
|  | 20 | + | 
|  | 21 | +FROM --platform=${PLATFORM} ${BASE} AS golang | 
|  | 22 | + | 
|  | 23 | +## Build Satlas smooth_point_labels_viterbi.go (Requires golang) | 
|  | 24 | +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl | 
|  | 25 | +RUN curl -L https://go.dev/dl/go1.22.12.linux-amd64.tar.gz | tar -xz -C /usr/local | 
|  | 26 | +ENV PATH="/usr/local/go/bin:${PATH}" | 
|  | 27 | + | 
|  | 28 | +COPY rslp/satlas/scripts /tmp/smooth_point_labels_viterbi/ | 
|  | 29 | +WORKDIR /tmp/smooth_point_labels_viterbi/ | 
|  | 30 | +RUN go build smooth_point_labels_viterbi.go | 
|  | 31 | + | 
|  | 32 | +# To use this: | 
|  | 33 | +#  COPY --from=golang /tmp/smooth_point_labels_viterbi/smooth_point_labels_viterbi /usr/local/bin/smooth_point_labels_viterbi | 
|  | 34 | + | 
|  | 35 | +FROM --platform=${PLATFORM} pytorch/pytorch:2.7.0-cuda12.8-cudnn9-runtime@sha256:7db0e1bf4b1ac274ea09cf6358ab516f8a5c7d3d0e02311bed445f7e236a5d80 AS base | 
|  | 36 | + | 
|  | 37 | +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git openssh-client | 
|  | 38 | + | 
|  | 39 | +# Pin GitHub's host keys so SSH won't prompt | 
|  | 40 | +RUN mkdir -p -m 700 /root/.ssh && \ | 
|  | 41 | +    ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> /root/.ssh/known_hosts | 
|  | 42 | + | 
|  | 43 | +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv | 
|  | 44 | + | 
|  | 45 | +COPY . /opt/rslearn_projects/ | 
|  | 46 | + | 
|  | 47 | +# ============================================================================ | 
|  | 48 | +# SSH Multi-Key Configuration for GitHub Actions | 
|  | 49 | +# ============================================================================ | 
|  | 50 | +# This section handles SSH authentication for multiple private GitHub repositories | 
|  | 51 | +# when building in CI/CD environments that use separate deploy keys per repository. | 
|  | 52 | +# | 
|  | 53 | +# CONTEXT: | 
|  | 54 | +# - GitHub deploy keys are scoped to a single repository for security | 
|  | 55 | +# - We need to clone from multiple repos: rslearn, olmoearth_pretrain, olmoearth_run | 
|  | 56 | +# - Each repository has its own deploy key stored as a GitHub Actions secret | 
|  | 57 | +# | 
|  | 58 | +# THE PROBLEM: | 
|  | 59 | +# When SSH tries to connect to github.com with multiple keys in the agent: | 
|  | 60 | +#   1. SSH tries the first key | 
|  | 61 | +#   2. If it authenticates successfully, SSH stops trying other keys | 
|  | 62 | +#   3. If that key lacks access to a specific repo, GitHub returns "Repository not found" | 
|  | 63 | +#   4. The connection fails even though other keys in the agent might have access | 
|  | 64 | +# | 
|  | 65 | +# This happens because SSH authenticates at the HOST level (github.com), not the | 
|  | 66 | +# repository level. Once any key authenticates with github.com, SSH considers the | 
|  | 67 | +# connection successful and doesn't try other keys. | 
|  | 68 | +# | 
|  | 69 | +# THE SOLUTION: | 
|  | 70 | +# We use SSH host aliases to make SSH think each repository is on a different host: | 
|  | 71 | +#   - git@github-olmoearth-pretrain:allenai/olmoearth_pretrain.git | 
|  | 72 | +#   - git@github-olmoearth-run:allenai/olmoearth_run.git | 
|  | 73 | +# | 
|  | 74 | +# Each alias points to github.com but specifies which SSH key to use via IdentityFile. | 
|  | 75 | +# With IdentitiesOnly=yes, SSH only tries the specified key for that alias. | 
|  | 76 | +# | 
|  | 77 | +# IMPLEMENTATION: | 
|  | 78 | +# The GitHub Actions workflow writes deploy keys to .docker-ssh/ and sets | 
|  | 79 | +# USE_SSH_KEYS_FROM_BUILD=true. This code then: | 
|  | 80 | +#   1. Copies the key files to ~/.ssh/ | 
|  | 81 | +#   2. Creates SSH config with host aliases mapped to specific keys | 
|  | 82 | +#   3. Rewrites requirements*.txt files to use the host aliases | 
|  | 83 | +# | 
|  | 84 | +# LOCAL DEVELOPMENT: | 
|  | 85 | +# Local developers typically have a single SSH key with access to all repositories, | 
|  | 86 | +# so this complexity is unnecessary. When USE_SSH_KEYS_FROM_BUILD=false (default), | 
|  | 87 | +# this entire setup is skipped and standard SSH agent forwarding is used. | 
|  | 88 | + | 
|  | 89 | +ARG USE_SSH_KEYS_FROM_BUILD=false | 
|  | 90 | +RUN if [ "$USE_SSH_KEYS_FROM_BUILD" = "true" ] && [ -d /opt/rslearn_projects/.docker-ssh ]; then \ | 
|  | 91 | +      echo "Setting up SSH keys from build context..." && \ | 
|  | 92 | +      cp /opt/rslearn_projects/.docker-ssh/*_key /root/.ssh/ && \ | 
|  | 93 | +      cp /opt/rslearn_projects/.docker-ssh/config /root/.ssh/config && \ | 
|  | 94 | +      chmod 600 /root/.ssh/*_key /root/.ssh/config && \ | 
|  | 95 | +      cp /opt/rslearn_projects/.docker-ssh/requirements-olmoearth_pretrain.txt /opt/rslearn_projects/requirements-olmoearth_pretrain.txt && \ | 
|  | 96 | +      cp /opt/rslearn_projects/.docker-ssh/requirements-olmoearth_run.txt /opt/rslearn_projects/requirements-olmoearth_run.txt && \ | 
|  | 97 | +      echo "SSH multi-key setup complete."; \ | 
|  | 98 | +    else \ | 
|  | 99 | +      echo "Using default SSH configuration (single key or SSH agent)."; \ | 
|  | 100 | +    fi | 
|  | 101 | + | 
|  | 102 | +RUN --mount=type=ssh \ | 
|  | 103 | +    --mount=type=cache,target=/root/.cache/uv \ | 
|  | 104 | +    uv pip install --system /opt/rslearn_projects[olmoearth_run,olmoearth_pretrain] | 
| 17 | 105 | 
 | 
|  | 106 | +FROM base AS full | 
|  | 107 | + | 
|  | 108 | +COPY --from=tippecanoe /opt/tippecanoe /opt/tippecanoe | 
|  | 109 | +COPY --from=golang /tmp/smooth_point_labels_viterbi/smooth_point_labels_viterbi /usr/local/bin/smooth_point_labels_viterbi | 
| 18 | 110 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv | 
| 19 | 111 | 
 | 
| 20 |  | -# Install rslearn. | 
| 21 |  | -# We use git clone and then git checkout instead of git clone -b so that the user could | 
| 22 |  | -# specify a commit name or branch instead of only accepting a branch. | 
|  | 112 | +ENV PATH="/opt/tippecanoe/bin:${PATH}" | 
|  | 113 | + | 
|  | 114 | +## Install rslearn. | 
|  | 115 | +## We use git clone and then git checkout instead of git clone -b so that the user could | 
|  | 116 | +## specify a commit name or branch instead of only accepting a branch. | 
| 23 | 117 | ARG RSLEARN_BRANCH=master | 
| 24 |  | -RUN git clone https://github.com/allenai/rslearn.git /opt/rslearn | 
|  | 118 | +RUN --mount=type=ssh git clone git@github.com:allenai/rslearn.git /opt/rslearn | 
| 25 | 119 | WORKDIR /opt/rslearn | 
| 26 | 120 | RUN git checkout $RSLEARN_BRANCH | 
| 27 |  | -RUN uv pip install --system /opt/rslearn[extra] | 
|  | 121 | +RUN --mount=type=cache,target=/root/.cache/uv \ | 
|  | 122 | +    uv pip install --system /opt/rslearn[extra] | 
| 28 | 123 | 
 | 
| 29 |  | -# Install rslearn_projects. | 
| 30 | 124 | COPY . /opt/rslearn_projects/ | 
| 31 |  | -RUN uv pip install --system /opt/rslearn_projects[dev,extra] | 
| 32 |  | - | 
| 33 |  | -# Build Satlas smooth_point_labels_viterbi.go program. | 
| 34 |  | -WORKDIR /opt/rslearn_projects/rslp/satlas/scripts | 
| 35 |  | -RUN go build smooth_point_labels_viterbi.go | 
| 36 |  | - | 
| 37 |  | -WORKDIR /opt/rslearn_projects | 
|  | 125 | +RUN --mount=type=ssh \ | 
|  | 126 | +    --mount=type=cache,target=/root/.cache/uv \ | 
|  | 127 | +    uv pip install --system /opt/rslearn_projects[dev,extra] | 
0 commit comments