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
This commit is contained in:
Jose Diaz-Gonzalez
2024-12-16 03:39:24 -05:00
parent 819f9a84c9
commit bde2f2e43d

View File

@@ -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