<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rishav Raj</title>
    <description>The latest articles on DEV Community by Rishav Raj (@rishav_raj_4566509aaef548).</description>
    <link>https://dev.to/rishav_raj_4566509aaef548</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3730384%2F206c901b-e96c-4ce8-a877-045518c2b384.png</url>
      <title>DEV Community: Rishav Raj</title>
      <link>https://dev.to/rishav_raj_4566509aaef548</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rishav_raj_4566509aaef548"/>
    <language>en</language>
    <item>
      <title>Dockerfile: From Basic to Production, Step by Step</title>
      <dc:creator>Rishav Raj</dc:creator>
      <pubDate>Sat, 24 Jan 2026 15:48:46 +0000</pubDate>
      <link>https://dev.to/rishav_raj_4566509aaef548/dockerfile-from-basic-to-production-step-by-step-2bjk</link>
      <guid>https://dev.to/rishav_raj_4566509aaef548/dockerfile-from-basic-to-production-step-by-step-2bjk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Dockerfile Evolution: From Basic Containers to Production-Ready Supply-Chain-Aware Builds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article explains how a Dockerfile evolves step by step to meet real production, security, and portability requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 — Basic Dockerfile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the application inside a container with minimum effort and validate runtime behavior.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uses a single-stage Dockerfile with an official base image and application code copied directly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installs dependencies and runs the application in the same image without build-time separation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Focuses only on correctness, not image size, security posture, or long-term maintainability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Suitable for learning, prototyping, or validating that the application runs inside containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lacks optimization, reproducibility, and security hardening required for production workloads.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "index.js"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note for beginners&lt;/strong&gt;: The * is a wildcard. It means all files starting with &lt;strong&gt;package&lt;/strong&gt; and ending with &lt;strong&gt;.json&lt;/strong&gt; will be copied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 — Optimized Base Image (Slim / Alpine)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reduce image size and remove unnecessary operating system components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This layer focuses on reducing image size by switching from a full OS image to Alpine or Slim variants.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The application runtime remains the same while unnecessary system packages are removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Smaller images lead to faster pull times and reduced storage usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build speed and startup time improve without changing application logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This layer introduces optimization without increasing Dockerfile complexity.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Layer 3 — Multi-Stage Build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use multi-stage builds to separate build and runtime concerns while applying basic production-grade Dockerfile practices.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This layer is useful when the application has a build or compilation step before runtime, such as TypeScript, Java, or Python packaging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-stage builds isolate compilers and build tools from the runtime image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime images include only build artifacts and required production dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic production practices like version pinning, non-root execution, and health checks are introduced.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This layer represents a stable mid-level production Dockerfile without advanced security or supply-chain tooling.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18.19.0-alpine AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM node:18.19.0-alpine
WORKDIR /app

COPY --from=builder /app/dist ./dist

EXPOSE 3000

RUN addgroup -S app &amp;amp;&amp;amp; adduser -S app -G app
USER app

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', res =&amp;gt; process.exit(res.statusCode === 200 ? 0 : 1)).on('error', () =&amp;gt; process.exit(1))"

CMD ["node", "dist/index.js"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Layer 4 — Distroless + Reproducible Build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a secure, minimal, reproducible container with production hygiene, metadata, healthcheck, non-root execution, and pinned versions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uses distroless images to remove shells, package managers, and unnecessary OS utilities, keeping the runtime minimal and secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Base images pinned using SHA digests and dependencies locked via package-lock.json for fully reproducible builds across environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Includes LABEL metadata like maintainer name, email, version, and description for traceability and legacy maintenance support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creates a non-root user and adds a basic HEALTHCHECK to improve container safety and orchestrator readiness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copies only runtime artifacts; development tools, compilers, and unnecessary packages remain in the build stage, reducing attack surface.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Distroless images are not always smaller in size.&lt;br&gt;
Sometimes they look bigger because the full runtime and required dependencies are bundled.&lt;/p&gt;

&lt;p&gt;The main purpose of distroless is &lt;strong&gt;better security, reproducibility, and a reduced attack surface,&lt;/strong&gt; not just image size optimization.&lt;br&gt;
For deeper understanding, refer to the official Docker documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18.19.0-alpine@sha256:0085670310d2879621f96a4216c893f92e2ded827e9e6ef8437672e1bd72f437 AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM gcr.io/distroless/nodejs:18@sha256:b534f9b5528e69baa7e8caf7bcc1d93ecf59faa15d289221decf5889a2ed3877
WORKDIR /app

ARG APP_VERSION=1.0.0
LABEL maintainer="Anonymous &amp;lt;abc@example.com&amp;gt;" \
      description="Production-ready Node.js app with distroless and reproducible build" \
      version="$APP_VERSION"

COPY --from=builder /app/dist ./dist

EXPOSE 3000
USER nonroot

HEALTHCHECK CMD node -e "process.exit(0)"

CMD ["dist/index.js"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Layer 5 — Production-Ready Multi-Arch Distroless Build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a secure, minimal, reproducible, and portable container for multiple architectures with proper metadata and hygiene.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uses distroless images to remove shells, package managers, and unnecessary OS utilities, keeping the runtime minimal and secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Builds multi-architecture images (amd64 + arm64) ensuring portability across cloud, ARM servers, and heterogeneous infrastructures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Base images pinned via SHA and dependencies locked through package-lock.json to guarantee reproducible builds every time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Includes ARGs, LABEL metadata, non-root user, and basic HEALTHCHECK to improve maintainability, security, and orchestrator readiness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copies only runtime artifacts from the build stage; dev tools and compilers remain isolated, reducing attack surface.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM --platform=$BUILDPLATFORM node:18.19.0-alpine@sha256:0085670310d2879621f96a4216c893f92e2ded827e9e6ef8437672e1bd72f437 AS builder
WORKDIR /app

ARG NODE_ENV=production
ARG APP_VERSION=1.0.0

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM --platform=$TARGETPLATFORM gcr.io/distroless/nodejs:18@sha256:b534f9b5528e69baa7e8caf7bcc1d93ecf59faa15d289221decf5889a2ed3877
WORKDIR /app

ARG APP_VERSION=1.0.0
LABEL maintainer="Anonymous &amp;lt;anonymous@example.com&amp;gt;" \
      description="Production-ready Node.js app with distroless, reproducible, multi-arch build" \
      version="$APP_VERSION"

COPY --from=builder /app/dist ./dist

EXPOSE 3000
USER nonroot

HEALTHCHECK CMD node -e "process.exit(0)"

CMD ["dist/index.js"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The screenshot below shows the final container image size after applying multi-stage builds, distroless base images, and reproducible build practices, highlighting the impact of each optimization layer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feeo0f1p3x2ckh3hc908n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feeo0f1p3x2ckh3hc908n.png" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>career</category>
      <category>discuss</category>
      <category>security</category>
    </item>
  </channel>
</rss>
