Skip to content

feat: Add Docker build and publish CI for web app #418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: main
Choose a base branch
from

Conversation

vishalmakwana111
Copy link
Contributor

@vishalmakwana111 vishalmakwana111 commented Apr 26, 2025

This PR adds Docker support for the apps/web application and a GitHub Actions workflow to automatically build and publish images to GHCR.

Changes:

  1. docker/Dockerfile.prod: New Dockerfile to build the web application production image.
  2. .github/workflows/publish-docker.yml: New GitHub Action workflow that:
    • Triggers on version tag pushes (v*.*.*).
    • Builds the image using Dockerfile.prod.
    • Pushes the tagged image to GHCR.
    • Note for Maintainers: Please update the images path in this workflow to ghcr.io/${{ github.repository_owner }}/inbox-zero after merging.
  3. Code Changes (apps/web/...): Modified blog/sitemap components to correctly handle dummy Sanity credentials during the Docker build process (next build).

Testing & Local Usage:

  • CI Workflow: Successfully tested in fork (vishalmakwana111/inbox-zero). Pushing a version tag built and pushed a working image. You can test this specific image: docker pull ghcr.io/vishalmakwana111/inbox-zero:v0.0.11
  • Local Build: You can build the image locally using docker build -t inbox-zero-test -f docker/Dockerfile.prod .
  • Running Pre-Built Image with Docker Compose:
    • To run the pre-built images from GHCR (after this PR is merged and images are published to the main repo's registry), modify your local docker-compose.yml file:
      1. Comment out or remove the build: section for the web service (if present).
      2. Set the image: line for the web service to point to the desired image tag, e.g., image: ghcr.io/elie222/inbox-zero:vX.Y.Z (replace elie222 and vX.Y.Z as needed). Use the tag mentioned above for testing from the fork.
    • Ensure your local ./apps/web/.env file contains the necessary runtime environment variables.
    • Run docker compose up -d.

Addresses the request for an official Docker image raised in #389.

Summary by CodeRabbit

  • New Features
    • Introduced automated publishing of Docker images to GitHub Container Registry on version tag pushes.
    • Added a production-ready Dockerfile for optimized and reproducible builds.
  • Bug Fixes
    • Improved blog and sitemap build reliability by skipping Sanity data fetches when dummy credentials are detected.
    • Added a user-facing message when blog post content is unavailable.
  • Chores
    • Updated Docker Compose to use a pre-built image from a remote registry.
    • Added Prettier Tailwind CSS plugin as a development dependency.

…stallation and explicitly run prisma generate after code copy
…process and update build command for Next.js application
…s with a single .env.build copy for build-time configuration
…s for build-time configuration, including database, authentication, Redis, and Sanity settings
… modify CMD in Dockerfile.prod for production server startup
…nds in Dockerfile.prod for improved troubleshooting
…nts and consolidating environment variable setup for build
… installing dependencies, ensuring postinstall scripts run correctly
Copy link

vercel bot commented Apr 26, 2025

@vishalmakwana111 is attempting to deploy a commit to the Inbox Zero Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Contributor

coderabbitai bot commented Apr 26, 2025

Walkthrough

This update introduces a new GitHub Actions workflow for automated Docker image publishing to GHCR on pushes to the main branch and semantic version tags. A new production Dockerfile is added to build the application container with Node 22 Alpine, pnpm, Prisma, Next.js, and dummy environment variables for build-time. The Docker Compose configuration is updated to use the published image from GHCR instead of building locally. Application code changes detect a dummy Sanity project ID to conditionally skip data fetching and static parameter generation during builds. Additionally, a Prettier plugin for Tailwind CSS is added as a development dependency.

Changes

File(s) Change Summary
.github/workflows/publish-docker.yml Added a new GitHub Actions workflow to build and publish Docker images to GHCR on pushes to main branch and semantic version tag pushes.
docker/Dockerfile.prod Added a production Dockerfile based on Node 22 Alpine with pnpm, Prisma client generation, Next.js build, dummy environment variables, and setup for production runtime.
docker-compose.yml Modified web service to comment out local Docker build and use a pre-built image from GHCR instead.
apps/web/app/blog/page.tsx
apps/web/app/blog/post/[slug]/page.tsx
apps/web/app/sitemap.ts
Updated to conditionally skip Sanity data fetching and static parameter generation when the environment variable NEXT_PUBLIC_SANITY_PROJECT_ID equals 'dummy-sanity-project-id-for-build', preventing fetches during certain build scenarios.
package.json Added prettier-plugin-tailwindcss version 0.6.11 as a new development dependency.

Sequence Diagram(s)

sequenceDiagram
    participant Developer
    participant GitHub
    participant GitHubActions
    participant DockerBuild
    participant GHCR
    participant DockerCompose
    participant Application

    Developer->>GitHub: Push to main branch or tag vX.Y.Z
    GitHub->>GitHubActions: Trigger publish-docker workflow
    GitHubActions->>DockerBuild: Build Docker image using Dockerfile.prod
    DockerBuild->>GHCR: Push image with tags (latest, semantic version)
    GitHubActions->>GitHub: Complete workflow
    Developer->>DockerCompose: Use docker-compose.yml to run container
    DockerCompose->>Application: Pull and run image from GHCR
Loading

Poem

🐇
A Docker hop, a workflow leap,
To GHCR our images creep.
Dummy IDs keep fetches at bay,
Ensuring smooth builds, night or day.
Tailwind Prettier joins the show,
Compose pulls images—off we go!
The rabbit cheers this tidy feat,
With every change, our build’s complete!
🌱


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b15101 and 8118c41.

📒 Files selected for processing (1)
  • .github/workflows/publish-docker.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/publish-docker.yml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
docker/Dockerfile.prod (1)

21-26: Consider using multi-stage build for a smaller production image

The current approach installs all dependencies including dev dependencies without pruning them after the build, which results in a larger final image.

- # Copy the rest of the application code FIRST
- COPY . .
- 
- # Install ALL dependencies (including dev, no pruning)
- # This will now run postinstall scripts *after* source code is copied
- RUN pnpm install --frozen-lockfile
+ # Copy the rest of the application code
+ COPY . .
+ 
+ # Install dependencies and run postinstall scripts
+ RUN pnpm install --frozen-lockfile && \
+     pnpm --filter inbox-zero-ai exec -- prisma generate && \
+     pnpm --filter inbox-zero-ai exec -- next build && \
+     pnpm install --frozen-lockfile --prod
apps/web/app/blog/post/[slug]/page.tsx (1)

13-13: Consider using consistent quote style across files.

Minor consistency note: this file uses single quotes for the dummy project ID string, while sitemap.ts uses double quotes for the same value.

-  if (process.env.NEXT_PUBLIC_SANITY_PROJECT_ID === 'dummy-sanity-project-id-for-build') {
+  if (process.env.NEXT_PUBLIC_SANITY_PROJECT_ID === "dummy-sanity-project-id-for-build") {
.github/workflows/publish-docker.yml (2)

4-4: Remove trailing whitespace.

There are trailing spaces at the end of these lines.

-name: Publish Docker Image 
+name: Publish Docker Image
-      - 'v*.*.*' # Trigger on tags like v1.0.0, v1.2.3, etc. 
+      - 'v*.*.*' # Trigger on tags like v1.0.0, v1.2.3, etc.

Also applies to: 9-9

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 4-4: trailing spaces

(trailing-spaces)


51-51: Consider removing no-cache: true.

You're using GitHub Actions cache with cache-from and cache-to, but no-cache: true disables the Docker build cache entirely, which could make builds slower. Unless you specifically need to ensure completely fresh builds every time, consider removing this line to benefit from both GHA and Docker caching.

-          no-cache: true
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b17a22e and 7e2bb3a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .github/workflows/publish-docker.yml (1 hunks)
  • apps/web/app/blog/page.tsx (1 hunks)
  • apps/web/app/blog/post/[slug]/page.tsx (2 hunks)
  • apps/web/app/sitemap.ts (1 hunks)
  • docker-compose.yml (1 hunks)
  • docker/Dockerfile.prod (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/app/blog/page.tsx (1)
apps/web/sanity/lib/fetch.ts (1)
  • sanityFetch (12-42)
🪛 YAMLlint (1.35.1)
.github/workflows/publish-docker.yml

[error] 4-4: trailing spaces

(trailing-spaces)


[error] 9-9: trailing spaces

(trailing-spaces)

🪛 Checkov (3.2.334)
docker/Dockerfile.prod

[MEDIUM] 32-33: Basic Auth Credentials

(CKV_SECRET_4)

🔇 Additional comments (12)
package.json (1)

24-24: Good addition for consistent Tailwind CSS formatting

Adding the Tailwind CSS Prettier plugin will help maintain consistent formatting of Tailwind CSS classes throughout the codebase, which improves readability and makes styles more maintainable.

docker/Dockerfile.prod (5)

1-8: LGTM: Proper base image and setup

Using Node 22 Alpine as the base image is a good choice for minimizing image size while providing the latest Node.js version. The essential tools installation looks good.


9-20: LGTM: Optimized Docker layer caching

Copying package manager files first before the rest of the application code is a great practice for optimizing Docker build caching. When package.json files don't change, Docker can reuse the cached dependency installation layer.


31-52: Dummy environment variables are properly isolated for build-time only

The use of dummy environment variables during build is a reasonable approach to satisfy build-time requirements without exposing sensitive information. However, ensure that these variables are only used during build and not at runtime.

Note that lines 32-33 containing dummy database URLs were flagged by static analysis as potential basic auth credentials, but since these are just placeholders for build time only, they don't represent a security risk.

Consider adding a comment clarifying that these values are never used in runtime:

- # Provide dummy build-time ENV VARS (Still needed for build)
+ # Provide dummy build-time ENV VARS (Still needed for build, never used at runtime)
🧰 Tools
🪛 Checkov (3.2.334)

[MEDIUM] 32-33: Basic Auth Credentials

(CKV_SECRET_4)


53-58: LGTM: Proper build steps

Generating the Prisma client followed by building the Next.js application is the correct sequence for the production build.


59-64: LGTM: Container configuration

Exposing port 3000 and setting the default command for starting the production server looks good.

docker-compose.yml (1)

40-44: Update the image reference before merging

The image is currently set to use the contributor's personal GitHub Container Registry path. As noted in the PR objectives, maintainers should update this to use the organization's registry path after merging.

- image: ghcr.io/vishalmakwana111/inbox-zero:latest # Use pre-built image (updated tag)
+ image: ghcr.io/${{ github.repository_owner }}/inbox-zero:latest # Use pre-built image (updated tag)

It might be better to use a specific version tag instead of latest for better stability and reproducibility, e.g., v0.0.1.

apps/web/app/blog/page.tsx (1)

209-213: LGTM: Properly handling Sanity fetch during build

Good approach to conditionally skip Sanity fetches during builds with dummy credentials. This ensures that the Docker build process won't attempt to fetch from Sanity when using the dummy project ID, avoiding build-time errors.

This change aligns with the PR's objective to modify blog components to properly handle dummy Sanity credentials during the Docker build process.

apps/web/app/sitemap.ts (1)

7-13: Good addition to handle dummy Sanity credentials during Docker builds.

This conditional check prevents calling the Sanity API during build time when using placeholder credentials, which is exactly what's needed for Docker builds to succeed without real Sanity access. The early return with an empty array is an elegant solution.

apps/web/app/blog/post/[slug]/page.tsx (2)

13-15: Good addition for Docker build compatibility.

This condition correctly prevents fetching post paths during builds with dummy credentials, consistent with the approach used in sitemap.ts.


73-75: Nice defensive programming with fallback UI.

Adding this guard clause prevents potential runtime errors when post data is unavailable, improving the resilience of the application. The fallback message is clear and appropriate.

.github/workflows/publish-docker.yml (1)

1-52: Well-structured Docker publishing workflow.

This GitHub Actions workflow is well-organized and properly configured for building and publishing Docker images to GHCR on version tag pushes. The semantic versioning tag strategy is particularly good for maintaining versioned Docker images.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 4-4: trailing spaces

(trailing-spaces)


[error] 9-9: trailing spaces

(trailing-spaces)

id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/vishalmakwana111/inbox-zero
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update Docker image path after merging.

As mentioned in the PR description, the image path should be updated to use the repository owner variable after merging.

-          images: ghcr.io/vishalmakwana111/inbox-zero
+          images: ghcr.io/${{ github.repository_owner }}/inbox-zero
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
images: ghcr.io/vishalmakwana111/inbox-zero
images: ghcr.io/${{ github.repository_owner }}/inbox-zero

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
.github/workflows/publish-docker.yml (1)

27-27: Update Docker image path after merging.

As noted in the PR description, once this lands, the image path should be parameterized to use the repository owner variable instead of the contributor’s namespace.

-          images: ghcr.io/vishalmakwana111/inbox-zero
+          images: ghcr.io/${{ github.repository_owner }}/inbox-zero
🧹 Nitpick comments (3)
.github/workflows/publish-docker.yml (3)

4-4: Remove trailing spaces.

YAMLlint flagged trailing spaces on this line—please remove them to ensure clean YAML syntax.

- name: Publish Docker Image␣
+ name: Publish Docker Image
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 4-4: trailing spaces

(trailing-spaces)


29-33: Clean up or fill out commented tag configurations.

There are several commented-out tag strategies (SHA, latest). Either remove these examples to declutter or enable the ones you intend to use.


49-51: Reconcile cache settings with no-cache.

You’ve configured both cache-from/cache-to and no-cache: true, which disables layer caching. If you intend to leverage GitHub Actions caching to speed up builds, remove the no-cache: true flag. Otherwise, drop the cache entries. For example:

-          cache-from: type=gha
-          cache-to: type=gha,mode=max
-          no-cache: true
+          cache-from: type=gha
+          cache-to: type=gha,mode=max
# remove `no-cache: true` to enable caching
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e2bb3a and 2b15101.

📒 Files selected for processing (2)
  • .github/workflows/publish-docker.yml (1 hunks)
  • docker-compose.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docker-compose.yml
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/publish-docker.yml

[error] 4-4: trailing spaces

(trailing-spaces)

🔇 Additional comments (1)
.github/workflows/publish-docker.yml (1)

1-3:

✅ Verification successful

Verify linked documentation exists.

The header references CICD_PLAN.md for details—ensure this file is present at the repository root and up to date.


🏁 Script executed:

#!/bin/bash
# Check for the presence of CICD_PLAN.md in the repo root
if ! fd --hidden --max-depth 1 'CICD_PLAN\.md'; then
  echo "Error: CICD_PLAN.md not found in the repository root."
  exit 1
fi
echo "CICD_PLAN.md exists."

Length of output: 94


CICD_PLAN.md presence verified
The workflow header in .github/workflows/publish-docker.yml references CICD_PLAN.md, and the file exists at the repository root. No further action required.

…shes and refine tagging logic for versioned releases
@vishalmakwana111
Copy link
Contributor Author

Just a quick note on the workflow triggers in .github/workflows/publish-docker.yml:

The workflow runs on pushes to main in addition to version tags (v*.*.*). This is intentional to ensure the latest Docker tag is always automatically updated to reflect the current state of the main development branch.

@vishalmakwana111 vishalmakwana111 changed the title Feat/docker publish ci feat: Add Docker build and publish CI for web app Apr 26, 2025
@elie222
Copy link
Owner

elie222 commented Apr 29, 2025

Thanks so much for this!

I will be looking at this PR later this week. There was also this PR, any overlap?
#417

@vishalmakwana111
Copy link
Contributor Author

vishalmakwana111 commented Apr 30, 2025

I was actually working on this feature but forgot to add a comment on that issue, which caused the overlap. I suggest reviewing both PRs and accepting whichever seems better.
I've tested it locally, and it's working fine

Latest Image : https://github.com/vishalmakwana111/inbox-zero/pkgs/container/inbox-zero

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants