Skip to content

Commit 9c3ec7b

Browse files
luisleo526claude
andcommitted
build(docker): halve the runtime image — 1.12GB -> 520MB
- pineforge-codegen target-installed in the builder stage and COPY'd across (PYTHONPATH): the runtime carries no pip and no ca-certificates and never touches the network - purge /usr/share/{doc,man,locale,info} after apt - stop COPYing tests/ into the build context (BUILD_TESTS=OFF) - run as non-root (uid 10001); entrypoint already works out of mktemp Verified: full strategy.pine -> transpile -> compile -> backtest smoke test passes in the slim image as non-root. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 32198f9 commit 9c3ec7b

1 file changed

Lines changed: 18 additions & 11 deletions

File tree

docker/Dockerfile

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2727
ca-certificates \
2828
git \
2929
libeigen3-dev \
30+
python3-pip \
3031
&& rm -rf /var/lib/apt/lists/*
3132

33+
# Stage the pure-Python transpiler here so the runtime never needs pip or
34+
# network: target-install gives a plain directory tree to COPY across.
35+
RUN pip3 install --break-system-packages --no-cache-dir --target /opt/codegen pineforge-codegen
36+
3237
WORKDIR /src
3338
# VERSION file is the version source-of-truth inside the build context;
3439
# release.yml writes the bumped value before `docker build` so the
@@ -38,7 +43,6 @@ COPY CMakeLists.txt ./
3843
COPY cmake ./cmake
3944
COPY include ./include
4045
COPY src ./src
41-
COPY tests ./tests
4246

4347
RUN cmake -B build \
4448
-DCMAKE_BUILD_TYPE=Release \
@@ -66,24 +70,22 @@ LABEL org.opencontainers.image.title="pineforge" \
6670
org.opencontainers.image.licenses="Apache-2.0"
6771

6872
# g++ + Eigen to compile the generated TU; python3 for the JSON harness and
69-
# the bundled PineScript->C++ transpiler (pineforge-codegen, source-available
70-
# on PyPI). With codegen baked in, the container accepts strategy.pine directly
71-
# and transpiles locally — no hosted API, no API key, source never leaves the
72-
# box. (bookworm python3 ships no pip and is PEP-668 externally-managed, hence
73-
# python3-pip + --break-system-packages. codegen is pure-Python, zero deps.)
73+
# the bundled PineScript->C++ transpiler (pineforge-codegen, target-installed
74+
# in the builder stage and COPY'd in — the runtime carries no pip, no
75+
# ca-certificates, and never touches the network). With codegen baked in, the
76+
# container accepts strategy.pine directly and transpiles locally — no hosted
77+
# API, no API key, source never leaves the box.
7478
RUN apt-get update && apt-get install -y --no-install-recommends \
7579
g++ \
7680
libeigen3-dev \
7781
python3 \
78-
python3-pip \
79-
ca-certificates \
80-
&& pip3 install --break-system-packages --no-cache-dir pineforge-codegen \
81-
&& rm -rf /var/lib/apt/lists/*
82+
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man /usr/share/locale /usr/share/info
8283

8384
# Bundle the prebuilt static library, the public headers (curated +
8485
# generated version.h), and the JSON harness. Users only mount their
8586
# own code.
8687
RUN mkdir -p /opt/pineforge/lib /opt/pineforge/include /opt/pineforge/bin
88+
COPY --from=builder /opt/codegen /opt/pineforge/pycodegen
8789
COPY --from=builder /src/build/lib/libpineforge.a /opt/pineforge/lib/
8890
COPY --from=builder /src/include/pineforge /opt/pineforge/include/pineforge
8991

@@ -93,6 +95,11 @@ RUN chmod +x /opt/pineforge/bin/entrypoint.sh /opt/pineforge/bin/run_json.py
9395

9496
ENV PINEFORGE_PREFIX=/opt/pineforge \
9597
PINEFORGE_VERSION=${PINEFORGE_VERSION} \
96-
PINEFORGE_GIT_SHA=${PINEFORGE_GIT_SHA}
98+
PINEFORGE_GIT_SHA=${PINEFORGE_GIT_SHA} \
99+
PYTHONPATH=/opt/pineforge/pycodegen
100+
101+
# Drop root: the entrypoint compiles and runs everything under mktemp dirs.
102+
RUN useradd -r -u 10001 -s /usr/sbin/nologin pineforge
103+
USER pineforge
97104

98105
ENTRYPOINT ["/opt/pineforge/bin/entrypoint.sh"]

0 commit comments

Comments
 (0)