-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathDockerfile
More file actions
183 lines (163 loc) · 9.8 KB
/
Dockerfile
File metadata and controls
183 lines (163 loc) · 9.8 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# ==============================================================================
# Stage 1: Builder — install all deps, resolve LFS assets, build
# ==============================================================================
FROM node:22-bookworm AS builder
# Install Bun (primary package manager and build tool)
RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.10"
ENV PATH="/root/.bun/bin:${PATH}"
WORKDIR /app
ENV NODE_LLAMA_CPP_SKIP_DOWNLOAD="true"
ARG MILADY_DOCKER_APT_PACKAGES=""
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git git-lfs $MILADY_DOCKER_APT_PACKAGES && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
# Copy full source so Bun can resolve all workspaces declared in package.json.
COPY . .
# Pull large media tracked by Git LFS when git metadata is available (e.g. Railway GitHub deploy).
RUN if [ -d .git ]; then \
git lfs install --local && \
git lfs pull || true; \
fi
# If pointer files remain (common in some cloud build contexts), fallback to
# cloning the repo and pulling LFS assets directly, then overwrite local media.
ARG MILADY_LFS_REPO_URL=""
ARG MILADY_LFS_REF=""
ARG MILADY_LFS_COMMIT=""
ARG GITHUB_TOKEN=""
RUN set -e; \
GITHUB_TOKEN="${GITHUB_TOKEN}"; \
REPO_URL_RAW="$MILADY_LFS_REPO_URL"; \
if [ -z "$REPO_URL_RAW" ] && [ -d .git ]; then REPO_URL_RAW="$(git config --get remote.origin.url || true)"; fi; \
if [ -z "$REPO_URL_RAW" ]; then REPO_URL_RAW="https://github.com/miladybsc/milady.git"; fi; \
if echo "$REPO_URL_RAW" | grep -q '^git@github.com:'; then REPO_URL_RAW="$(echo "$REPO_URL_RAW" | sed -E 's#^git@github.com:(.+)$#https://github.com/\1#')"; fi; \
if echo "$REPO_URL_RAW" | grep -q '^ssh://git@github.com/'; then REPO_URL_RAW="$(echo "$REPO_URL_RAW" | sed -E 's#^ssh://git@github.com/#https://github.com/#')"; fi; \
POINTERS="$(grep -RIl '^version https://git-lfs.github.com/spec/v1' apps/app/public/vrms apps/app/public/animations || true)"; \
if [ -n "$POINTERS" ]; then \
echo '[build] Unresolved Git LFS pointers detected in build context; attempting fallback clone...'; \
REPO_URL="$REPO_URL_RAW"; \
REF="$MILADY_LFS_REF"; \
COMMIT="$MILADY_LFS_COMMIT"; \
if [ -z "$REF" ] && [ -n "${RAILWAY_GIT_BRANCH:-}" ]; then REF="${RAILWAY_GIT_BRANCH}"; fi; \
if [ -z "$REF" ]; then REF="main"; fi; \
if [ -z "$COMMIT" ] && [ -n "${RAILWAY_GIT_COMMIT_SHA:-}" ]; then COMMIT="${RAILWAY_GIT_COMMIT_SHA}"; fi; \
if [ -n "$GITHUB_TOKEN" ] && echo "$REPO_URL" | grep -q '^https://github.com/'; then \
REPO_URL="$(echo "$REPO_URL" | sed "s#^https://#https://x-access-token:${GITHUB_TOKEN}@#")"; \
fi; \
rm -rf /tmp/milady-lfs-src; \
if git -c filter.lfs.smudge= -c filter.lfs.process= -c filter.lfs.required=false clone --depth 1 --branch "$REF" "$REPO_URL" /tmp/milady-lfs-src; then \
cd /tmp/milady-lfs-src; \
if [ -n "$COMMIT" ]; then \
git -c filter.lfs.smudge= -c filter.lfs.process= -c filter.lfs.required=false fetch --depth 1 origin "$COMMIT" && GIT_LFS_SKIP_SMUDGE=1 git checkout "$COMMIT"; \
fi; \
git lfs install --local; \
# LFS budget/quota can block fetch; continue so media.githubusercontent fallback can run.
git lfs fetch origin "$REF" --include='apps/app/public/vrms' || true; \
git lfs fetch origin "$REF" --include='apps/app/public/animations/mixamo' || true; \
git lfs fetch origin "$REF" --include='apps/app/public/animations/emotes' || true; \
git lfs fetch origin "$REF" --include='apps/app/public/animations/idle.glb' || true; \
git lfs checkout apps/app/public/vrms || true; \
git lfs checkout apps/app/public/animations/mixamo || true; \
git lfs checkout apps/app/public/animations/emotes || true; \
git lfs checkout apps/app/public/animations/idle.glb || true; \
cd /app; \
rm -rf apps/app/public/vrms apps/app/public/animations; \
mkdir -p apps/app/public/vrms/previews apps/app/public/vrms/backgrounds apps/app/public/animations; \
for vrm_id in 1 4 5 9; do \
if [ -f "/tmp/milady-lfs-src/apps/app/public/vrms/milady-${vrm_id}.vrm" ]; then \
gzip -c "/tmp/milady-lfs-src/apps/app/public/vrms/milady-${vrm_id}.vrm" > "apps/app/public/vrms/milady-${vrm_id}.vrm.gz"; \
fi; \
if [ -f "/tmp/milady-lfs-src/apps/app/public/vrms/previews/milady-${vrm_id}.png" ]; then \
cp -a "/tmp/milady-lfs-src/apps/app/public/vrms/previews/milady-${vrm_id}.png" apps/app/public/vrms/previews/; \
fi; \
done; \
for bg_id in 1 4 5 9; do \
if [ -f "/tmp/milady-lfs-src/apps/app/public/vrms/backgrounds/milady-${bg_id}.png" ]; then \
cp -a "/tmp/milady-lfs-src/apps/app/public/vrms/backgrounds/milady-${bg_id}.png" apps/app/public/vrms/backgrounds/; \
fi; \
done; \
cp -a /tmp/milady-lfs-src/apps/app/public/animations/mixamo apps/app/public/animations/ || true; \
cp -a /tmp/milady-lfs-src/apps/app/public/animations/emotes apps/app/public/animations/ || true; \
cp -a /tmp/milady-lfs-src/apps/app/public/animations/idle.glb apps/app/public/animations/ || true; \
rm -f apps/app/public/animations/emotes/idle.glb apps/app/public/animations/emotes/punch.glb apps/app/public/animations/mixamo/Crying.fbx; \
find apps/app/public/animations -type f \( -name '*.glb' -o -name '*.fbx' \) -exec sh -c 'gzip -c "$1" > "$1.gz" && rm -f "$1"' _ {} \; ; \
rm -rf /tmp/milady-lfs-src; \
else \
echo '[build] WARNING: fallback clone failed; continuing with existing assets.'; \
fi; \
fi; \
MEDIA_REPO="$REPO_URL_RAW"; \
MEDIA_REPO_PATH="$(echo "$MEDIA_REPO" | sed -E 's#^https://([^@/]+@)?github.com/([^/]+/[^/.]+)(\\.git)?$#\\2#')"; \
if [ -z "$MEDIA_REPO_PATH" ] || [ "$MEDIA_REPO_PATH" = "$MEDIA_REPO" ]; then MEDIA_REPO_PATH="miladybsc/milady"; fi; \
MEDIA_REF="$MILADY_LFS_REF"; \
if [ -z "$MEDIA_REF" ] && [ -n "${RAILWAY_GIT_BRANCH:-}" ]; then MEDIA_REF="${RAILWAY_GIT_BRANCH}"; fi; \
if [ -z "$MEDIA_REF" ]; then MEDIA_REF="main"; fi; \
VRM_POINTERS="$(grep -RIl '^version https://git-lfs.github.com/spec/v1' apps/app/public/vrms || true)"; \
if [ -n "$VRM_POINTERS" ]; then \
echo '[build] VRM pointers detected after LFS restore; attempting media.githubusercontent fallback...'; \
echo "$VRM_POINTERS" | while IFS= read -r FILE; do \
[ -z "$FILE" ] && continue; \
URL="https://media.githubusercontent.com/media/${MEDIA_REPO_PATH}/${MEDIA_REF}/${FILE}"; \
echo "[build] downloading $FILE"; \
curl -fsSL "$URL" -o "$FILE" || true; \
done; \
fi; \
VRM_POINTERS="$(grep -RIl '^version https://git-lfs.github.com/spec/v1' apps/app/public/vrms || true)"; \
if [ -n "$VRM_POINTERS" ]; then \
echo '[build] ERROR: unresolved Git LFS pointers remain in VRM assets:'; \
echo "$VRM_POINTERS"; \
exit 1; \
fi; \
ANIMATION_POINTERS="$(grep -RIl '^version https://git-lfs.github.com/spec/v1' apps/app/public/animations || true)"; \
if [ -n "$ANIMATION_POINTERS" ]; then \
echo '[build] WARNING: unresolved Git LFS pointers remain in animation assets; build will continue.'; \
echo "$ANIMATION_POINTERS" | head -n 60; \
fi
# Install dependencies with the committed lockfile while skipping third-party
# postinstall hooks that may fail in cloud builders. Then run our required
# local patch/link scripts before building.
RUN bun install --frozen-lockfile --ignore-scripts
RUN node ./scripts/link-browser-server.mjs && node ./scripts/patch-deps.mjs
RUN bun run build
# Re-install with production-only dependencies for the runtime image.
RUN rm -rf node_modules && bun install --frozen-lockfile --ignore-scripts --production
# ==============================================================================
# Stage 2: Runtime — lean production image without dev deps, source, or build tools
# ==============================================================================
FROM node:22-bookworm AS runtime
# Install Bun (needed at runtime for bun-native modules)
RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.10"
ENV PATH="/root/.bun/bin:${PATH}"
WORKDIR /app
ENV NODE_LLAMA_CPP_SKIP_DOWNLOAD="true"
ARG MILADY_DOCKER_APT_PACKAGES=""
RUN if [ -n "$MILADY_DOCKER_APT_PACKAGES" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $MILADY_DOCKER_APT_PACKAGES && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
fi
# Copy production node_modules (no devDependencies)
COPY --from=builder /app/node_modules ./node_modules
# Copy build outputs
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/apps/app/dist ./apps/app/dist
# Copy entrypoint and runtime scripts
COPY --from=builder /app/milady.mjs ./milady.mjs
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/scripts ./scripts
# Copy resolved VRM/animation assets (from LFS or fallback)
COPY --from=builder /app/apps/app/public ./apps/app/public
# Copy workspace package.json files so Node module resolution works
COPY --from=builder /app/apps/app/package.json ./apps/app/package.json
COPY --from=builder /app/apps/app/node_modules ./apps/app/node_modules
ENV NODE_ENV=production
ENV MILADY_API_BIND="0.0.0.0"
ENV MILADY_STATE_DIR="/data/.milady"
ENV MILADY_CONFIG_PATH="/data/.milady/milady.json"
ENV PGLITE_DATA_DIR="/data/.milady/workspace/.eliza/.elizadb"
# Railway volume mount target. If /data is backed by a persistent volume,
# onboarding/config/database survive redeploys.
RUN mkdir -p /data/.milady/workspace/.eliza/.elizadb
# Railway sets $PORT dynamically. Map it to MILADY_PORT at runtime.
CMD ["sh", "-lc", "MILADY_PORT=${PORT:-2138} node milady.mjs start"]