Skip to content

The Dockerfile now uses a multi-stage build:#25

Merged
calj merged 1 commit intomasterfrom
feat/dockerfile
Mar 8, 2026
Merged

The Dockerfile now uses a multi-stage build:#25
calj merged 1 commit intomasterfrom
feat/dockerfile

Conversation

@calj
Copy link
Contributor

@calj calj commented Mar 8, 2026

  1. builder stage (golang:1.25-alpine) — installs build-base, downloads dependencies, and compiles the binary.

  2. Runtime stage (alpine:3.21) — a minimal image with only ca-certificates and the compiled binary. No Go toolchain, no build tools.

This will produce a significantly smaller final image since the Go SDK, source code, and build dependencies are all left behind in the builder stage.

Summary by CodeRabbit

  • Chores
    • Added a database file to the repository ignore list to keep local data out of version control.
    • Improved container image build: switched to a multi-stage build for smaller runtime images, ensured runtime includes TLS certificates, copied the compiled binary into the final image, exposed port 8080, and added a separate worker command.

@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

📝 Walkthrough

Walkthrough

Adds nitewatch.db to .gitignore and converts the Dockerfile to a multi-stage build: separate builder and final runtime stages, copies the built binary into the runtime image, exposes port 8080, and adds a CMD ["worker"] alongside ENTRYPOINT ["nitewatch"].

Changes

Cohort / File(s) Summary
Version Control
/.gitignore
Adds nitewatch.db to ignored files (alongside existing entries).
Container Build Configuration
Dockerfile
Converts to multi-stage build (AS builder + final alpine:3.23 stage); keeps Go build steps with ARG VERSION and ldflags; installs ca-certificates only in final stage; copies built binary from builder to final image; adds CMD ["worker"], ENTRYPOINT ["nitewatch"], and EXPOSE 8080.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 I built a tiny image in the sun,
Stashed the DB where it won't be spun,
Builder hops, then copies through—
A lean runner wakes anew,
Hooray, the container's fun!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: converting the Dockerfile to use a multi-stage build, which is the primary modification in this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/dockerfile

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Dockerfile (1)

12-12: ⚠️ Potential issue | 🟠 Major

Update .dockerignore to exclude all local runtime artifacts.

.dockerignore exists but is incomplete. While .gitignore excludes config.yaml, nitewatch, nitewatch.sqlite, and nitewatch.db, these patterns are missing from .dockerignore. During COPY . ., Docker respects .dockerignore (not .gitignore), so these local runtime artifacts can still end up in the build context. Add the missing patterns to .dockerignore.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 12, The Dockerfile uses COPY . . which pulls the build
context from the repo; update .dockerignore to exclude local runtime artifacts
so they are not copied. Add the missing patterns config.yaml, nitewatch,
nitewatch.sqlite, and nitewatch.db to .dockerignore (one per line or appropriate
glob patterns) so those files/directories are excluded from the Docker build
context referenced by COPY . ..
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 16-20: The final Dockerfile runs /usr/local/bin/nitewatch as root;
create and switch to a non-root user in the runtime stage: add a system
user/group (e.g., "app" or "nitewatch"), ensure ownership of the copied binary
(/usr/local/bin/nitewatch) and any runtime dirs are chowned to that user, and
set USER to that non-root account so the nitewatch process from the builder
stage no longer runs as root.

---

Outside diff comments:
In `@Dockerfile`:
- Line 12: The Dockerfile uses COPY . . which pulls the build context from the
repo; update .dockerignore to exclude local runtime artifacts so they are not
copied. Add the missing patterns config.yaml, nitewatch, nitewatch.sqlite, and
nitewatch.db to .dockerignore (one per line or appropriate glob patterns) so
those files/directories are excluded from the Docker build context referenced by
COPY . ..

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1bfe1661-6c95-45c4-98d2-c7e6e3fbe8ce

📥 Commits

Reviewing files that changed from the base of the PR and between 49e36ac and 5480dce.

📒 Files selected for processing (2)
  • .gitignore
  • Dockerfile

