Cloud Native 8 min read

How to Shrink Docker Images from 1.16 GB to 22 MB: Step‑by‑Step Optimization

This article explains Docker fundamentals, outlines why containers are popular, and walks through a practical example of reducing a React app's Docker image size from 1.16 GB to 22 MB using a lightweight Alpine base, multi‑stage builds, and an Nginx final stage.

macrozheng
macrozheng
macrozheng
How to Shrink Docker Images from 1.16 GB to 22 MB: Step‑by‑Step Optimization

Docker Introduction

Docker is a platform that lets developers and system administrators build, run, and share applications using containers. A container runs as an isolated process with its own filesystem built from a Docker image that contains everything needed to run the application, defined by a Dockerfile.

The terms dockerization or containerization refer to the process of creating Docker containers.

Containers are popular because they offer several advantages:

Flexibility – even the most complex applications can be containerized.

Lightweight – containers share the host kernel, making them far more efficient than virtual machines.

Portability – build locally, run anywhere.

Loose coupling – a container is self‑contained; replacing or upgrading one container does not disrupt others.

Security – containers enforce strict isolation without additional configuration.

This article focuses on optimizing Docker images to make them lightweight.

Optimization Process

We start with a sample React application. After running

npx create-react-app app --template typescript

and creating a Dockerfile, the initial image size is 1.16 GB.

<code>FROM node:10<br/>WORKDIR /app<br/>COPY app /app<br/>RUN npm install -g webserver.local<br/>RUN npm install && npm run build<br/>EXPOSE 3000<br/>CMD webserver.local -d ./build</code>

Step 1: Use a Lightweight Base Image

Switching the base image from the default to an Alpine‑based image reduces the size dramatically. Alpine images contain only the minimal required packages.

<code>FROM node:10-alpine<br/>WORKDIR /app<br/>COPY app /app<br/>RUN npm install -g webserver.local<br/>RUN npm install && npm run build<br/>EXPOSE 3000<br/>CMD webserver.local -d ./build</code>

Resulting image size: ~330 MB.

Step 2: Multi‑Stage Build

Multi‑stage builds allow us to compile the application in one stage and copy only the compiled output to a final, minimal image, discarding source files,

node_modules

, and

package.json

.

<code>FROM node:10-alpine AS build<br/>WORKDIR /app<br/>COPY app /app<br/>RUN npm install && npm run build<br/>FROM node:10-alpine<br/>WORKDIR /app<br/>RUN npm install -g webserver.local<br/>COPY --from=build /app/build ./build<br/>EXPOSE 3000<br/>CMD webserver.local -d ./build</code>

Resulting image size: ~91.5 MB.

Step 3: Use Nginx for Static Content

Serving static files with Nginx is more efficient than using a Node container. The final Dockerfile builds the React app in the first stage and copies the built assets into an

nginx:stable-alpine

image.

<code>FROM node:10-alpine AS build<br/>WORKDIR /app<br/>COPY app /app<br/>RUN npm install && npm run build<br/>FROM nginx:stable-alpine<br/>COPY --from=build /app/build /usr/share/nginx/html<br/>EXPOSE 80<br/>CMD ["nginx", "-g", "daemon off;"]</code>

Resulting image size: ~22.4 MB, and the container serves the React application correctly.

DockerImage OptimizationContainerizationNginxAlpineMulti‑Stage Build
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.