Search code examples
containerstarpodman

Exclude a directory from `podman/docker export` stream and save to a file


I have a container that I want to export as a .tar file. I have used a podman run with a tar --exclude=/dir1 --exclude=/dir2 … that outputs to a file located on a bind-mounted host dir. But recently this has been giving me some tar: .: file changed as we read it errors, which podman/docker export would avoid. Besides, the export I suppose is more efficient. So I'm trying to migrate to using the export, but the major obstacle is I can't seem to find a way to exclude paths from the tar stream.

If possible, I'd like to avoid modifying a tar archive already saved on disk, and instead modify the stream before it gets saved to a file.

I've been banging my head for multiple hours, trying useless advices from ChatGPT, looking at cpio, and attempting to pipe the podman export to tar --exclude … command. With the last I did have small success at some point, but couldn't make tar save the result to a particularly named file.

Any suggestions?

(note: I do not make distinction between docker and podman here as their export command is completely the same, and it's useful for searchability)


Solution

  • Inspired by this answer, I found that bsdtar (as opposed to the usual tar) does have the ability to filter out files from stdin. It's implemented by passing -f - for "write to stdout" and @- for "read from stdin".

    So, suppose I want to filter out all dirs containing etc and lib64, then I execute:

    λ podman export frosty_banach | bsdtar -czf - --exclude="etc" --exclude="lib64" @- > foo.tar.gz
    λ tar tf foo.tar.gz | grep -P "\betc|lib64"
        # no matches, the dirs were filtered out successfully
    

    The usual glob expansion with * is also supported as part of pattern-matching.