dockerimg: stream tar to docker cp
Stop writing a temp file.
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s7f35a450897c1efek
diff --git a/dockerimg/dockerimg.go b/dockerimg/dockerimg.go
index 77af08a..728175c 100644
--- a/dockerimg/dockerimg.go
+++ b/dockerimg/dockerimg.go
@@ -2,6 +2,7 @@
package dockerimg
import (
+ "archive/tar"
"bytes"
"context"
"crypto/rand"
@@ -1165,30 +1166,45 @@
return fmt.Errorf("nil embedded linux binary reader, did you build using `make`?")
}
- cacheDir := filepath.Join(os.TempDir(), "sketch-binary-cache")
- if err := os.MkdirAll(cacheDir, 0o700); err != nil {
- return fmt.Errorf("failed to create cache directory: %w", err)
- }
+ // Stream a tarball to docker cp.
+ pr, pw := io.Pipe()
- hash := sha256.Sum256(bin)
- binaryPath := filepath.Join(cacheDir, hex.EncodeToString(hash[:]))
- _, statErr := os.Stat(binaryPath)
- switch {
- case os.IsNotExist(statErr):
- if err := os.WriteFile(binaryPath, bin, 0o700); err != nil {
- return fmt.Errorf("failed to write binary to cache: %w", err)
+ errCh := make(chan error, 1)
+ go func() {
+ defer pw.Close()
+ tw := tar.NewWriter(pw)
+
+ hdr := &tar.Header{
+ Name: "bin/sketch", // final path inside the container
+ Mode: 0o700,
+ Size: int64(len(bin)),
}
- case statErr != nil:
- return fmt.Errorf("failed to check if cached binary exists: %w", statErr)
- }
- // TODO: clean up old sketch binaries from the cache dir:
- // maybe set a max of 5, and then delete oldest after that by atime/mtime/ctime
+ if err := tw.WriteHeader(hdr); err != nil {
+ errCh <- fmt.Errorf("failed to write tar header: %w", err)
+ return
+ }
+ if _, err := tw.Write(bin); err != nil {
+ errCh <- fmt.Errorf("failed to write binary to tar: %w", err)
+ return
+ }
+ if err := tw.Close(); err != nil {
+ errCh <- fmt.Errorf("failed to close tar writer: %w", err)
+ return
+ }
+ errCh <- nil
+ }()
- if out, err := combinedOutput(ctx, "docker", "cp", binaryPath, containerName+":/bin/sketch"); err != nil {
- return fmt.Errorf("docker cp failed: %s: %w", out, err)
- }
+ cmd := exec.CommandContext(ctx, "docker", "cp", "-", containerName+":/")
+ cmd.Stdin = pr
- slog.DebugContext(ctx, "copied embedded linux binary to container", "container", containerName)
+ out, cmdErr := cmd.CombinedOutput()
+
+ if tarErr := <-errCh; tarErr != nil {
+ return tarErr
+ }
+ if cmdErr != nil {
+ return fmt.Errorf("docker cp failed: %s: %w", out, cmdErr)
+ }
return nil
}