Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
node_modules
dist
coverage
.env
.env.*
!.env.example
.git
.github
test
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
Dockerfile
*.log
3 changes: 3 additions & 0 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ jobs:
- name: Build
run: pnpm build

- name: Build container image
run: docker build --tag keygate-server:ci .

- name: Boot the service against an unreachable RPC
# The routes that matter must answer before the first sync completes, and
# answering is the point: `/readyz` is 503 and a decision is a denial, not
Expand Down
34 changes: 34 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM node:20-bookworm-slim AS build

WORKDIR /app

RUN corepack enable

COPY package.json pnpm-lock.yaml ./
COPY scripts/only-pnpm.js scripts/
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

FROM node:20-bookworm-slim AS runtime

ENV NODE_ENV=production
WORKDIR /app

RUN groupadd --system --gid 1001 keygate \
&& useradd --system --uid 1001 --gid keygate keygate

RUN corepack enable

COPY package.json pnpm-lock.yaml ./
COPY scripts/only-pnpm.js scripts/
RUN pnpm install --prod --frozen-lockfile \
&& pnpm store prune \
&& rm -rf scripts

COPY --from=build /app/dist ./dist

USER keygate

CMD ["node", "dist/index.js"]
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ cp .env.example .env # then edit the three contract ids
pnpm dev # tsx watch, on KEYGATE_PORT
```

### Running in a container

Build and run the image with the required configuration supplied as environment
variables. The image runs as a non-root user and does not contain `.env` files.

```bash
docker build -t keygate-server .
docker run --rm \
-p 8080:8080 \
-e KEYGATE_SOROBAN_RPC_URL=https://your-rpc.example \
-e KEYGATE_CORE_CONTRACT=C... \
-e KEYGATE_POLICY_CONTRACT=C... \
-e KEYGATE_BREAKER_CONTRACT=C... \
keygate-server
```

Configure the orchestrator to use `/readyz` for readiness and `/healthz` for
liveness. `/readyz` remains unavailable until the first ledger sync completes.

```bash
curl -s localhost:8080/readyz
# {"ready":true,"stalenessSeconds":4}
Expand Down