Skip to content

Conversation

@kaedwen
Copy link
Contributor

@kaedwen kaedwen commented Sep 5, 2023

Added a way to extract the current focused item in the tree view. This is far from optimal and we can start discussing on it.
#224

@TheRealGramdalf
Copy link

This could use docker create and docker cp which would be much more efficient: https://unix.stackexchange.com/questions/331645/extract-file-from-docker-image

@miskr-instructure
Copy link

miskr-instructure commented Apr 2, 2024

This could use docker create and docker cp which would be much more efficient:

  • docker cp requires tar to be installed in the image which makes that solution worse.
  • docker cp also requires the container to be running, so the entrypoint would need to be overwritten with a program that keeps running, this also requires specific binaries (eg. sleep/tail) to be present
  • it would be difficult to ensure that the container is deleted in every case (dive can get killed/terminated)
  • for small images, or if the file is early in the tar stream, the PR's solution is probably more efficient that waiting for docker to spin up a sandbox and run a process in it.

@TheRealGramdalf
Copy link

  • docker cp requires tar to be installed in the image which makes that solution worse.
  • I wasn't able to find anything that would indicate this - as far as I'm aware it just finds the file in the relevant /var/lib/docker/overlay2/* directory from the host.
  • docker cp also requires the container to be running, so the entrypoint would need to be overwritten with a program that keeps running, this also requires specific binaries (eg. sleep/tail) to be present
  • The answer I linked says otherwise: "According to the docker create documentation, this doesn't run the container:"

The docker create command creates a writeable container layer over the specified image and prepares it for running the specified command. The container ID is then printed to STDOUT. This is similar to docker run -d except the container is never started. You can then use the docker start <container_id> command to start the container at any point.

  • it would be difficult to ensure that the container is deleted in every case (dive can get killed/terminated)
  • This is a fair point. I'm not sure how exactly you would get around this, but it really shouldn't be that bad - a docker prune would easily fix this. Worst case scenario make dive create containers with a specific label (like --label wagoodman.dive.temp), and then check for containers with that label on next run (and notify the user to remove them/remove them automatically)
  • for small images, or if the file is early in the tar stream, the PR's solution is probably more efficient that waiting for docker to spin up a sandbox and run a process in it.
  • True, it might be. Except for the process point, since doesn't need to spin up the sandbox.

The only other thing I can think of is copying a file from an intermediate layer (that has been changed in a following layer) - I'm not sure if you can do that with docker cp, it doesn't look like you can

@kaedwen
Copy link
Contributor Author

kaedwen commented Apr 3, 2024

Hey @TheRealGramdalf, I would say that @miskr-instructure is right with the docker cp had this problem (hence the idea of using Dive and using it to extract files)

Try this

  • use a container FROM scratch, with just one file in it
  • try docker cp with it, it will complain about not having cp, and if you have it in there (busybox or whatever), the next missing is tar

@miskr-instructure
Copy link

^ You may be able to solve those by readonly-mounting cp and tar from somewhere outside, but those have the dynamic library dependencies (unless they are busybox-based) which you'd also need to mount in, etc...

All the solutions to this are more complex than the PR's. The only other trick would be directly accessing docker's image repo in the filesystem instead of going through the daemon, which is too brittle.

@avan-pra
Copy link

avan-pra commented Nov 6, 2024

Hi, thanks a lot for your PR, I added the functionality to extract from local archives in my local repository (I don't think I can contribute code to this PR)

@DeanAyalon
Copy link

* docker cp requires `tar` to be installed in the image which makes that solution worse.

No?

FROM scratch
COPY --from=alpine /lib/apk/db/installed .
# Just a random text file
docker build . -t test
docker create test .
docker cp test:/installed .

File extracted successfully

* docker cp also requires the container to be running, so the entrypoint would need to be overwritten with a program that keeps running, this also requires specific binaries (eg. sleep/tail) to be present

Also wrong, it just needs to exist, it can be stopped.

* it would be difficult to ensure that the container is deleted in every case (dive can get killed/terminated)

That is correct, yes. @TheRealGramdalf good idea!

* for small images, or if the file is early in the tar stream, the PR's solution is probably _more_ efficient that waiting for docker to spin up a sandbox and run a process in it.

Have you looked into Crane? Perhaps this could supply with a better file extraction method?

@TheRealGramdalf
Copy link

No?

Glad to know I'm not going crazy. I've since stopped using docker for a lot of things, so I didn't end up trying that myself. Thanks @DeanAyalon!

@DeanAyalon
Copy link

DeanAyalon commented Mar 20, 2025

I think this might not be working, at least, on my MacOS

I'm not savvy at Go, and I'm not sure which file runs for what purposes, but I see in some of the Extract functions, it simply logs "Not implemented" - Could it be the case for Mac as well?

And - How do I access the fmt log? So perhaps I can see what error my own machine is throwing when attempting to extract

Also, sorry where are the files extracted to? Perhaps it does work, but I just am looking in the wrong place

@wagoodman
Copy link
Owner

I agree, this functionality was pulled in already, however, I don't see it working as expected. I can dig further on this.

@w-edd
Copy link

w-edd commented May 18, 2025

docker create has implicit modifications to the content of "/". At least, it modifies /etc/hosts. On create, it is emptied. On run, it is populated by the container id and IP.

IMAGE=some-repo.com/image:tag

❯ docker create --name debug-etc-hosts "$IMAGE"
ffae30115b0d6c3dfaeb1f1111ccea0e7a60ec00f8cad5830d9bba73c4448eff

❯ docker cp debug-etc-hosts:/etc/hosts ./debug-hosts
Successfully copied 1.54kB to /home/user/pwd/debug-hosts

❯ ls -lart /home/user/pwd/debug-hosts
-rwxr-xr-x  1 user user    0 May 18 17:20 debug-hosts

❯ cat /home/user/pwd/debug-hosts

Let's examine it according to this great suggestion

echo "from $IMAGE" | docker build --output type=tar,dest=examine-fs.tar -
mkdir examine-fs
tar -C examine-fs -xf examine-fs.tar

❯ ls -lart examine-fs/etc/hosts
-rw-r--r-- 1 user user 261 May 18 16:45 examine-fs/etc/hosts

❯ cat examine-fs/etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
fe00::0	ip6-mcastprefix
fe00::1	ip6-allnodes
fe00::2	ip6-allrouters

Regardless of the above, I'm getting a panic error when trying to extract /etc/hosts using the TUI

❯ docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    docker.io/wagoodman/dive:latest some-repo.com/image:tag
Image Source: some-repo.com/image:tag
Extracting image from docker-engine... (this can take a while for large images)
Analyzing image...
Building cache...
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xa0 pc=0x715f92]

goroutine 35 [running]:
github.com/wagoodman/dive/dive/filetree.(*FileNode).Path(0xc0001a98e8?)
	/Users/wagoodman/code/dive/dive/filetree/file_node.go:276 +0x12
github.com/wagoodman/dive/runtime/ui/view.(*FileTree).extractFile(0xc0000d4000)
	/Users/wagoodman/code/dive/runtime/ui/view/filetree.go:321 +0x78
github.com/wagoodman/dive/runtime/ui/key.(*Binding).onAction(0x3?, 0x3?, 0x2?)
	/Users/wagoodman/code/dive/runtime/ui/key/binding.go:111 +0x1c
github.com/awesome-gocui/gocui.(*Gui).execKeybinding(0xc0001a99d8?, 0x74d3c8?, 0xc000936580?)
	/Users/wagoodman/go/pkg/mod/github.com/awesome-gocui/[email protected]/gui.go:947 +0x4f
github.com/awesome-gocui/gocui.(*Gui).execKeybindings(0xc0009c60f0, 0xc00014ef00, 0xc0001a9a98)
	/Users/wagoodman/go/pkg/mod/github.com/awesome-gocui/[email protected]/gui.go:926 +0x155
github.com/awesome-gocui/gocui.(*Gui).onKey(0xc0009c60f0, 0xc0001a9a98)
	/Users/wagoodman/go/pkg/mod/github.com/awesome-gocui/[email protected]/gui.go:882 +0x5d
github.com/awesome-gocui/gocui.(*Gui).handleEvent(0xc0001a9ae0?, 0xc0001a9a8c?)
	/Users/wagoodman/go/pkg/mod/github.com/awesome-gocui/[email protected]/gui.go:554 +0x2a
github.com/awesome-gocui/gocui.(*Gui).MainLoop(0xc0009c60f0)
	/Users/wagoodman/go/pkg/mod/github.com/awesome-gocui/[email protected]/gui.go:504 +0x22a
github.com/wagoodman/dive/runtime/ui.Run({0x7ffda6c32f23, 0x52}, {0xa26190, 0xd8c8c0}, 0xc000807ce0, {{0xc0001140e0, 0x3, 0x4}, 0xc00097a5a0, 0xc00097a5d0})
	/Users/wagoodman/code/dive/runtime/ui/app.go:160 +0x17a
github.com/wagoodman/dive/runtime.run(0x1, {0x0, {0x7ffda6c32f23, 0x52}, 0x1, 0x0, {0x0, 0x0}, 0xc00014e300, {0x0, ...}}, ...)
	/Users/wagoodman/code/dive/runtime/run.go:111 +0x1045
created by github.com/wagoodman/dive/runtime.Run in goroutine 1
	/Users/wagoodman/code/dive/runtime/run.go:133 +0x2bb

@clombo
Copy link

clombo commented Oct 17, 2025

Hi,

Is there been any movement on this feature? I just installed dive on MacOS and tried using it to extract a file but it just does nothing or nothing of note that I can see.

NOTE: I installed this using "brew install dive". From what I understand this is still a open PR and should not be in a stable release? So either this slipped in and it is not working or the brew installation is using something it is not suppose too?

@aj0413
Copy link

aj0413 commented Nov 2, 2025

#659

Partial fix for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants