Skip to content

Commit

Permalink
compression: add support for the zstd algorithm
Browse files Browse the repository at this point in the history
zstd is a compression algorithm that has a very fast decoder, while
providing also good compression ratios.  The fast decoder makes it
suitable for container images, as decompressing the tarballs is a very
expensive operation.

opencontainers/image-spec#788 added support
for zstd to the OCI image specs.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Sep 16, 2021
1 parent 5176095 commit e187eb2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
vim-common \
xfsprogs \
xz-utils \
zip
zip \
zstd


# Switch to use iptables instead of nftables (to match the CI hosts)
Expand Down
13 changes: 13 additions & 0 deletions pkg/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/pools"
"github.com/docker/docker/pkg/system"
"github.com/klauspost/compress/zstd"
"github.com/sirupsen/logrus"
exec "golang.org/x/sys/execabs"
)
Expand Down Expand Up @@ -83,6 +84,8 @@ const (
Gzip
// Xz is xz compression algorithm.
Xz
// Zstd is zstd compression algorithm.
Zstd
)

const (
Expand Down Expand Up @@ -127,6 +130,7 @@ func DetectCompression(source []byte) Compression {
Bzip2: {0x42, 0x5A, 0x68},
Gzip: {0x1F, 0x8B, 0x08},
Xz: {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00},
Zstd: {0x28, 0xb5, 0x2f, 0xfd},
} {
if bytes.HasPrefix(source, m) {
return compression
Expand Down Expand Up @@ -215,6 +219,13 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
}
readBufWrapper := p.NewReadCloserWrapper(buf, xzReader)
return wrapReadCloser(readBufWrapper, cancel), nil
case Zstd:
zstdReader, err := zstd.NewReader(buf)
if err != nil {
return nil, err
}
readBufWrapper := p.NewReadCloserWrapper(buf, zstdReader)
return readBufWrapper, nil
default:
return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
}
Expand Down Expand Up @@ -341,6 +352,8 @@ func (compression *Compression) Extension() string {
return "tar.gz"
case Xz:
return "tar.xz"
case Zstd:
return "tar.zst"
}
return ""
}
Expand Down
14 changes: 14 additions & 0 deletions pkg/archive/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ func TestDecompressStreamXz(t *testing.T) {
testDecompressStream(t, "xz", "xz -f")
}

func TestDecompressStreamZstd(t *testing.T) {
if _, err := exec.LookPath("zstd"); err != nil {
t.Skip("zstd not installed")
}
testDecompressStream(t, "zst", "zstd -f")
}

func TestCompressStreamXzUnsupported(t *testing.T) {
dest, err := os.Create(tmp + "dest")
if err != nil {
Expand Down Expand Up @@ -210,6 +217,13 @@ func TestExtensionXz(t *testing.T) {
t.Fatalf("The extension of a xz archive should be 'tar.xz'")
}
}
func TestExtensionZstd(t *testing.T) {
compression := Zstd
output := compression.Extension()
if output != "tar.zst" {
t.Fatalf("The extension of a zstd archive should be 'tar.zst'")
}
}

func TestCmdStreamLargeStderr(t *testing.T) {
cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
Expand Down

0 comments on commit e187eb2

Please sign in to comment.