Comment on lines +16 to +20
FROM alpine:3.23

RUN apk add --no-cache ca-certificates

COPY --from=builder /usr/local/bin/nitewatch /usr/local/bin/nitewatch
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Run the final image as a non-root user.

The runtime stage never sets USER, so nitewatch runs as root. For a network-facing process, that is unnecessary privilege if the process is compromised.

Suggested hardening
 FROM alpine:3.23
 
 RUN apk add --no-cache ca-certificates
+RUN addgroup -S nitewatch && adduser -S -G nitewatch nitewatch
 
-COPY --from=builder /usr/local/bin/nitewatch /usr/local/bin/nitewatch
+COPY --from=builder --chown=nitewatch:nitewatch /usr/local/bin/nitewatch /usr/local/bin/nitewatch
+USER nitewatch
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 16 - 20, The final Dockerfile runs
/usr/local/bin/nitewatch as root; create and switch to a non-root user in the
runtime stage: add a system user/group (e.g., "app" or "nitewatch"), ensure
ownership of the copied binary (/usr/local/bin/nitewatch) and any runtime dirs
are chowned to that user, and set USER to that non-root account so the nitewatch
process from the builder stage no longer runs as root.

1. builder stage (golang:1.25-alpine) — installs build-base, downloads
   dependencies, and compiles the binary.

2. Runtime stage (alpine:3.21) — a minimal image with only ca-certificates
   and the compiled binary. No Go toolchain, no build tools.

This will produce a significantly smaller final image since the Go SDK,
source code, and build dependencies are all left behind in the builder
stage.
@calj calj force-pushed the feat/dockerfile branch from 5480dce to 3d70ea7 Compare March 8, 2026 08:23
Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Line 1: The PR description and the Dockerfile disagree on the Go base image;
the Dockerfile uses the Dockerfile line "FROM golang:1.24-alpine" while the PR
text mentions "golang:1.25-alpine". Update the PR description to state the exact
intended Go version (e.g., 1.24 or 1.25) to match the Dockerfile, or if you
intended to change the Dockerfile instead, update the Dockerfile's FROM line
accordingly and note that change in the PR description so both sources are
consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf218c23-3b30-4628-8d26-e37f0913be0f

📥 Commits

Reviewing files that changed from the base of the PR and between 5480dce and 3d70ea7.

📒 Files selected for processing (2)
  • .gitignore
  • Dockerfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • .gitignore

@@ -1,6 +1,6 @@
FROM golang:1.24-alpine
FROM golang:1.24-alpine AS builder
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if golang:1.24-alpine exists on Docker Hub
curl -s "https://hub.docker.com/v2/repositories/library/golang/tags/1.24-alpine" | jq '.name // "NOT FOUND"'

Repository: layer-3/nitewatch

Length of output: 74


🏁 Script executed:

#!/bin/bash
# Check if golang:1.25-alpine exists on Docker Hub
curl -s "https://hub.docker.com/v2/repositories/library/golang/tags/1.25-alpine" | jq '.name // "NOT FOUND"'

Repository: layer-3/nitewatch

Length of output: 74


Clarify Go version choice in PR description.

The Dockerfile specifies golang:1.24-alpine, but the PR description mentions golang:1.25-alpine. Both tags exist and are valid. Please update the PR description to match the intended version or clarify if this is an intentional downgrade.

🧰 Tools
🪛 Trivy (0.69.2)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 1, The PR description and the Dockerfile disagree on the
Go base image; the Dockerfile uses the Dockerfile line "FROM golang:1.24-alpine"
while the PR text mentions "golang:1.25-alpine". Update the PR description to
state the exact intended Go version (e.g., 1.24 or 1.25) to match the
Dockerfile, or if you intended to change the Dockerfile instead, update the
Dockerfile's FROM line accordingly and note that change in the PR description so
both sources are consistent.

@calj calj merged commit 435cf72 into master Mar 8, 2026
9 checks passed
@calj calj deleted the feat/dockerfile branch March 8, 2026 13:42
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.

1 participant