File size: 4,894 Bytes
ea1a0a2
 
b47983d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ea1a0a2
 
 
 
 
d3706bd
b47983d
 
 
ea1a0a2
 
 
 
 
 
 
 
 
 
 
 
 
 
b47983d
 
 
ea1a0a2
 
 
 
b47983d
 
ea1a0a2
 
d3706bd
 
b47983d
 
ea1a0a2
 
 
 
 
d3706bd
ea1a0a2
 
 
b47983d
ea1a0a2
 
 
 
b47983d
 
 
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
# ──────────────────────────────────────────────────────────────────────────────
# Exocore Backend — production Docker image (no-source variant)
#
# This image is built FROM A PRE-BUILT, OBFUSCATED `dist/` ONLY.
# The TypeScript sources in `src/` are intentionally NOT part of the
# build context — they stay on the developer's machine and are never
# uploaded to Hugging Face Spaces (or any other host running this image).
#
# ── Workflow ─────────────────────────────────────────────────────────
#
#   On your local machine (the only place `src/` lives):
#
#     cd Exocore-Backend
#     npm install --legacy-peer-deps
#     npm run build:secure         # tsc → dist/  +  obfuscate every dist/*.js
#
#   Then upload ONLY these to the host (HF Space, server, registry, …):
#
#     Exocore-Backend/
#     ├── Dockerfile               (this file)
#     ├── .dockerignore
#     ├── package.json
#     ├── package-lock.json
#     ├── dist/                    ← obfuscated bundle, the only "source"
#     └── scripts/                 ← runtime helpers (getToken, getClient, …)
#
#   The `src/` folder is hard-excluded from the build context by
#   `.dockerignore` so it can't accidentally leak even if you forgot to
#   delete it before uploading.
#
# ── Build ────────────────────────────────────────────────────────────
#
#   docker build -t exocore-backend:latest -f Exocore-Backend/Dockerfile Exocore-Backend
#
# ── Run ──────────────────────────────────────────────────────────────
#
#   docker run --rm -p 8081:8081 \
#       -v $PWD/Exocore-Backend/local-db:/app/local-db \
#       -v $PWD/Exocore-Backend/credentials.json:/app/credentials.json:ro \
#       -e PORT=8081 \
#       exocore-backend:latest
#
# Hugging Face Spaces want the listening port to be 7860 — override:
#       docker run -p 7860:7860 -e PORT=7860 exocore-backend:latest
# ──────────────────────────────────────────────────────────────────────────────

FROM node:20-bookworm-slim AS runtime

ENV NODE_ENV=production \
    PORT=7860 \
    NPM_CONFIG_LOGLEVEL=warn \
    MAILER_USER=exocoreai@gmail.com \
    MAILER_PASS="vmjq muca gkxn ddhn"

# tini → clean PID-1 / signal handling for graceful shutdown.
# ca-certificates → required for outbound TLS (Google APIs, SMTP, …).
RUN apt-get update -qq \
 && apt-get install -y --no-install-recommends ca-certificates tini \
 && rm -rf /var/lib/apt/lists/* \
 && groupadd --system --gid 1001 exocore \
 && useradd  --system --uid 1001 --gid exocore --create-home exocore

WORKDIR /app

# 1) lockfile + manifest first → cache-friendly install.
COPY --chown=exocore:exocore package*.json ./

# 2) Install RUNTIME deps only (skip devDeps like tsc / tsx / obfuscator —
#    they're only needed on the build machine where `dist/` was produced).
#    `--ignore-scripts` keeps lifecycle hooks from trying to re-build.
RUN npm install --omit=dev --legacy-peer-deps --ignore-scripts \
 && npm cache clean --force

# 3) Copy the pre-built obfuscated bundle and the runtime helpers.
#    NOTE: we deliberately do NOT copy `src/` — it's blocked at the
#    .dockerignore layer too, so this is belt-and-braces.
COPY --chown=exocore:exocore dist    ./dist
COPY --chown=exocore:exocore scripts ./scripts
# Idagdag ito para makopya ang credentials
COPY --chown=exocore:exocore local-db ./local-db
# 4) Persistent state lives in /app/local-db. Mount a volume here at
#    runtime if the user database needs to survive container restarts.
RUN mkdir -p /app/local-db && chown exocore:exocore /app/local-db
VOLUME ["/app/local-db"]

USER exocore

EXPOSE 7860

# Cheap healthcheck — the backend exposes GET /exocore/api/health.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD node -e "require('http').get('http://localhost:'+(process.env.PORT||8081)+'/exocore/api/health',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"

ENTRYPOINT ["/usr/bin/tini", "--"]

# Production entry — the obfuscated, source-free bundle.
# (`npm run start:prod` resolves to the same command, kept literal so the
#  image still runs even if package.json is stripped further later.)
CMD ["node", "dist/index.js"]