HomeReadTools deskBuild your Docker image once: a CI pattern review for solo founders
Tools·Jun 21, 2026

Build your Docker image once: a CI pattern review for solo founders

A founder's GitHub Actions pipeline builds their Next.js app twice. We analyze the 'build-once-test-artifact' pattern, which saves CI minutes and de-risks deployments by testing the final container.…

A founder's GitHub Actions pipeline builds their Next.js app twice. We analyze the 'build-once-test-artifact' pattern, which saves CI minutes and de-risks deployments by testing the final container.

THE ANSWER UP FRONT

For developers shipping containerized applications, the correct pattern is to build your deployable artifact (the Docker image) exactly once, then run all subsequent checks against that immutable artifact. The alternative, building the application separately for testing and then again for containerization, is a common but flawed approach that introduces risk and wastes CI resources. This is especially true for Next.js developers using GitHub Actions, where default configurations can easily lead to this anti-pattern. If you are building and deploying containers, adopt the 'build-once' pattern. If you aren't using containers, your pipeline has different concerns, but the principle of testing your final artifact still holds.

METHODOLOGY

This v0 review analyzes a common CI/CD challenge using a public request for comment as its source. Our analysis is based on the pipeline structure detailed by user Particular-Run1230 on Reddit on June 17, 2024. The review covers the two described pipeline configurations for a Next.js application using GitHub Actions, Playwright for end-to-end testing, and Docker for containerization. We evaluate the trade-offs based on established DevOps principles of artifact management and immutable infrastructure.

This review does not include independent performance benchmarks. All claims of improved efficiency or cost savings are logical deductions from the described patterns, not measured results. The analysis is specific to the Next.js and Docker stack but the principles are broadly applicable. This v0 review draws on the founder's published description at https://www.reddit.com/r/devops/comments/1u9fpvs/am_i_wasting_ci_time_by_building_my_application/; independent benchmarks are pending.

WHAT IT DOES

The user's post outlines two distinct approaches to a CI/CD pipeline.

The 'build-twice' anti-pattern

The original pipeline follows a sequential logic that results in redundant work:

  1. Lint & Typecheck: Static analysis runs on the source code.
  2. Playwright E2E Tests: A dedicated job checks out the code, runs npm ci, builds the Next.js application (next build), starts the server, and runs tests against it.
  3. Docker Build: A separate job builds the final Docker image. This step also runs npm ci and next build inside the Docker build context, creating a second, distinct build artifact.
  4. Scan & Deploy: The newly built image is scanned with Trivy and deployed.

The critical flaw is that the application is built twice. The artifact validated by the Playwright tests is not the same artifact that gets deployed.

The 'build-once-test-artifact' solution

The proposed alternative pipeline correctly treats the Docker image as the canonical build artifact:

  1. Lint & Typecheck: Same as before.
  2. Docker Build: The pipeline builds the production Docker image immediately after static checks pass. This becomes the single source of truth for the rest of the pipeline.
  3. Playwright E2E Tests: Tests run against the application inside a container started from the image built in the previous step.
  4. Scan & Deploy: The exact same image that was just tested is scanned with Trivy and deployed.

This revised structure ensures that every test and validation step operates on the final, deployable unit.

WHAT'S INTERESTING / WHAT'S NOT

The most interesting aspect here is the principle of testing the thing you will actually ship. When the Playwright tests run against a next build in a generic CI runner, you are testing the application code in the CI environment. When you later build a Docker image, you introduce dozens of new variables: the base image OS, system libraries, environment variables, and Dockerfile instructions. A discrepancy between these two environments is a classic source of "it worked in CI but broke in production" errors.

By building the Docker image first and testing against it, you eliminate this entire class of bugs. The test suite validates the complete package, not just the application code in isolation. The primary benefit is not just saving CI minutes, but de-risking the deployment itself.

What's not interesting is the novelty of the idea. This is a standard best practice in mature software delivery organizations. However, the Reddit post demonstrates that it is not an obvious default for solo founders or smaller teams. The tooling (like GitHub Actions) provides powerful primitives but doesn't always guide users to the most robust patterns. This gap between tooling primitives and best-practice implementation is a persistent source of friction for developers who are not DevOps specialists.

PRICING

This is a methodology, not a commercial tool, so there is no direct price. The cost is measured in CI/CD provider minutes (e.g., from GitHub Actions). The 'build-once' pattern is designed to reduce this cost by eliminating a redundant, often slow, application build step. For a Next.js application, this could save several minutes per pipeline run. On a project with frequent commits, these savings can become significant over time.

Pricing snapshot taken June 21, 2024, based on standard CI provider pay-per-minute models.

VERDICT

The 'build-once-test-artifact' pattern is the correct choice for any team deploying applications via containers. It improves pipeline efficiency by removing redundant build steps, which saves time and money. More importantly, it significantly reduces deployment risk by ensuring that end-to-end tests validate the exact artifact that will be shipped to production. The 'build-twice' approach is an anti-pattern that creates a dangerous gap between testing and deployment environments.

For the Next.js developer in the source signal, the proposed change is a clear and unambiguous improvement. Our recommendation is to refactor the pipeline to build the Docker image once and run all subsequent stages against that immutable artifact.

WHAT WE'D TEST NEXT

For a v2 of this analysis, we would move from principles to measurement.

  1. Benchmark Pipeline Duration: Implement both pipeline patterns for a moderately complex, open-source Next.js application on GitHub Actions. We would measure the wall-clock time difference for a typical pull request workflow.
  2. Quantify Cost Savings: Using the duration benchmarks, calculate the concrete cost savings based on GitHub's public pricing for hosted runners over 100 and 1,000 pipeline runs.
  3. Introduce Environment Drift: Construct a test case where a subtle difference between the CI runner environment and the Docker container environment (e.g., a missing system dependency or a different Node.js patch version) causes the 'build-twice' pipeline to pass tests but fail on deployment, while the 'build-once' pipeline correctly catches the error in the testing stage.

The investor read

This pattern analysis highlights a key market dynamic: the friction inherent in using generic CI/CD tools versus framework-aware platforms. The fact that a developer must manually discover and implement this best practice on GitHub Actions is a product gap. This is the gap filled by platforms like Vercel (for Next.js) or Render, which make the 'build-once' pattern the invisible, correct default. For investors, this signals the durable advantage of opinionated platforms that abstract away CI/CD complexity for specific ecosystems. Any tool claiming to improve 'developer experience' on raw CI/CD must be evaluated on how well it automates these kinds of best-practice patterns. The continued prevalence of these questions indicates a large, underserved market segment that prioritizes working defaults over configurable primitives.

Pull quote: “The primary benefit is not just saving CI minutes, but de-risking the deployment itself.”

Sources · how we verified
  1. Am I wasting CI time by building my application twice?

Every claim ties to a primary source. See our methodology.

Reported by the Riley desk on Founderr Pulse’s Tools beat. Every factual claim is tied to a primary source and linked; anything that can’t be stood up doesn’t run. Founderr (RIKHATH LLC) is the accountable publisher and corrects in place. How we work · About · File a correction.
R
Riley

The Riley desk covers tools — what founders are building with, switching to, and abandoning. Every claim is sourced and linked. Operated by Founderr (RIKHATH LLC) See the desk →

Founderr Pulse — free & independent. The desk for people who build & back.