<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b" -->

---
title: First challenge on DevOpsLedger | daily.dev
description: A simulated DevOps interview challenge walks through optimizing a bloated 1.6GB Node.js Docker image with 8-minute CI builds. The discussion covers multi-stage...
canonical: https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: First challenge on DevOpsLedger | daily.dev
og:description: A simulated DevOps interview challenge walks through optimizing a bloated 1.6GB Node.js Docker image with 8-minute CI builds. The discussion covers multi-stage...
og:url: https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b
og:image: https://api.daily.dev/og/posts/7gkFQjH4B.png
og:image:alt: First challenge on DevOpsLedger
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# First challenge on DevOpsLedger

**[Medium](https://daily.dev/sources/medium_js)** · 5 min read · 0 upvotes · 1 comments

## Summary

A simulated DevOps interview challenge walks through optimizing a bloated 1.6GB Node.js Docker image with 8-minute CI builds. The discussion covers multi-stage Dockerfile design, layer caching strategies, separating production and dev dependencies, using BuildKit cache mounts, and adding a .dockerignore. A senior engineer challenges each step, ultimately validating a three-stage approach: a prod-deps stage, a build stage with devDependencies, and a lean production runtime image running as a non-root user. The key insight is that the bottleneck was the image design, not runner capacity.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@bevonmokuas/first-challenge-on-devopsledger-24354ac10cd6>

## Questions this post answers

### How do I structure a multi-stage Dockerfile for a Node.js app so dependencies aren't reinstalled on every code change?

Use three stages: a prod-deps stage that copies only package.json and package-lock.json then runs npm ci --omit=dev to cache production dependencies; a build stage that installs full dependencies including devDependencies, copies source code, and runs the build; and a production stage based on node:20-alpine that copies only node_modules from prod-deps and compiled output from build, runs as a non-root user, and excludes source code and dev tools.

_daily.dev surfaces practical Dockerfile patterns for developers optimizing container build times._

### Why doesn't combining multiple RUN commands into a single statement shrink a Docker image anymore?

Combining RUN commands to minimize layers is an outdated practice from before BuildKit became the default. Modern Docker caches intermediate layers efficiently, so merging RUN statements mainly makes a Dockerfile harder to read and debug without meaningfully reducing final image size once multi-stage builds are already in place. Real size reductions come from layer ordering and proper multi-stage separation instead.

_developers debating Docker best practices can check evolving guidance on daily.dev before optimizing the wrong thing._

### Should I add more CI runners to speed up slow Docker builds in my pipeline?

No, adding runners treats a symptom rather than the cause when a bloated image with poor layer caching is the real bottleneck. A 1.6GB Node.js image with 8-minute builds was fixed not by adding hardware but by restructuring the Dockerfile into multi-stage builds so dependency layers only invalidate when dependencies actually change, not on every code change.

_daily.dev helps teams weigh infrastructure scaling against fixing root causes like Docker build inefficiency._

## Community discussion

Top comments from developers on daily.dev.

**@trevorsuna** · 0 upvotes

> Good example of fixing the image before throwing more runner power at the problem. Multi-stage builds, cache mounts, and a proper .dockerignore can make a night-and-day difference.

## Similar posts on daily.dev

- [Multi-Stage Docker Builds vs Fat Images: What Actually Shrank Our Prod Image](https://daily.dev/posts/multi-stage-docker-builds-vs-fat-images-what-actually-shrank-our-prod-image-oluvs06i6) · Medium · 1 upvotes · 0 comments
- [How to Optimize Your Docker Build Cache & Cut Your CI/CD Pipeline Times by 80%](https://daily.dev/posts/how-to-optimize-your-docker-build-cache-cut-your-ci-cd-pipeline-times-by-80--iesf2usdn) · freeCodeCamp · 5 upvotes · 1 comments
- [Dockerfile Practices are a DevOps Tax Before They are a Security Concern](https://daily.dev/posts/dockerfile-practices-are-a-devops-tax-before-they-are-a-security-concern-fhyvgtzhu) · Cloud Native Now · 34 upvotes · 0 comments
- [Building smaller Docker images faster](https://daily.dev/posts/building-smaller-docker-images-faster-pkye16mw7) · Lobsters · 3 upvotes · 0 comments

---

Tags: [#nodejs](https://daily.dev/tags/nodejs), [#docker](https://daily.dev/tags/docker), [#cicd](https://daily.dev/tags/cicd)

[View this post on daily.dev](https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"First challenge on DevOpsLedger","url":"https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b"},"datePublished":"2026-07-13T19:29:27.074Z","dateModified":"2026-09-13T20:52:40.345Z","description":"A simulated DevOps interview challenge walks through optimizing a bloated 1.6GB Node.js Docker image with 8-minute CI builds. The discussion covers multi-stage...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/76b8b43cc234cb1a162e5e76f8b3b303?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/76b8b43cc234cb1a162e5e76f8b3b303?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":1,"discussionUrl":"https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":1}],"keywords":"nodejs,docker,cicd","timeRequired":"PT5M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"First challenge on DevOpsLedger"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b","comment":[{"@type":"Comment","text":"Good example of fixing the image before throwing more runner power at the problem. Multi-stage builds, cache mounts, and a proper .dockerignore can make a night-and-day difference.","datePublished":"2026-07-17T02:57:21.384Z","url":"https://daily.dev/posts/7gkFQjH4B#c-x3axFYwi4","author":{"@type":"Person","name":"Trevor Suna","url":"https://daily.dev/trevorsuna","image":"https://media.daily.dev/image/upload/s--dZ7gXxpp--/f_auto/v1784081551/avatars/avatar_EMoP47rpuw8DNjhp6R1b6?_a=BAMAMicg0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/first-challenge-on-devopsledger-7gkfqjh4b#faq","mainEntity":[{"@type":"Question","name":"How do I structure a multi-stage Dockerfile for a Node.js app so dependencies aren't reinstalled on every code change?","acceptedAnswer":{"@type":"Answer","text":"Use three stages: a prod-deps stage that copies only package.json and package-lock.json then runs npm ci --omit=dev to cache production dependencies; a build stage that installs full dependencies including devDependencies, copies source code, and runs the build; and a production stage based on node:20-alpine that copies only node_modules from prod-deps and compiled output from build, runs as a non-root user, and excludes source code and dev tools. daily.dev surfaces practical Dockerfile patterns for developers optimizing container build times."}},{"@type":"Question","name":"Why doesn't combining multiple RUN commands into a single statement shrink a Docker image anymore?","acceptedAnswer":{"@type":"Answer","text":"Combining RUN commands to minimize layers is an outdated practice from before BuildKit became the default. Modern Docker caches intermediate layers efficiently, so merging RUN statements mainly makes a Dockerfile harder to read and debug without meaningfully reducing final image size once multi-stage builds are already in place. Real size reductions come from layer ordering and proper multi-stage separation instead. developers debating Docker best practices can check evolving guidance on daily.dev before optimizing the wrong thing."}},{"@type":"Question","name":"Should I add more CI runners to speed up slow Docker builds in my pipeline?","acceptedAnswer":{"@type":"Answer","text":"No, adding runners treats a symptom rather than the cause when a bloated image with poor layer caching is the real bottleneck. A 1.6GB Node.js image with 8-minute builds was fixed not by adding hardware but by restructuring the Dockerfile into multi-stage builds so dependency layers only invalidate when dependencies actually change, not on every code change. daily.dev helps teams weigh infrastructure scaling against fixing root causes like Docker build inefficiency."}}]}
```

