Relabeling Docker Images in GitHub Actions
I recently switched a small Rust application to use Nix to build Docker images. The project is hosted on GitHub. Previously, the pipeline was simple: use docker/metadata-action to generate the labels and tags, feed those to docker/build-push-action to build and push the image. Nix added a new wrinkle, as the resultant Docker image would only have a single tag and no labels. I now had to apply those afterwards.
The Docker CLI provides a few shortcuts, so I
didn’t need to write a new Dockerfile. The main issue was getting the --label
arguments right.
Given one (unquoted) label per line from metadata-action:
Outputlabel1=with, commas, label2=may contain "quotes"
What I wanted to run was this:
Bashdocker build - -t someimage:sometag --label "label1=with, commas," --label "label2=may contain \"quotes\""
Looping over the list directly wouldn’t work, because it would be substituted literally by Actions:
Bashdocker build - -t someimage:sometag --label label1=with, commas,\
--label label2=may contain "quotes"
Simply adding quotes would also be incorrect:
Bashdocker build - -t someimage:sometag --label "label1=with, commas,"\
--label "label2=may contain "quotes""
The command would succeed in this example with balanced quotes, since there are no syntactic errors
from Bash’s perspective, but label2
would actually be given the value may contain quotes
, due to
Bash parsing. Other values might cause different problems.
The solution came from b-fuze on the DSI Discord:
Bashlabels="${{ steps.meta.outputs.labels }}"
label_args=$(IFS=$'\n'; printf ' --label %q' $labels)
echo "FROM $image_name" | docker build . -f - -t "$new_image_name" $label_args
What this does is:
-
Store the list in a variable to get around other issues with quoting.
-
Convert each
key=value
line in the list into--label key=value
, withkey=value
correctly quoted for use as a single argument. This takes advantage ofprintf
’s looping behaviour:The format is reused as necessary to consume all of the arguments.
-
Pass all the arguments verbatim to
docker build
.