Docker Copy with File Globbing

Docker COPY files using glob pattern?

There is a solution based on multistage-build feature:

FROM node:12.18.2-alpine3.11

WORKDIR /app
COPY ["package.json", "yarn.lock", "./"]
# Step 2: Copy whole app
COPY packages packages

# Step 3: Find and remove non-package.json files
RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf

# Step 4: Define second build stage
FROM node:12.18.2-alpine3.11

WORKDIR /app
# Step 5: Copy files from the first build stage.
COPY --from=0 /app .

RUN yarn install --frozen-lockfile

COPY . .

# To restore workspaces symlinks
RUN yarn install --frozen-lockfile

CMD yarn start

On Step 5 the layer cache will be reused even if any file in packages directory has changed.

How to copy multiple files in one layer using a Dockerfile?


COPY README.md package.json gulpfile.js __BUILD_NUMBER ./

or

COPY ["__BUILD_NUMBER", "README.md", "gulpfile", "another_file", "./"]

You can also use wildcard characters in the sourcefile specification. See the docs for a little more detail.

Directories are special! If you write

COPY dir1 dir2 ./

that actually works like

COPY dir1/* dir2/* ./

If you want to copy multiple directories (not their contents) under a destination directory in a single command, you'll need to set up the build context so that your source directories are under a common parent and then COPY that parent.

docker copy all files in directory with given extention

I don't think you can do this with docker cp command

To do this you can mount the directory inside the docker and then you can run the regular cp command with regex to copy it to another directory.

Mount:

docker run -d --name containerName -v myvol2:/app imageName:tag

Inside Container:

cp app/*.pdf /destination

dockerfile copy list of files, when list is taken from a local file

Not possible in the sense that the COPY directive allows it out of the box, however if you know the extensions you can use a wildcard for the path such as COPY folder*something*name somewhere/.

For simple requirements.txt fetching that could be:

# but you need to distinguish it somehow
# otherwise it'll overwrite the files and keep the last one
# e.g. rename package/requirements.txt to package-requirements.txt
# and it won't be an issue
COPY */requirements.txt ./
RUN for item in $(ls requirement*);do pip install -r $item;done

But if it gets a bit more complex (as in collecting only specific files, by some custom pattern etc), then, no. However for that case simply use templating either by a simple F-string, format() function or switch to Jinja, create a Dockerfile.tmpl (or whatever you'd want to name a temporary file), then collect the paths, insert into the templated Dockerfile and once ready dump to a file and execute afterwards with docker build.

Example:

# Dockerfile.tmpl
FROM alpine
{{replace}}
# organize files into coherent structures so you don't have too many COPY directives
files = {
"pattern1": [...],
"pattern2": [...],
...
}
with open("Dockerfile.tmpl", "r") as file:
text = file.read()

insert = "\n".join([
f"COPY {' '.join(values)} destination/{key}/"
for key, values in files.items()
])

with open("Dockerfile", "w") as file:
file.write(text.replace("{{replace}}", insert))

Using regex in Docker COPY for digits

Dockerfile COPY uses shell globs, not regular expressions. The actual implementation uses the Go filepath.Match syntax. That syntax doesn't allow some of the combinations that regular expressions do: you can match any single digit [0-9], or any number of characters *, but not any number of digits.

Depending on how strict you want to be about what files you'll accept and how consistent the filename format is, any of the following will work:

COPY database-[0-9][0-9].[0-9].[0-9].zip ./database.zip
COPY database-*.*.*.zip ./database.zip
COPY database-*.zip ./database.zip

In all cases note that the pattern can match multiple files in the build context. If the right-hand side of COPY is a single file name (not ending with /) but the glob matches multiple files you will get a build error. In this case that's probably what you want.

COPY files in current local directory only and do not include subdirectories in Docker?

The Dockerfile COPY syntax supports shell globs but doesn't support any sort of matching on file type. You can copy all things with a given name *.py but not "only files". For the actual glob syntax it delegates to the Go path/filepath module which supports only the basic *, ?, and [a-z] characters as "special".

You aren't limited to a single file in a COPY command, though, as @JoachimSauer notes in a comment, and you don't have to spell out the destination directory or filename on the right-hand side. A relative path like . is relative to the current WORKDIR. So here I might write

WORKDIR /app
COPY run_myapp.py requirements.txt .


Related Topics



Leave a reply



Submit