- Published on
Docker Build Cache Can Hide Scheduled Posts
- Authors

- Name
- Mehdi Akiki
Article · Derived state
A cached Docker build can keep scheduled posts hidden after their date arrives. If the source files and build command are unchanged, the site-build layer may still contain yesterday's publication decision. Refresh that layer with an explicit build input while keeping earlier dependency work reusable.
Imagine a static site with an article scheduled for tomorrow morning. The source is already committed. Today's build leaves the article out, as it should. Tomorrow, the scheduled workflow builds the site again.
Docker reuses yesterday's site-build layer. The workflow finishes quickly. The deployed pages still leave out the article.
Time has changed, but the cache has no reason to rebuild the pages. This example describes a cache mistake, separate from the disk-space failure that recently affected this site.
An agent asked to speed up CI could miss the problem if it only looks at the shorter build time.
The date is part of the input
For many builds, unchanged source and dependencies are good reasons to reuse an earlier result. A scheduled article adds another input: the time when the build decides which pages to publish.
At 09:59, the article belongs in the future. At 10:00, it is due. The source file hasn't changed, yet the right output has.
The cache can't know that unless the build gives it a reason to run again. Docker's cache documentation explains that a cached RUN instruction doesn't automatically execute again because time has passed. If its relevant inputs still match, Docker can reuse the earlier result.
The pages depend on the date, but Docker has only seen the same files and command. It reuses the old result.
Other builds can have a similar problem. A command may fetch external data or install packages from a changing source. Decide when that result needs refreshing. An unchanged command does not always mean an unchanged answer.
For scheduled pages, start by finding where the date is used. Does the build choose the pages, generate the search index, or write the sitemap? All of those outputs need to use the intended publication time.
Rebuild the pages and keep the dependency cache
Disabling every cache would make the pages rebuild. It would also repeat work that hasn't changed, such as installing the same dependencies.
Keep that work reusable and make the site build run again when publication needs a fresh result. Here is an abbreviated Dockerfile fragment:
COPY package.json yarn.lock .yarnrc.yml ./
# A real project may also need package-manager patches here.
RUN yarn install --immutable
COPY . .
ARG PUBLICATION_BUILD_ID
RUN yarn build
The workflow supplies a different PUBLICATION_BUILD_ID for each publication build. Changing the argument prevents reuse of the following RUN result. The earlier dependency installation can still come from the cache.
The argument doesn't need to appear in the command text. Docker includes declared build arguments in the environment of following RUN instructions, as its build-caching reference explains.
The matching GitHub Actions input is also needed. This is an abbreviated build step; registry login, tags, cache settings, and the decision to build belong in the surrounding workflow:
- uses: docker/build-push-action@v6
with:
context: .
build-args: |
PUBLICATION_BUILD_ID=${{ github.run_id }}-${{ github.run_attempt }}
This site uses the workflow run ID and attempt number. The recorded Dockerfile and matching workflow show the complete version at an immutable revision. Those values tell Docker to rebuild; they do not tell the publication code what time it is. The code still compares article dates with the build's current time.
Another design could pass a fixed publication cutoff into the build. Rebuilding with the same cutoff would make it easier to reproduce which articles were included. That requires every place that filters articles to use the same value. Adding a variable without connecting it to those filters wouldn't solve the problem.
Ask the agent to explain the difference between making a build run again and choosing the time that build uses. The two decisions are related, but they are separate parts of the fix.
Look at the pages the build produced
Check a build before the article's timestamp and another at or after it. For an illustrative post due at 10:00 UTC, the intended results are:
| Build cutoff | Article state | Intended output |
|---|---|---|
| 09:59:59 UTC | Approved and not a draft | Hidden |
| 10:00:00 UTC | Approved and not a draft | Included |
| 10:00:00 UTC | Still a draft | Hidden |
| 10:00:00 UTC | Still unreviewed | Hidden |
These are constructed expectations, not a claim that this table came from a new cache experiment. Verify the date rule separately from whether Docker reran the build command. A changing argument can force work to run while a faulty visibility filter still produces the wrong pages.
Then look beyond the blog list. Search might expose an article that the list hides. The sitemap might name a page that wasn't generated. All the places that show articles need to agree.
For a release, open the live page too. A new image in the registry still has to reach the server and start serving requests. If the image contains the right page but the website doesn't, investigate deployment before changing the build cache again.
That gives the agent a useful order of questions. Did the site build run? Does its output contain the due article? Did that output reach the server? Which version is the server serving now? The deployment postmortem follows a different failure: a correct new image that the server could not unpack.
Explain why each cached result is safe to reuse
A speed report should say more than “the build is faster.” Ask which work was skipped and why its old result is still valid.
Unchanged dependency installation has one answer. Pages that depend on today's date have another. Treating them separately keeps useful caching without serving yesterday's publication decision.
For the next scheduled run, the page build needs fresh input when an article becomes due. If the live site already has every due article, the publication check can avoid a deployment altogether. Each saved step then has a reason a reviewer can check.