Skip to content
Merged
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
34 changes: 28 additions & 6 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
name: Docker Release
name: Docker Image

on:
pull_request:
paths:
- Dockerfile
- docker-compose*.yml
- docker-entrypoint.sh
- package.json
- pnpm-lock.yaml
- next.config.mjs
- prisma/**
- app/**
- components/**
- lib/**
- .github/workflows/docker-release.yml
push:
branches: [main]
tags: ['v*.*.*']
release:
types: [published]

permissions:
contents: read
packages: write

concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build and Push Docker Image
name: Build Docker image
runs-on: ubuntu-latest

steps:
Expand All @@ -25,6 +45,7 @@ jobs:
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
Expand All @@ -37,17 +58,18 @@ jobs:
with:
images: ${{ steps.image.outputs.name }}
tags: |
type=ref,event=tag
type=raw,value=main,enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
type=sha,prefix=sha-,format=short,enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest
type=raw,value=latest,enable=${{ github.event_name == 'release' || startsWith(github.ref, 'refs/tags/v') }}

- name: Build and push Docker image
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
Expand Down
38 changes: 24 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,40 +1,50 @@
# syntax=docker/dockerfile:1.7
FROM node:24-alpine AS base

ENV NEXT_TELEMETRY_DISABLED="1"
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

WORKDIR /app

FROM base AS deps
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

FROM base AS builder
ENV AUTH_SECRET="docker-build-placeholder"
ENV DATABASE_URL="postgresql://agentbridge:agentbridge@localhost:5432/agentbridge?schema=public"
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm prisma generate
RUN pnpm build

FROM base AS prod-deps
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN --mount=type=cache,id=pnpm-prod,target=/pnpm/store pnpm install --frozen-lockfile --prod

FROM base AS runner
ENV NODE_ENV="production"
ENV NEXT_TELEMETRY_DISABLED="1"
ENV PORT="3000"
ENV HOSTNAME="0.0.0.0"

COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/generated ./generated
COPY --from=builder /app/public ./public
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts
COPY --from=builder /app/next.config.mjs ./next.config.mjs
COPY docker-entrypoint.sh ./docker-entrypoint.sh
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs

COPY --from=prod-deps --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/generated ./generated
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
COPY --from=builder --chown=nextjs:nodejs /app/prisma.config.ts ./prisma.config.ts
COPY --from=builder --chown=nextjs:nodejs /app/docker-entrypoint.sh ./docker-entrypoint.sh

RUN chmod +x ./docker-entrypoint.sh

USER nextjs

EXPOSE 3000

ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["pnpm", "start", "--", "-H", "0.0.0.0"]
CMD ["node", "server.js"]
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,44 @@ corepack enable

7. Open [http://localhost:3000](http://localhost:3000). The root route redirects to `/dashboard`.

## Docker deployment

AgentBridge ships a production Docker image for the Next.js app. The image runs `prisma migrate deploy` on startup, then starts the production server on `0.0.0.0:3000`.

Required runtime environment:

- `DATABASE_URL`: PostgreSQL connection string, including `?schema=public` when using the default Prisma schema.
- `AUTH_SECRET`: long random secret used for session signing.
- `NEXT_TELEMETRY_DISABLED`: set to `1` to keep Next telemetry disabled.
- `PORT`: optional host port for Docker Compose; the container listens on port `3000`.

Run with an external PostgreSQL database:

```bash
docker run --rm \
-p 3000:3000 \
-e DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/agentbridge?schema=public" \
-e AUTH_SECRET="replace-with-a-long-random-string" \
-e NEXT_TELEMETRY_DISABLED="1" \
ghcr.io/Vann-Dev/AgentBridge:latest
```

Build and run locally with Compose against an external database:

```bash
DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/agentbridge?schema=public" \
AUTH_SECRET="replace-with-a-long-random-string" \
docker compose up --build app
```

For local Docker-only testing, start the bundled PostgreSQL service through the `local-db` profile:

```bash
docker compose --profile local-db up --build
```

The GitHub Actions Docker workflow validates image builds on pull requests without pushing. Pushes to `main` publish `ghcr.io/Vann-Dev/AgentBridge:main` and `sha-<shortsha>`. Semver tags such as `v1.2.3` and published GitHub releases publish semver tags and `latest`.

## First-run workflow

1. Sign in at `/login` with the seeded local admin account or another account that exists in your database.
Expand Down
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ services:
depends_on:
db:
condition: service_healthy
required: false
environment:
AUTH_SECRET: ${AUTH_SECRET:-replace-with-a-long-random-string-for-local-docker}
DATABASE_URL: postgresql://agentbridge:agentbridge@db:5432/agentbridge?schema=public
DATABASE_URL: ${DATABASE_URL:-postgresql://agentbridge:agentbridge@db:5432/agentbridge?schema=public}
NEXT_TELEMETRY_DISABLED: "1"
ports:
- "3000:3000"
- "${PORT:-3000}:3000"

db:
image: postgres:18-alpine
profiles: ["local-db"]
restart: unless-stopped
environment:
POSTGRES_DB: agentbridge
Expand Down
4 changes: 3 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
const nextConfig = {
output: 'standalone',
}

export default nextConfig
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"next": "16.1.7",
"next-themes": "^0.4.6",
"pg": "^8.20.0",
"prisma": "^7.8.0",
"radix-ui": "^1.4.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
Expand All @@ -54,10 +55,20 @@
"postcss": "^8",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"prisma": "^7.8.0",
"tailwindcss": "^4.2.1",
"tsx": "^4.21.0",
"typescript": "^5.9.3"
},
"packageManager": "pnpm@11.0.9"
"packageManager": "pnpm@11.0.9",
"pnpm": {
"onlyBuiltDependencies": [
"@prisma/engines",
"@scarf/scarf",
"esbuild",
"msw",
"prisma",
"sharp",
"unrs-resolver"
]
}
}
Loading
Loading