# syntax=docker/dockerfile:1

# {{ parent_stack }}.{{ layer_name }}'s base image, built from a Bun + TypeScript project
# (BUILD_CONTEXT in image.env) on a hardened Wolfi base. The build stage compiles the
# server and its dependencies into one executable (`bun build --compile`); the runtime
# keeps that executable and the C++ runtime it links, and nothing else: no Bun, so no
# package manager. Each environment's overlay (<env>/Dockerfile) builds FROM it. The
# source layer's own Operations lint, test and scan the source; this layer builds, scans
# and pushes the image. The runtime runs as a non-root user.
#
# The base is pinned by digest, but `apk upgrade` and `apk add` fetch the current Wolfi
# packages on every build, so each rebuild picks up new fixes.

# cgr.dev/chainguard/wolfi-base:latest, pinned. Bump it by digest.
ARG WOLFI_BASE=cgr.dev/chainguard/wolfi-base@sha256:256c88bb066424045021090932d50be93c8e3f2ce3586707702a401b146f3e43

FROM ${WOLFI_BASE} AS build
RUN apk upgrade --no-cache && apk add --no-cache bun ca-certificates
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY tsconfig.json ./
COPY src ./src
RUN bun build ./src/index.ts --compile --minify --outfile dist/server

FROM ${WOLFI_BASE} AS runtime
# The executable's C++ runtime and the CA bundle and a non-root user; then drop the
# package manager. wolfi-baselayout and busybox are added by name so that removing the
# wolfi-base meta-package (which pulls in apk) keeps them.
RUN apk upgrade --no-cache \
    && apk add --no-cache libstdc++ libgcc busybox wolfi-baselayout ca-certificates \
    && addgroup -g 1000 app \
    && adduser -D -u 1000 -G app -h /app -s /sbin/nologin app \
    && apk del --no-cache wolfi-base apk-tools wolfi-keys \
    && rm -rf /var/cache/apk /etc/apk /lib/apk
WORKDIR /app
COPY --from=build --chown=1000:1000 /app/dist/server ./server

ENV NODE_ENV=production \
    PORT={{ container_port }}
USER 1000
EXPOSE {{ container_port }}
CMD ["/app/server"]
