Skip to content

Docker 29 Images aren't compressed after squash #260

@lorenz-werner

Description

@lorenz-werner

When I squash images built with Docker 29, those images are bigger than before, because it seems like they are no longer compressed.
This is problematic, because those images aren't working with JIB and well, they are bigger.

With docker 29+ squashing won't work as expected:

--- docker version ---
Client:
 Version:           29.0.4
 API version:       1.52
 Go version:        go1.25.4
 Git commit:        3247a5a
 Built:             Mon Nov 24 21:58:38 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          29.0.4
  API version:      1.52 (minimum version 1.44)
  Go version:       go1.25.4
  Git commit:       4612690e
  Built:            Mon Nov 24 22:01:10 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v2.1.5
  GitCommit:        fcd43222d6b07379a4be9786bda52438f0dd16a1
 runc:
  Version:          1.3.3
  GitCommit:        v1.3.3-0-gd842d77
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

--- build original image ---
#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 69B done
#1 DONE 0.0s

#2 [internal] load metadata for docker.io/library/debian:latest
#2 DONE 0.9s

#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s

#4 [1/2] FROM docker.io/library/debian:latest@sha256:3352c2e13876c8a5c5873ef20870e1939e73cb9a3c1aeba5e3e72172a85ce9ed
#4 resolve docker.io/library/debian:latest@sha256:3352c2e13876c8a5c5873ef20870e1939e73cb9a3c1aeba5e3e72172a85ce9ed 0.0s done
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 0B / 49.30MB 0.2s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 15.73MB / 49.30MB 0.5s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 31.46MB / 49.30MB 0.6s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 40.89MB / 49.30MB 0.8s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 49.30MB / 49.30MB 0.9s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 49.30MB / 49.30MB 0.9s done
#4 extracting sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155
#4 extracting sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 0.4s done
#4 DONE 1.4s

#5 [2/2] RUN echo foo > /bar
#5 DONE 0.4s

#6 exporting to image
#6 exporting layers 0.1s done
#6 exporting manifest sha256:8a36237b0b1053059f573eab5456a22f5b7660b101a7b8f40355987f5878b4aa 0.0s done
#6 exporting config sha256:a3059884c168e6bb512861ebd80166163e27db341c48a1e2f684bfbc40a3e34f 0.0s done
#6 naming to docker.io/library/foo:latest done
#6 unpacking to docker.io/library/foo:latest 0.0s done
#6 DONE 0.1s

--- squash image ---
2026-04-20 13:37:52,238 squash.py:54         INFO  docker-squash version 1.2.2, Docker 29.0.4, API 1.52...
2026-04-20 13:37:52,238 squash.py:96         INFO  Using v2 image format
2026-04-20 13:37:52,244 image.py:179        INFO  Old image has 2 layers
2026-04-20 13:37:52,244 image.py:212        INFO  Checking if squashing is necessary...
2026-04-20 13:37:52,244 image.py:224        INFO  Attempting to squash last 2 layers...
2026-04-20 13:37:52,244 image.py:372        INFO  Saving image sha256:8a36237b0b1053059f573eab5456a22f5b7660b101a7b8f40355987f5878b4aa to /tmp/docker-squash-inep5mk5/old directory...
2026-04-20 13:37:52,473 image.py:407        INFO  Image saved!
2026-04-20 13:37:52,473 image.py:233        INFO  Squashing image 'foo'...
2026-04-20 13:37:52,474 image.py:750        INFO  Starting squashing for /tmp/docker-squash-inep5mk5/new/squashed/layer.tar...
2026-04-20 13:37:52,474 image.py:775        INFO  Squashing file '/tmp/docker-squash-inep5mk5/old/blobs/sha256/baa5fc1c2fcd86eb46a5356d9e93a5edbd10ae0b1e5df4811311a494f69cb554'...
2026-04-20 13:37:52,474 image.py:775        INFO  Squashing file '/tmp/docker-squash-inep5mk5/old/blobs/sha256/a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155'...
2026-04-20 13:37:53,801 image.py:923        INFO  Squashing finished!
2026-04-20 13:37:53,874 image.py:245        INFO  Original image size: 47.02 MB
2026-04-20 13:37:53,874 image.py:246        INFO  Squashed image size: 118.10 MB
2026-04-20 13:37:53,874 image.py:249        INFO  If the squashed image is larger than original it means that there were no meaningful files to squash and it just added metadata. Are you sure you specified correct parameters?
2026-04-20 13:37:53,874 squash.py:136        INFO  New squashed image ID is c64188825f55ff7381844dcf5bc80eaed885131395c8d66d234c02148d7628bc
2026-04-20 13:37:54,809 image.py:281        INFO  Image registered in Docker daemon as foo:squashed
2026-04-20 13:37:54,813 squash.py:159        INFO  Done

