Stream docker export directly to consumer

Rather than queueing up into a `bytes.Buffer`.

In my test case (building kube master image) this reduces Maximum RSS (as
measured by time(1)) compared with the previous patch from 2.8G to 110M. The
tar output case goes from 2.1G to 110M also. Overall allocations are ~715M in
both cases.

Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
Ian Campbell 2017-12-06 15:05:04 +00:00
parent 9f44acf8e3
commit 3045a80c85
2 changed files with 7 additions and 14 deletions

View File

@ -4,7 +4,6 @@ package moby
// and also using the Docker API not shelling out
import (
"bytes"
"errors"
"fmt"
"io"
@ -81,25 +80,18 @@ func dockerCreate(image string) (string, error) {
return respBody.ID, nil
}
func dockerExport(container string) ([]byte, error) {
func dockerExport(container string) (io.ReadCloser, error) {
log.Debugf("docker export: %s", container)
cli, err := dockerClient()
if err != nil {
return []byte{}, errors.New("could not initialize Docker API client")
return nil, errors.New("could not initialize Docker API client")
}
responseBody, err := cli.ContainerExport(context.Background(), container)
if err != nil {
return []byte{}, err
}
defer responseBody.Close()
output := bytes.NewBuffer(nil)
_, err = io.Copy(output, responseBody)
if err != nil {
return []byte{}, err
return nil, err
}
return output.Bytes(), nil
return responseBody, err
}
func dockerRm(container string) error {

View File

@ -119,6 +119,8 @@ func ImageTar(ref *reference.Spec, prefix string, tw tarWriter, trust bool, pull
if err != nil {
return fmt.Errorf("Failed to docker export container from container %s: %v", container, err)
}
defer contents.Close()
err = dockerRm(container)
if err != nil {
return fmt.Errorf("Failed to docker rm container %s: %v", container, err)
@ -126,8 +128,7 @@ func ImageTar(ref *reference.Spec, prefix string, tw tarWriter, trust bool, pull
// now we need to filter out some files from the resulting tar archive
r := bytes.NewReader(contents)
tr := tar.NewReader(r)
tr := tar.NewReader(contents)
for {
hdr, err := tr.Next()