## 🐳 Starting Your [[Docker]] Image Diet: Uncovering Its Ancestry with `docker history` {#sec-168deae1dd0f} You've deployed a seemingly lightweight app, but then you check the image size and it's well over 1GB. You might think, "What did I even put in there?" It's a common frustration. This is precisely when you need to delve into the image's 'lineage' or 'history'. ![docker-layer-diet](/media/whitedec/blog_img/de42f6f1949c4e91bc6defa030f10ea5.webp) ## "What Did You Eat to Get So Big?" {#sec-5eaafdc2833e} A Docker image is like an onion, with layers stacked one upon another. The `docker history` command acts as an X-ray, peeling back these layers one by one to reveal the culprit behind its size. Its basic usage is quite straightforward. ```bash # Basic Usage docker history [OPTIONS] # Example: Check my app's history docker history my-app:latest ``` Executing the command will display the image's history, starting from the newest layer all the way down to the base image, in reverse chronological order. ```text IMAGE CREATED CREATED BY SIZE a6215f271958 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B 7 weeks ago /bin/sh -c #(nop) ADD file:f28242cf608f6... 7.81MB ``` Pay close attention to the **SIZE** column. If you see hundreds of MB where you'd expect 0B, that's your target for optimization. With experience, you'll start to detect "suspicious areas" that clearly indicate bloat. > \*\*💡 Useful Tip: `--no-trunc** ` > > The default output truncates long commands. Appending the `--no-trunc` option displays the full command without truncation, which is essential for accurate analysis. > > `docker history --no-trunc my-app:latest` *** ## Real-World Case Study: "The Culprit Was `chown`" {#sec-036665971432} Let me share a real-life incident I encountered. I built a project with files totaling 150MB, yet the resulting image inexplicably ballooned to over 300MB. The culprit turned out to be two seemingly innocuous lines in the Dockerfile. **[Inefficient Method: Creating Two Layers]** ```dockerfile # 1. First, copy the files (copied as root by default) COPY . . # 2. Change ownership for security (executed as a separate command) RUN chown -R appuser:appgroup /app ``` After building this and checking with `docker history`, I found the following result: ```text IMAGE CREATED BY SIZE /bin/sh -c chown -R appuser:appgroup /app 150MB <-- (The problem spot!) /bin/sh -c #(nop) COPY dir:abc in /app 150MB ``` Here's where the insidious nature of Docker layers reveals itself. When 150MB of files are copied in step 1, one layer is created. However, when `chown` is executed in step 2, Docker thinks, "Oh, the file metadata (ownership) has changed? I'd better create another layer with this new state!" and proceeds to copy the entire 150MB again, stacking a new layer on top. Consequently, the content remained identical, but files with different ownership were stored twice, effectively doubling the image size. *** ## The Solution: A One-Line Diet! {#sec-b564ee91d4d9} The solution is simple: specify the ownership right from the copy command, merging it into a single layer. **[Efficient Method: Creating One Layer]** ```dockerfile # Copy and specify ownership simultaneously! COPY --chown=appuser:appgroup . . ``` After modifying the Dockerfile this way and running `docker history` again, the results are dramatic. ```text IMAGE CREATED BY SIZE /bin/sh -c #(nop) COPY --chown=appuser... dir:abc 150MB ``` See? Only a single layer was created, and the image size gracefully returned to a lean 150MB. Merging two commands into one effectively halved the image's footprint. *** ## Conclusion: Always Check 'History' After Building! {#sec-74645a10d229} Never forget that a [[Docker]] image generates **one layer per command line**. Just as you test your code after writing it, make it a habit to run `docker history --no-trunc` after building your images. As you ponder questions like, "Why is this `apt-get` so heavy?" or "Why was this layer split unnecessarily?", you'll gradually build extremely lightweight and efficient systems. Unnecessary layers are the enemy of an efficient system! *** **Was this helpful?** If so, please give it a like! Also read our related articles. **Related Articles** [Understanding Docker Shared Memory (shm_size and ipc) Perfectly](/ko/whitedec/2025/11/5/docker-shm-size-ipc/) [Docker: Communicating Between Containers via Host Ports Without Network Sharing](/ko/whitedec/2025/11/4/docker-host-port-container-communication/) [Docker Volume Copy: 'Why' You Should Do It That Way](/ko/whitedec/2025/11/10/docker-volume-copy-reason/)