--- original manifest ---
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "digest": "sha256:a3059884c168e6bb512861ebd80166163e27db341c48a1e2f684bfbc40a3e34f",
    "size": 660
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "digest": "sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155",
      "size": 49297833
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "digest": "sha256:baa5fc1c2fcd86eb46a5356d9e93a5edbd10ae0b1e5df4811311a494f69cb554",
      "size": 104
    }
  ]
}

--- squashed manifest ---
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "digest": "sha256:c64188825f55ff7381844dcf5bc80eaed885131395c8d66d234c02148d7628bc",
    "size": 372
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar",
      "digest": "sha256:ade72a6b4d581e45e5affdc9269f55ebd5e8bfad11a335985fa2209e4eee73dd",
      "size": 123832320
    }
  ]
}

--- original layer mediaTypes ---
application/vnd.docker.image.rootfs.diff.tar.gzip
application/vnd.docker.image.rootfs.diff.tar.gzip

--- squashed layer mediaTypes ---
application/vnd.docker.image.rootfs.diff.tar

--- image sizes ---
foo:squashed    554cc145f4cd    258MB
foo:latest      8a36237b0b10    183MB

Here you can see, that the mediaType after squashing is application/vnd.docker.image.rootfs.diff.tar, while it should be application/vnd.docker.image.rootfs.diff.tar.gzip.

And with docker 28.* it works as expected:

--- docker version ---
Client:
 Version:           28.5.2
 API version:       1.51
 Go version:        go1.25.3
 Git commit:        ecc6942
 Built:             Wed Nov  5 14:42:42 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.5.2
  API version:      1.51 (minimum version 1.24)
  Go version:       go1.24.9
  Git commit:       89c5e8f
  Built:            Wed Nov  5 14:45:42 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.7.28
  GitCommit:        b98a3aace656320842a23f4a392a33f46af97866
 runc:
  Version:          1.3.3
  GitCommit:        v1.3.3-0-gd842d77
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

--- build original image ---
#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 69B done
#1 DONE 0.0s

#2 [internal] load metadata for docker.io/library/debian:latest
#2 DONE 1.1s

#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s

#4 [1/2] FROM docker.io/library/debian:latest@sha256:3352c2e13876c8a5c5873ef20870e1939e73cb9a3c1aeba5e3e72172a85ce9ed
#4 resolve docker.io/library/debian:latest@sha256:3352c2e13876c8a5c5873ef20870e1939e73cb9a3c1aeba5e3e72172a85ce9ed 0.0s done
#4 sha256:3352c2e13876c8a5c5873ef20870e1939e73cb9a3c1aeba5e3e72172a85ce9ed 8.93kB / 8.93kB done
#4 sha256:84cc642701b773b0df5a98553f4bf9aab4ad4d10a34c406e46d33ee1fd548fa7 1.02kB / 1.02kB done
#4 sha256:8ce2894044f6727bb22b6a00b3fdb8c345f1e16f2bd8e512e2ecf05d6b8ddd5c 451B / 451B done
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 0B / 49.30MB 0.1s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 9.44MB / 49.30MB 0.4s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 13.63MB / 49.30MB 0.6s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 20.97MB / 49.30MB 0.7s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 30.41MB / 49.30MB 0.9s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 48.23MB / 49.30MB 1.1s
#4 sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 49.30MB / 49.30MB 1.3s done
#4 extracting sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 0.1s
#4 extracting sha256:a7730063fcfe708b222d34c4f07d633dfe087a28c05c4daaab2fa9943854c155 0.4s done
#4 DONE 1.8s

#5 [2/2] RUN echo foo > /bar
#5 DONE 0.6s

