Skip to content

Commit 6313e5a

Browse files
Merge pull request #431 from CodeForAfrica/ft/docker-image
feat(docker): add docker support with apache tika integration
2 parents 0f09342 + bb4aff3 commit 6313e5a

29 files changed

+1685
-618
lines changed

.dockerignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Exclude version control and dependency directories
2+
.git
3+
.gitignore
4+
node_modules
5+
.next
6+
out
7+
build
8+
coverage
9+
temp
10+
old
11+
# Ignore local env and config overrides
12+
.env*
13+
.env.local
14+
.env.*
15+
16+
# OS / editor files
17+
.DS_Store
18+
.idea
19+
20+
# Test artifacts
21+
playwright-report
22+
blob-report
23+
test-results
24+
25+
# vscode
26+
.vscode
27+
28+
# Misc
29+
script.js
30+
documents
31+
media
32+
old
33+
temp
34+
tests

.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ NEXT_PUBLIC_APP_URL=http://localhost:3000
33
# Payload
44
DATABASE_URI=mongodb://127.0.0.1/your-database-name
55
PAYLOAD_SECRET=YOUR_SECRET_HERE
6+
AX_APACHE_TIKA_URL=http://127.0.0.1:9998/
67

78
#Sentry
89
NEXT_PUBLIC_SENTRY_DSN=
@@ -13,3 +14,16 @@ SENTRY_PROJECT=promisetracker
1314
#Locales
1415
NEXT_PUBLIC_DEFAULT_LOCALE=en
1516
NEXT_PUBLIC_LOCALES="en, fr"
17+
18+
# S3
19+
S3_BUCKET=
20+
S3_ACCESS_KEY_ID=
21+
S3_SECRET_ACCESS_KEY=
22+
S3_REGION=
23+
24+
# SMTP
25+
SMTP_USER=
26+
SMTP_HOST=
27+
SMTP_PASS=
28+
SMTP_FROM_ADDRESS=
29+
SMTP_FROM_NAME=

.github/workflows/deploy-dev.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Promise Tracker | Deploy | Dev
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
concurrency:
8+
group: "${{ github.workflow }} @ ${{ github.ref }}"
9+
cancel-in-progress: true
10+
11+
env:
12+
APP_NAME: promisetracker-v2
13+
DOKKU_REMOTE_BRANCH: "master"
14+
DOKKU_REMOTE_URL: "ssh://[email protected]"
15+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16+
IMAGE_NAME: "codeforafrica/promisetracker-v2"
17+
NEXT_PUBLIC_APP_URL: "https://promisetracker-v2.dev.codeforafrica.org"
18+
SENTRY_ENVIRONMENT: "development"
19+
20+
jobs:
21+
deploy:
22+
runs-on: ${{ matrix.os }}
23+
strategy:
24+
matrix:
25+
node-version: [20.16]
26+
os: [ubuntu-latest]
27+
steps:
28+
- name: Checkout
29+
uses: actions/checkout@v4
30+
with:
31+
fetch-depth: 1
32+
33+
# Add support for more platforms with QEMU (optional)
34+
- name: Set up QEMU
35+
uses: docker/setup-qemu-action@v3
36+
37+
- name: Set up Docker Buildx
38+
uses: docker/setup-buildx-action@v3
39+
40+
- name: Login to DockerHub
41+
uses: docker/login-action@v3
42+
with:
43+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
44+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
45+
46+
- name: Build Docker image
47+
uses: docker/build-push-action@v6
48+
with:
49+
build-args: |
50+
NEXT_PUBLIC_APP_URL=${{ env.NEXT_PUBLIC_APP_URL }}
51+
NEXT_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}
52+
SENTRY_ENVIRONMENT=${{ env.SENTRY_ENVIRONMENT }}
53+
cache-from: type=gha
54+
cache-to: type=gha,mode=max
55+
context: .
56+
platforms: linux/arm64
57+
push: true
58+
secrets: |
59+
"database_uri=${{ secrets.DATABASE_URI }}"
60+
"payload_secret=${{ secrets.PAYLOAD_SECRET }}"
61+
"sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}"
62+
"sentry_org=${{ secrets.SENTRY_ORG }}"
63+
"sentry_project=${{ secrets.SENTRY_PROJECT }}"
64+
tags: "${{ env.IMAGE_NAME }}:${{ github.sha }}"
65+
66+
- name: Push to Dokku
67+
uses: dokku/[email protected]
68+
with:
69+
git_remote_url: ${{ env.DOKKU_REMOTE_URL }}/${{ env.APP_NAME }}
70+
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
71+
deploy_docker_image: ${{ env.IMAGE_NAME }}:${{ github.sha }}

Dockerfile

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,80 @@
11
# To use this Dockerfile, you have to set `output: 'standalone'` in your next.config.mjs file.
2-
# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
2+
# Based on https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
3+
4+
ARG PNPM_VERSION=10.16.1
35

46
FROM node:22.12.0-alpine AS base
7+
ARG PNPM_VERSION
8+
RUN npm install -g pnpm@${PNPM_VERSION}
59

610
# Install dependencies only when needed
711
FROM base AS deps
8-
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
912
RUN apk add --no-cache libc6-compat
1013
WORKDIR /app
1114

