-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathContainerfile.j2
More file actions
167 lines (141 loc) · 6.34 KB
/
Containerfile.j2
File metadata and controls
167 lines (141 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
ARG BASE_VERSION=15
ARG UPSTREAM_URL="https://api.github.com/repos/kikootwo/readmeabook/releases/latest"
FROM ghcr.io/daemonless/base:${BASE_VERSION} AS builder
ARG UPSTREAM_URL
# Build dependencies (C compiler + python for bcrypt, Rust libs for Prisma engines)
RUN pkg update && pkg install -y \
jq \
node npm \
git-lite gmake pkgconf \
FreeBSD-clang FreeBSD-clang-dev FreeBSD-clibs-dev FreeBSD-openssl-dev \
FreeBSD-toolchain \
FreeBSD-libexecinfo-dev FreeBSD-utilities-dev FreeBSD-runtime-dev \
python311 \
&& pkg clean -ay
# Install Rust (needed to build Prisma query engine for FreeBSD)
RUN fetch -qo - https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
# Set up compiler symlinks for node-gyp
RUN ln -sf /usr/bin/clang++ /usr/bin/c++ && \
ln -sf /usr/bin/clang /usr/bin/cc
# Clone source (resolve latest version from upstream)
WORKDIR /build
RUN --mount=type=secret,id=github_token \
FETCH_URL="${UPSTREAM_URL}"; \
GITHUB_TOKEN=$(cat /run/secrets/github_token 2>/dev/null || echo ""); \
if [ -n "${GITHUB_TOKEN}" ]; then \
FETCH_URL=$(echo "${UPSTREAM_URL}" | sed "s|https://|https://x-access-token:${GITHUB_TOKEN}@|"); \
fi && \
VERSION=$(fetch -qo - "${FETCH_URL}" | jq -r '.tag_name') && \
echo "Resolved VERSION=$VERSION" && \
git clone --depth 1 --branch ${VERSION} \
https://github.com/kikootwo/readmeabook.git . && \
echo "${VERSION}" > /tmp/app_version
# Install dependencies (includes bcrypt native build via node-gyp)
RUN PYTHON=/usr/local/bin/python3.11 npm ci
# Build Prisma query engine + schema engine for FreeBSD (no prebuilt binaries available)
RUN . "$HOME/.cargo/env" && \
PRISMA_ENGINE_HASH=$(node -e "console.log(require('./node_modules/@prisma/engines-version').enginesVersion)") && \
echo "Building Prisma engines at commit $PRISMA_ENGINE_HASH" && \
git clone https://github.com/prisma/prisma-engines.git /tmp/prisma-engines && \
cd /tmp/prisma-engines && \
git checkout "$PRISMA_ENGINE_HASH" && \
cargo build --release -p query-engine-node-api && \
cargo build --release -p schema-engine-cli && \
cp target/release/libquery_engine.so /build/node_modules/.prisma/client/libquery_engine-freebsd15.so.node && \
cp target/release/schema-engine /tmp/schema-engine && \
rm -rf /tmp/prisma-engines
# Generate Prisma client
ENV DATABASE_URL="postgresql://dummy:dummy@localhost:5432/dummy?schema=public"
RUN PRISMA_SCHEMA_ENGINE_BINARY=/tmp/schema-engine \
PRISMA_QUERY_ENGINE_LIBRARY=/build/node_modules/.prisma/client/libquery_engine-freebsd15.so.node \
npx prisma generate
# Build Next.js application (standalone output)
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
# Turbopack requires native @next/swc (no FreeBSD binary), WASM fallback doesn't support it
RUN npx next build --webpack
# Reorganize standalone output
RUN cp -r .next/standalone/* . && \
cp -r .next/static ./.next/static && \
cp -r public ./public 2>/dev/null || true
# Prepare production app directory
RUN mkdir -p /app && \
cp -r server.js package.json node_modules .next public prisma /app/ 2>/dev/null || true && \
cp /tmp/app_version /app/version && \
cp /tmp/schema-engine /app/schema-engine
# Ensure native query engine is in all expected locations
RUN cp /build/node_modules/.prisma/client/libquery_engine-freebsd15.so.node \
/app/node_modules/.prisma/client/ 2>/dev/null || true && \
cp /build/node_modules/.prisma/client/libquery_engine-freebsd15.so.node \
/app/prisma/ 2>/dev/null || true
# Clean up dev artifacts
RUN cd /app && \
find node_modules -name "*.d.ts" -delete 2>/dev/null || true && \
find node_modules -name "*.map" -delete 2>/dev/null || true && \
rm -rf node_modules/.cache 2>/dev/null || true
# Production image
FROM ghcr.io/daemonless/base:${BASE_VERSION}
ARG FREEBSD_ARCH=amd64
ARG PACKAGES="node postgresql16-server postgresql16-client redis ffmpeg openssl"
ARG UPSTREAM_URL="https://api.github.com/repos/kikootwo/readmeabook/releases/latest"
ARG UPSTREAM_JQ=".tag_name"
{%- if ports %}
ARG HEALTHCHECK_ENDPOINT="http://localhost:{{ ports[0].port }}/api/health"
{%- else %}
ARG HEALTHCHECK_ENDPOINT="http://localhost:3030/api/health"
{%- endif %}
ENV HEALTHCHECK_URL="${HEALTHCHECK_ENDPOINT}"
# --- Metadata (Injected by Generator) ---
LABEL org.opencontainers.image.title="{{ title }}" \
org.opencontainers.image.description="{{ description }}" \
org.opencontainers.image.source="{{ repo_url }}" \
org.opencontainers.image.url="{{ web_url }}" \
org.opencontainers.image.version="latest" \
org.opencontainers.image.licenses="AGPL-3.0" \
org.opencontainers.image.vendor="daemonless" \
org.opencontainers.image.authors="daemonless" \
io.daemonless.category="{{ category }}" \
{%- if ports %}
io.daemonless.port="{{ ports[0].port }}" \
{%- endif %}
{%- if volumes %}
io.daemonless.volumes="{{ volumes | map(attribute='path') | join(',') }}" \
{%- endif %}
{%- if mlock %}
org.freebsd.jail.allow.mlock="required" \
{%- endif %}
io.daemonless.arch="${FREEBSD_ARCH}" \
io.daemonless.upstream-url="${UPSTREAM_URL}" \
io.daemonless.upstream-jq="${UPSTREAM_JQ}" \
io.daemonless.healthcheck-url="${HEALTHCHECK_ENDPOINT}" \
io.daemonless.packages="${PACKAGES}"
# Install runtime dependencies
RUN pkg update && \
pkg install -y ${PACKAGES} && \
mkdir -p /app && \
pkg clean -ay && \
rm -rf /var/cache/pkg/* /var/db/pkg/repos/*
# Copy version and built application from builder
COPY --from=builder /tmp/app_version /tmp/app_version
COPY --from=builder --chown=bsd:bsd /app /app
# Create directories
RUN cp /tmp/app_version /app/version && \
mkdir -p /app/config /app/cache /downloads /media \
/var/lib/postgresql/data /var/lib/redis \
/var/run/postgresql /etc/s6-env && \
chmod 755 /var/lib && \
chown -R bsd:bsd /app /var/lib/postgresql /var/run/postgresql \
/var/lib/redis /downloads /media
# Copy service files
COPY root/ /
RUN chmod +x /etc/services.d/*/run /etc/cont-init.d/* 2>/dev/null || true
WORKDIR /app
ENV NODE_ENV=production
# --- Expose (Injected by Generator) ---
{%- if ports %}
EXPOSE {{ ports | map(attribute='port') | join(' ') }}
{%- endif %}
# --- Volumes (Injected by Generator) ---
{%- if volumes %}
VOLUME {{ volumes | map(attribute='path') | join(' ') }}
{%- endif %}