Created
January 19, 2022 16:52
-
-
Save barn/79e9f500e699361eea543abcd1df3111 to your computer and use it in GitHub Desktop.
zsh function to copy files out of a container image.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/zsh | |
# | |
# Supports <image>:<path>, supports sha256/tags, path supports wildards, if a second arg is a path, it will output there, creating paths if needed | |
# $ copy_from_docker_image ruby:2.7.4:/etc/hosts ./ | |
copy_from_docker_image() { | |
if [ -z "$ZSH_VERSION" ]; then | |
echo "sorry I need to use zsh" | |
exit 1 | |
fi | |
setopt local_options pipefail errexit nounset | |
local image_arg _filename _image output_path | |
typeset -a bits _f lessbits | |
image_arg="$1" | |
output_path="${2-.}" | |
# If the target directory doesn't exist, try to make it, fail | |
# otherwise | |
[ -d "$output_path" ] || mkdir -p "$output_path" || { echo "cannot make output dir" ; exit 20; } | |
# split string by : | |
bits=("${(@s/:/)image_arg}") | |
# Get the last element of the split array | |
_filename="${bits[-1]}" | |
_f=($_filename) # make a temp array just with it. | |
# remove _f from the array | |
lessbits=(${bits:|_f}) | |
# join them back together with ':' | |
_image="${(j(:))lessbits}" | |
# dirname and basename in zsh | |
cdpath=${_filename:h} | |
files=${_filename:t} | |
# Run the container, but with as many options to increase safety as | |
# possible. No networking, no caps, read-only, etc etc | |
# We're trusting the tar on the target host sadly. | |
docker run \ | |
--pull missing \ | |
--user 0:0 \ | |
--no-healthcheck \ | |
--read-only \ | |
--cap-drop=all \ | |
--security-opt=no-new-privileges:true \ | |
--network none \ | |
--entrypoint /bin/sh \ | |
--rm \ | |
"$_image" -c "tar -cf - -C \"${cdpath}\" ${files}" | tar xvvf - -C "$output_path" | |
# No one has ever gotten pv to be helpful. | |
# | ( if [ -n "$commands[pv]" ]; then pv -tr -B 1024 -W --cursor | tar xvvf - -C "$output_path" >&4 ; else tar xvvf - -C "$output_path" ; fi ) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Bea, just saw this on Twitter, hope you don't mind some feedback:
You don't need https://gist.github.com/barn/79e9f500e699361eea543abcd1df3111#file-copy_from_docker_image-sh-L27-L30, you can rejoin just from the first to the second-to-last bits in the array by selecting
[1,-2]
:_image="${(j.:.)bits[1,-2]}"
BTW I think using dots in
(j.:.)
and(s.:.)
is more frequently used in zsh code when the delimiter is a colon.