12-
# Install dependencies based on the preferred package manager
13-
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
14-
RUN \
15-
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
16-
elif [ -f package-lock.json ]; then npm ci; \
17-
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
18-
else echo "Lockfile not found." && exit 1; \
19-
fi
20-
15+
COPY package.json pnpm-lock.yaml ./
16+
RUN pnpm install --frozen-lockfile
2117

2218
# Rebuild the source code only when needed
2319
FROM base AS builder
2420
WORKDIR /app
21+
2522
COPY --from=deps /app/node_modules ./node_modules
2623
COPY . .
2724

28-
# Next.js collects completely anonymous telemetry data about general usage.
29-
# Learn more here: https://nextjs.org/telemetry
30-
# Uncomment the following line in case you want to disable telemetry during the build.
31-
# ENV NEXT_TELEMETRY_DISABLED 1
25+
ENV NODE_ENV=production \
26+
NEXT_TELEMETRY_DISABLED=1 \
27+
NEXT_PUBLIC_APP_URL=http://localhost:3000
3228

33-
RUN \
34-
if [ -f yarn.lock ]; then yarn run build; \
35-
elif [ -f package-lock.json ]; then npm run build; \
36-
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
37-
else echo "Lockfile not found." && exit 1; \
38-
fi
29+
RUN --mount=type=secret,id=database_uri,env=DATABASE_URI \
30+
--mount=type=secret,id=payload_secret,env=PAYLOAD_SECRET \
31+
--mount=type=secret,id=sentry_auth_token,env=SENTRY_AUTH_TOKEN \
32+
--mount=type=secret,id=sentry_org,env=SENTRY_ORG \
33+
--mount=type=secret,id=sentry_project,env=SENTRY_PROJECT \
34+
NODE_OPTIONS="--no-deprecation" pnpm exec next build
3935

4036
# Production image, copy all the files and run next
4137
FROM base AS runner
38+
ARG TIKA_VERSION=3.2.3
4239
WORKDIR /app
4340

44-
ENV NODE_ENV production
45-
# Uncomment the following line in case you want to disable telemetry during runtime.
46-
# ENV NEXT_TELEMETRY_DISABLED 1
41+
ENV NODE_ENV=production \
42+
TIKA_VERSION=${TIKA_VERSION} \
43+
TIKA_PORT=9998 \
44+
TIKA_HOST=0.0.0.0 \
45+
TIKA_SERVER_JAR=/opt/tika/tika-server.jar \
46+
TIKA_ENABLED=1 \
47+
AX_APACHE_TIKA_URL=http://127.0.0.1:9998/ \
48+
HOSTNAME=0.0.0.0 \
49+
PORT=3000
50+
51+
RUN apk add --no-cache openjdk17-jre-headless curl
4752

4853
RUN addgroup --system --gid 1001 nodejs
4954
RUN adduser --system --uid 1001 nextjs
5055

51-
# Remove this line if you do not have this folder
56+
RUN mkdir -p /opt/tika \
57+
&& curl -fsSL "https://archive.apache.org/dist/tika/${TIKA_VERSION}/tika-server-standard-${TIKA_VERSION}.jar" -o "${TIKA_SERVER_JAR}" \
58+
&& chmod 644 "${TIKA_SERVER_JAR}"
59+
5260
COPY --from=builder /app/public ./public
5361

54-
# Set the correct permission for prerender cache
5562
RUN mkdir .next
5663
RUN chown nextjs:nodejs .next
5764

58-
# Automatically leverage output traces to reduce image size
59-
# https://nextjs.org/docs/advanced-features/output-file-tracing
6065
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
6166
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
6267

68+
COPY docker/entrypoint.sh /entrypoint.sh
69+
RUN chmod +x /entrypoint.sh
70+
71+
RUN mkdir -p /app/temp /app/media \
72+
&& chown nextjs:nodejs /app/temp /app/media \
73+
&& chmod 775 /app/temp /app/media
74+
6375
USER nextjs
6476

6577
EXPOSE 3000
6678

67-
ENV PORT 3000
68-
69-
# server.js is created by next build from the standalone output
70-
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
71-
CMD HOSTNAME="0.0.0.0" node server.js
79+
ENTRYPOINT ["/entrypoint.sh"]
80+
CMD ["node", "server.js"]

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,17 @@
1818
4. Update settings in admin
1919
[/admin/globals/settings]
2020
5. When testing multitenant app, use a domain that resolves to localhost, similar to `localtest.me`, for example `ken.localtest.me:3000`
21+
22+
## Docker Image
23+
24+
- Build the production image (bundles Apache Tika 3.2.3, no database services) using Docker BuildKit secrets:
25+
```
26+
docker build -t promisetracker:latest \
27+
--secret id=database_uri,env=DATABASE_URI \
28+
--secret id=payload_secret,env=PAYLOAD_SECRET \
29+
.
30+
```
31+
Provide `DATABASE_URI` and `PAYLOAD_SECRET` (build fails if they’re missing); Sentry secrets are optional. You can also point secrets at files via `--secret id=…,src=path/to/file`.
32+
- Run the container against an external database:
33+
`docker run -p 3000:3000 -e DATABASE_URI="<your-database-uri>" -e PAYLOAD_SECRET="<secret>" promisetracker:latest`
34+
- The bundled Apache Tika server listens on `http://127.0.0.1:9998/`. Override `AX_APACHE_TIKA_URL`, `TIKA_PORT`, or `TIKA_ENABLED=0` if you prefer an external Tika service.

0 commit comments

Comments
 (0)