From bde2f2e43d74bcdaa5f51fa3542501535b0697d8 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 16 Dec 2024 03:39:24 -0500 Subject: [PATCH] refactor: write contents to stdout before writing to a file Rather than writing directly to the file - thus utilizing whatever user docker is being executed as - we copy the file to stdout and then write it to the temp file. This ensures permissions on the file are as expected from Dokku's end. Closes #7336 --- plugins/common/docker.go | 47 ++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/plugins/common/docker.go b/plugins/common/docker.go index 18c90b41e..10d64b8f6 100644 --- a/plugins/common/docker.go +++ b/plugins/common/docker.go @@ -104,14 +104,6 @@ func CopyFromImage(appName string, image string, source string, destination stri } } - tmpFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", MustGetEnv("DOKKU_PID"), "CopyFromImage")) - if err != nil { - return fmt.Errorf("Cannot create temporary file: %v", err) - } - - defer tmpFile.Close() - defer os.Remove(tmpFile.Name()) - globalRunArgs := MustGetEnv("DOKKU_GLOBAL_RUN_ARGS") createLabelArgs := []string{"--label", fmt.Sprintf("com.dokku.app-name=%s", appName), globalRunArgs} containerID, err := DockerContainerCreate(image, createLabelArgs) @@ -125,7 +117,7 @@ func CopyFromImage(appName string, image string, source string, destination stri // ref: https://github.com/dotcloud/docker/issues/3986 result, err := CallExecCommand(ExecCommandInput{ Command: DockerBin(), - Args: []string{"container", "cp", fmt.Sprintf("%s:%s", containerID, source), tmpFile.Name()}, + Args: []string{"container", "cp", "--quiet", fmt.Sprintf("%s:%s", containerID, source), "-"}, }) if err != nil { return fmt.Errorf("Unable to copy file %s from image: %w", source, err) @@ -134,6 +126,43 @@ func CopyFromImage(appName string, image string, source string, destination stri return fmt.Errorf("Unable to copy file %s from image: %v", source, result.StderrContents()) } + tarContents := result.StdoutContents() + if tarContents == "" { + return fmt.Errorf("Unable to copy file %s from image", source) + } + + // extract the contents via tar + // tar -xOf - + result, err = CallExecCommand(ExecCommandInput{ + Command: "tar", + Args: []string{"-xOf", "-"}, + Stdin: strings.NewReader(tarContents), + }) + if err != nil { + return fmt.Errorf("Unable to extract contents from tar: %v", err) + } + + contents = result.StdoutContents() + + tmpFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", MustGetEnv("DOKKU_PID"), "CopyFromImage")) + if err != nil { + return fmt.Errorf("Cannot create temporary file: %v", err) + } + + defer func() { + if err := tmpFile.Close(); err != nil { + LogWarn(fmt.Sprintf("Unable to close temporary file: %v", err)) + } + if err := os.Remove(tmpFile.Name()); err != nil { + LogWarn(fmt.Sprintf("Unable to remove temporary file: %v", err)) + } + }() + + // write contents to tmpFile + if _, err := tmpFile.Write([]byte(contents)); err != nil { + return fmt.Errorf("Unable to write to temporary file: %v", err) + } + fi, err := os.Stat(tmpFile.Name()) if err != nil { return err