This syntax of copying files with multiple extensions (per Copying files with multiple extensions) works fine in a regular desktop environment:

$ mkdir /tmp/baz && cd /tmp/baz
$ touch /tmp/file.foo
$ touch /tmp/file.bar
$ cp /tmp/*.{foo,bar} ./

But this doesn't seem to work in a dockerfile:

# Dockerfile
FROM alpine:3.7 as base
RUN touch /tmp/file.foo
RUN touch /tmp/file.bar
RUN cp /tmp/*.{foo,bar} ./
$ docker build -t tmp:tmp . && docker run -it tmp:tmp
[+] Building 4.0s (7/7) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                             0.0s
 => => transferring dockerfile: 149B                                                                                                                                             0.0s
 => [internal] load .dockerignore                                                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                                                  0.0s
 => [internal] load metadata for docker.io/library/alpine:3.7                                                                                                                    0.0s
 => CACHED [1/4] FROM docker.io/library/alpine:3.7                                                                                                                               0.0s
 => [2/4] RUN touch /tmp/file.foo                                                                                                                                                1.1s
 => [3/4] RUN touch /tmp/file.bar                                                                                                                                                1.1s
 => ERROR [4/4] RUN cp /tmp/*.{foo,bar} ./                                                                                                                                       1.5s
 > [4/4] RUN cp /tmp/*.{foo,bar} ./:
#7 0.844 cp: can't stat '/tmp/*.{foo,bar}': No such file or directory
failed to solve with frontend dockerfile.v0: failed to build LLB: executor failed running [/bin/sh -c cp /tmp/*.{foo,bar} ./]: exit code: 1

Oddly, if I enter a running container, the exact same cp syntax works fine.

How can I copy files with multiple extensions in a Dockerfile?


Commands in a Dockerfile RUN instruction are run using /bin/sh, which may not support brace expansion (the post you refer to explicitly talks about bash).

You can try any of the following:

  1. Set bash as the shell for RUN using SHELL (assuming you already have bash installed in the base image or using a previous RUN instruction):

    SHELL ["/bin/bash", "-c"]
    RUN cp /tmp/*.{foo,bar} ./ 
  2. Call bash explicitly:

    RUN ["/bin/bash", "-c", "cp /tmp/*.{foo,bar} ./"]
  3. Just not use brace expansion at all:

    RUN cp /tmp/*.foo /tmp/*.bar ./

Oddly, if I enter a running container, the exact same cp syntax works fine.

Your running container might be running bash as the default shell. This needn't always be the case:

% docker run --rm -it alpine:3.7
/ # echo /tmp/*.{foo,bar} ./
/tmp/*.{foo,bar} ./
/ # exit
% docker run --rm -it ubuntu:20.04
root@f184619a1121:/# echo /tmp/*.{foo,bar} ./
/tmp/*.foo /tmp/*.bar ./
root@f184619a1121:/# exit

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.