#6 exporting to image
#6 exporting layers 0.0s done
#6 writing image sha256:bbb0cae47d672e4ae9c45ed5df8a89492f4a68c62de057c93f05d1f225c566f9 done
#6 naming to docker.io/library/foo done
#6 DONE 0.0s

--- squash image ---
2026-04-20 13:38:17,163 squash.py:54         INFO  docker-squash version 1.2.2, Docker 28.5.2, API 1.51...
2026-04-20 13:38:17,164 squash.py:96         INFO  Using v2 image format
2026-04-20 13:38:17,165 image.py:179        INFO  Old image has 2 layers
2026-04-20 13:38:17,165 image.py:212        INFO  Checking if squashing is necessary...
2026-04-20 13:38:17,165 image.py:224        INFO  Attempting to squash last 2 layers...
2026-04-20 13:38:17,165 image.py:372        INFO  Saving image sha256:bbb0cae47d672e4ae9c45ed5df8a89492f4a68c62de057c93f05d1f225c566f9 to /tmp/docker-squash-7gk07c21/old directory...
2026-04-20 13:38:17,866 image.py:407        INFO  Image saved!
2026-04-20 13:38:17,867 image.py:233        INFO  Squashing image 'foo'...
2026-04-20 13:38:17,867 image.py:750        INFO  Starting squashing for /tmp/docker-squash-7gk07c21/new/squashed/layer.tar...
2026-04-20 13:38:17,867 image.py:775        INFO  Squashing file '/tmp/docker-squash-7gk07c21/old/blobs/sha256/759d69e2f182ca5fd107982a72e603f3c9572c2c8674fd4c44e6c87ad52e7e8a'...
2026-04-20 13:38:17,868 image.py:775        INFO  Squashing file '/tmp/docker-squash-7gk07c21/old/blobs/sha256/47e673e32817fbaf53619364587ebf6b2d41f3fd5e02b3fa6a3b2fd01b47ddfb'...
2026-04-20 13:38:18,421 image.py:923        INFO  Squashing finished!
2026-04-20 13:38:18,497 image.py:245        INFO  Original image size: 118.10 MB
2026-04-20 13:38:18,498 image.py:246        INFO  Squashed image size: 118.10 MB
2026-04-20 13:38:18,498 image.py:253        INFO  Image size decreased by 0.00 %
2026-04-20 13:38:18,498 squash.py:136        INFO  New squashed image ID is 9c3b839554b0983a10eb17d44c449ff609ca4a32bddfb28995acb865bde66d1c
2026-04-20 13:38:18,940 image.py:281        INFO  Image registered in Docker daemon as foo:squashed
2026-04-20 13:38:18,944 squash.py:159        INFO  Done

--- original manifest ---
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 660,
    "digest": "sha256:bbb0cae47d672e4ae9c45ed5df8a89492f4a68c62de057c93f05d1f225c566f9"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 50483003,
      "digest": "sha256:e1d3d3808b7cc00ad2139fd148f20871698ae08d4b95020b8137bd3b7b9b75d4"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 133,
      "digest": "sha256:2d1db21fec235d9d4c4fc8b32c94f325e0f69af10edc5b516eb9f47a494c4afb"
    }
  ]
}

--- squashed manifest ---
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 372,
    "digest": "sha256:9c3b839554b0983a10eb17d44c449ff609ca4a32bddfb28995acb865bde66d1c"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 50467368,
      "digest": "sha256:9e50fa3cd8bd823f19b802eb87441112cfd0efb95d4f9cb0f5d8406a79c9ecd2"
    }
  ]
}

--- original layer mediaTypes ---
application/vnd.docker.image.rootfs.diff.tar.gzip
application/vnd.docker.image.rootfs.diff.tar.gzip

--- squashed layer mediaTypes ---
application/vnd.docker.image.rootfs.diff.tar.gzip

--- image sizes ---
foo:squashed    9c3b839554b0    120MB
foo:latest      bbb0cae47d67    120MB

I also tested

  • Docker 29.4.0
  • docker-squash git master (shows up as 1.3.0)

which are the latest releases and the problem occurs there also.

Is there a known way to get docker-squash working with Docker 29?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions