A Simpler Way to Patch Ghost Docker Images

Previously, I wrote about adding server-side syntax highlighting in Ghost. To do this, I had to make some changes to the Ghost code. Although there's a way to deploy those changes to a Ghost instance that's installed on a server, there's no clear way to deploy it as a Docker image (which is what I use). So I have to build my own Docker image to use it.

However, this makes it difficult to upgrade the Ghost version. Whenever I want to upgrade, I would have to merge the git tag to my fork, resolve the merge conflicts (which almost always happens because I edited the package.json), build a new zip file, build a new image using that zip file, and then use the new image.

The Ghost code that I modified is directly written in JS, and not generated from Typescript or anything else. If I didn't install any extra packages in the fork, I could generate a patch file from my git branch and just apply it to the files in the Docker image. As long as the lines I changed don't conflict with any new changes, the patch might work for a long time, and I would only need to update the FROM instruction to upgrade the Ghost version.

So I generated a patch using git diff v5.89.0...HEAD in the fork branch, replaced the paths to match the image's filesystem (/ghost/core/core/server/ -> /current/core/server/), and wrote a simple Dockerfile to apply it:

FROM ghost:5.89.0

COPY ./ghost.patch /var/lib/ghost/

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends patch; \
    cd /var/lib/ghost; \
    patch -p1 < ghost.patch; \
    apt-get remove -y patch; \
    rm -rf /var/lib/apt/lists/*;

You can check out the changes in the patch here.

To avoid installing extra packages, I moved the syntax highlighting logic to a separate service, and let the Ghost server call that service instead. I wrote a very simple Hono app to expose the previous postprocessing function as an API.