Skip to content

Update Dockerfile https://github.com/firepress-org/ghostfire/issues/601#602

Closed
pascalandy wants to merge 2 commits intomasterfrom
edge_659
Closed

Update Dockerfile https://github.com/firepress-org/ghostfire/issues/601#602
pascalandy wants to merge 2 commits intomasterfrom
edge_659

Conversation

@pascalandy
Copy link

@pascalandy pascalandy commented Jun 13, 2025

Summary by CodeRabbit

  • Refactor
    • Streamlined the Docker build process for the Ghost application, reducing complexity and modernizing the setup for improved reliability and security.
    • Switched to a minimal runtime image and a non-root user for enhanced security.
    • Simplified health checks and entrypoint behaviour.
    • Updated environment configuration and removed unnecessary dependencies for a leaner image.

@coderabbitai
Copy link

coderabbitai bot commented Jun 13, 2025

Walkthrough

The Dockerfile for the Ghost application was refactored from a multi-stage build with several custom layers to a streamlined two-stage build. The new process uses an Alpine-based Node.js builder and a runtime stage based on the same image, simplifies dependency management, removes privilege-dropping tools, and sets up a non-root runtime user with a direct Node.js entrypoint.

Changes

File(s) Change Summary
v5/Dockerfile Simplified from multi-stage (mynode, debug, builder, final) to two-stage (builder, runtime); updated base images, reorganized build arguments, installed dependencies via apk, enabled Yarn via Corepack, removed legacy layers and tools, set environment variables, improved user setup, added healthcheck, and simplified entrypoint.

Sequence Diagram(s)

sequenceDiagram
    participant Builder as Builder Stage (Alpine Node)
    participant Runtime as Runtime Stage (Alpine Node)
    participant Ghost as Ghost App

    Builder->>Builder: Install build & runtime dependencies
    Builder->>Builder: Enable Yarn via Corepack
    Builder->>Builder: Install Ghost CLI & Ghost (MySQL)
    Builder->>Builder: Run npm audit fix & clean caches
    Builder->>Runtime: Copy Ghost installation with ownership

    Runtime->>Runtime: Set environment and non-root user
    Runtime->>Ghost: Run node current/index.js
    Ghost->>Ghost: Serve on port 2368
    Runtime->>Runtime: Healthcheck via HTTP 200 on port 2368
Loading

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e9d811 and b736730.

📒 Files selected for processing (1)
  • v5/Dockerfile (1 hunks)
🧰 Additional context used
🪛 Hadolint (2.12.0)
v5/Dockerfile

[warning] 44-44: Pin versions in apk add. Instead of apk add <package> use apk add <package>=<version>

(DL3018)


[info] 44-44: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 79-79: Last USER should not be root

(DL3002)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_edge
🔇 Additional comments (19)
v5/Dockerfile (19)

3-5: Section headers are purely organizational and don’t require changes.


7-14: Well-defined CI-visible build-time arguments
Defining ARG APP_NAME, VERSION, GITHUB_USER and related values upfront makes the build reproducible and self-documenting. Everything looks correctly quoted and sensible for downstream stages.


16-19: Image-specific build parameters look solid
Explicitly pinning GHOST_CLI_VERSION, NODE_VERSION, BASE_OS and defaulting USER to node is clear and avoids ambiguity.


22-30: Build-package arguments are properly factored out
Listing each Alpine package as its own ARG makes it easy to override or pin later in CI. This separation is clean and maintainable.


32-35: Build stage declaration is correct
Switching to node:${NODE_VERSION} as the builder stage is appropriate and straightforward.


41-41: Re-declaration of build-time ARGS
Re-declaring only the ARGS you need in the builder stage ensures no unnecessary args are carried forward.


49-50: Enable Yarn via Corepack
Using Corepack to activate Yarn@stable is the modern approach in Node 20. Good to see the builder leveraging the bundled toolchain.


58-60: Create and chown Ghost directories before dropping privileges
The mkdir -p and chown pattern ensures the non-root user can write to the install and content paths. Nicely done.


62-64: Privilege drop and working directory set correctly
Switching to USER ${USER} followed by WORKDIR ${GHOST_INSTALL} matches best practices.


66-71: Ghost CLI and core installation
Chaining npm i -g ghost-cli with ghost install in a single RUN optimizes layer usage. The flags (--no-setup, --no-prompt) are appropriate for CI builds.


74-76: CVE mitigation and cache cleanup
Running npm audit fix, yarn cache clean, and npm cache clean --force helps shrink the layer and remove dev dependencies. This is well-sequenced.


79-81: Revert to root to purge build dependencies
Dropping the .build-deps virtual package and clearing all caches keeps the final builder image lean. Correct use of root here.

🧰 Tools
🪛 Hadolint (2.12.0)

[warning] 79-79: Last USER should not be root

(DL3002)


86-87: Runtime stage declaration
A second stage from the same base image keeps the runtime footprint minimal and consistent.


97-99: Runtime environment variables are set correctly
Defining GHOST_INSTALL, GHOST_CONTENT, and NODE_ENV=production in the runtime image matches the builder.


101-102: Persistent volume for Ghost content
Reintroducing VOLUME ["/opt/ghost/content"] ensures that user data isn’t lost on container recreation. Well aligned with Ghost best practices.


105-105: Copy application from builder with correct ownership
Using --chown=${USER}:${USER} on the COPY instruction secures file permissions for the runtime user.


107-108: Final user switch and port exposure
Switching back to ${USER} and exposing port 2368 is exactly what Ghost needs.


110-113: Healthcheck implemented without a shell
A Node one-liner is an effective way to avoid shell overhead and meets Docker’s recommendations for healthchecks.


114-114: Direct entrypoint to Ghost
Pointing ENTRYPOINT at node current/index.js simplifies the container startup and removes the need for wrapper scripts.


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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.

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

@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: 6

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 173358f and 0e9d811.

📒 Files selected for processing (1)
  • v5/Dockerfile (1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
v5/Dockerfile

[LOW] 70-70: Ensure the base image uses a non latest version tag

(CKV_DOCKER_7)

🪛 Hadolint (2.12.0)
v5/Dockerfile

[warning] 34-34: Pin versions in apk add. Instead of apk add <package> use apk add <package>=<version>

(DL3018)


[warning] 62-62: Last USER should not be root

(DL3002)


[warning] 70-70: Always tag the version of an image explicitly

(DL3006)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_edge

v5/Dockerfile Outdated
Comment on lines +34 to +37
RUN apk update && apk upgrade --no-cache \
&& apk add --no-cache --virtual .build-deps \
g++ make python3 pkgconfig libc6-compat vips-dev \
&& apk add --no-cache bash curl tzdata
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider pinning package versions for reproducible builds
Using apk add without explicit version pins can lead to non-reproducible images when upstream packages update. You may define and use versioned args or specify package=version.

🧰 Tools
🪛 Hadolint (2.12.0)

[warning] 34-34: Pin versions in apk add. Instead of apk add <package> use apk add <package>=<version>

(DL3018)

🤖 Prompt for AI Agents
In v5/Dockerfile around lines 34 to 37, the apk packages are installed without
specifying versions, which can cause non-reproducible builds. To fix this, pin
the versions of each package by either defining ARG variables for the package
versions or specifying the exact version with the package name (e.g.,
package=version) in the apk add commands. This ensures consistent and
reproducible Docker images.

@pascalandy pascalandy closed this Jun 13, 2025
@pascalandy pascalandy deleted the edge_659 branch June 13, 2025 15:02
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