1+ #! /bin/bash
2+ # ABOUTME: Script to analyze Docker image layers and find redundancy
3+ # ABOUTME: Helps identify duplicate layers and optimization opportunities
4+
5+ set -e
6+
7+ # Colors
8+ RED=' \033[0;31m'
9+ GREEN=' \033[0;32m'
10+ YELLOW=' \033[1;33m'
11+ BLUE=' \033[0;34m'
12+ NC=' \033[0m'
13+
14+ # Default image
15+ IMAGE=" ${1:- openspp: test} "
16+
17+ echo -e " ${BLUE} Docker Layer Analysis for: $IMAGE ${NC} "
18+ echo " ================================================"
19+
20+ # Check if image exists
21+ if ! docker image inspect " $IMAGE " > /dev/null 2>&1 ; then
22+ echo -e " ${RED} Error: Image '$IMAGE ' not found${NC} "
23+ echo " Usage: $0 [image-name]"
24+ exit 1
25+ fi
26+
27+ # 1. Show layer sizes
28+ echo -e " \n${YELLOW} Layer Sizes:${NC} "
29+ docker history " $IMAGE " --format " table {{.Size}}\t{{.CreatedBy}}" | head -20
30+
31+ # 2. Find duplicate sizes
32+ echo -e " \n${YELLOW} Checking for duplicate layer sizes:${NC} "
33+ docker history " $IMAGE " --format " {{.Size}}" | \
34+ grep -v " <missing>" | \
35+ sort | uniq -d | while read size; do
36+ if [ ! -z " $size " ] && [ " $size " != " 0B" ]; then
37+ echo -e " ${RED} Found duplicate size: $size ${NC} "
38+ echo " Layers with this size:"
39+ docker history " $IMAGE " --format " {{.Size}}\t{{.CreatedBy}}" | grep " ^$size "
40+ fi
41+ done
42+
43+ # 3. Calculate total image size
44+ echo -e " \n${YELLOW} Image Size Analysis:${NC} "
45+ SIZE=$( docker image inspect " $IMAGE " --format=' {{.Size}}' )
46+ SIZE_MB=$(( SIZE / 1024 / 1024 ))
47+ echo " Total image size: ${SIZE_MB} MB"
48+
49+ # 4. Show largest layers
50+ echo -e " \n${YELLOW} Top 5 Largest Layers:${NC} "
51+ docker history " $IMAGE " --format " table {{.Size}}\t{{.CreatedBy}}" | \
52+ grep -v SIZE | \
53+ sort -hr | \
54+ head -5
55+
56+ # 5. Check for common anti-patterns
57+ echo -e " \n${YELLOW} Checking for common anti-patterns:${NC} "
58+
59+ # Check for chown after COPY
60+ if docker history " $IMAGE " --no-trunc | grep -q " COPY.*from=.*installer" && \
61+ docker history " $IMAGE " --no-trunc | grep -q " chown.*openspp" ; then
62+ echo -e " ${RED} ⚠ Warning: Found COPY followed by chown - consider using COPY --chown${NC} "
63+ fi
64+
65+ # Check for multiple apt-get updates
66+ APT_UPDATES=$( docker history " $IMAGE " --no-trunc | grep -c " apt-get update" || true)
67+ if [ " $APT_UPDATES " -gt 2 ]; then
68+ echo -e " ${YELLOW} ⚠ Found $APT_UPDATES apt-get update commands - consider combining${NC} "
69+ fi
70+
71+ # Check for rm commands that might be ineffective
72+ if docker history " $IMAGE " --no-trunc | grep -q " rm -rf /var/lib/apt/lists" ; then
73+ echo -e " ${GREEN} ✓ Good: Cleaning apt cache${NC} "
74+ fi
75+
76+ # 6. Suggest dive tool if not installed
77+ if ! command -v dive & > /dev/null; then
78+ echo -e " \n${BLUE} For detailed layer analysis, install dive:${NC} "
79+ echo " brew install dive # macOS"
80+ echo " wget https://github.com/wagoodman/dive/releases/latest/download/dive_*_linux_amd64.deb"
81+ echo " sudo dpkg -i dive_*.deb # Ubuntu/Debian"
82+ echo " "
83+ echo " Then run: dive $IMAGE "
84+ else
85+ echo -e " \n${GREEN} Dive is installed. Run 'dive $IMAGE ' for interactive analysis${NC} "
86+ fi
87+
88+ # 7. Export detailed analysis
89+ echo -e " \n${YELLOW} Exporting detailed analysis...${NC} "
90+ REPORT_FILE=" layer-analysis-$( date +%Y%m%d-%H%M%S) .txt"
91+ {
92+ echo " Docker Layer Analysis Report"
93+ echo " Image: $IMAGE "
94+ echo " Date: $( date) "
95+ echo " ================================"
96+ echo " "
97+ echo " Full Layer History:"
98+ docker history --no-trunc " $IMAGE "
99+ echo " "
100+ echo " Layer SHA256 Hashes:"
101+ docker inspect " $IMAGE " | jq ' .[0].RootFS.Layers'
102+ } > " $REPORT_FILE "
103+
104+ echo -e " ${GREEN} Detailed report saved to: $REPORT_FILE ${NC} "
105+
106+ # Summary
107+ echo -e " \n${BLUE} Summary:${NC} "
108+ LAYERS=$( docker history " $IMAGE " | wc -l)
109+ echo " - Total layers: $LAYERS "
110+ echo " - Image size: ${SIZE_MB} MB"
111+
112+ # Optimization suggestions
113+ echo -e " \n${BLUE} Optimization Tips:${NC} "
114+ echo " 1. Use COPY --chown instead of separate chown commands"
115+ echo " 2. Combine multiple RUN commands with && to reduce layers"
116+ echo " 3. Order commands from least to most frequently changing"
117+ echo " 4. Clean package manager cache in the same RUN command"
118+ echo " 5. Use multi-stage builds to exclude build dependencies"
0 commit comments