Skip to content

Proposal: support wildcards and destination names in docker cp #7710

Open

Description

@SvenDowideit

Make docker cp work more like scp

Usage: docker cp CONTAINER:PATH HOSTPATH

Proposed

1 Allow the PATH to contain standard filesystem wildcards, and then expand them on the container side.
2 Allow the HOSTPATH to be the resulting filename if the daemon sends it a single file.

right now

HOSTPATH is a dir, which will even be created for you - rather than the name of the resulting file, and wildcards are not expanded.

tmp $ mkdir sven
tmp $ docker cp sven:/etc/* sven
2014/08/25 14:22:37 Error response from daemon: Could not find the file /etc/* in container sven
tmp $ docker cp sven:/etc/passwd sven/banana
tmp $ ls sven/
banana  passwd
tmp $ more sven/*

*** sven/banana: directory ***

tmp $ cd sven
sven $ docker cp sven:/etc/* .
2014/08/25 14:22:23 Error response from daemon: Could not find the file /etc/* in container sven

Activity

  1. vieux commented on Aug 27, 2014

    @vieux
    Contributor

    This reminds me of #6580

  2. SvenDowideit commented on Aug 29, 2014

    @SvenDowideit
    ContributorAuthor

    yup, true.

  3. duglin commented on Sep 30, 2014

    @duglin
    Contributor

    I think the wildcard support for this is now done, and #4272 should cover the other bits, so perhaps we can close this?

  4. jessfraz commented on Sep 30, 2014

    @jessfraz
    Contributor

    closed as dup of #4272

  5. ferrouswheel commented on Feb 23, 2015

    @ferrouswheel

    @duglin I am unable to find anything about docker cp supporting wildcards, and am unable to get wildcards working with docker 1.5.0. Can you please point towards me to somewhere with more info?

  6. gpetz commented on May 25, 2015

    @gpetz

    @duglin
    docker cp 87ff9d25b53d:/var/log/apache2/access.log .
    copies access.log to .

    docker cp 87ff9d25b53d:/var/log/apache2/*.log .
    returns: ATA[0000] Error response from daemon: Could not find the file /var/log/apache2/*.log in container 87ff9d25b53d

    (Boot2Docker v1.6.2)

  7. reopened this on May 25, 2015
  8. duglin commented on May 25, 2015

    @duglin
    Contributor

    You're correct - I think I was mixing up 'docker cp' with "COPY" from Dockerfiles.
    However #12858 should do it.

  9. added
    kind/enhancementEnhancements are not bugs or new features but can improve usability or performance.
    on May 25, 2015
  10. added
    kind/featureFunctionality or other elements that the project doesn't currently have. Features are new and shiny
    and removed on Sep 8, 2015
  11. mmarzec commented on Jun 16, 2016

    @mmarzec

    +1 for this feature

  12. xmhubj commented on Jun 30, 2016

    @xmhubj

    looking forward to be implemented.

  13. 7 remaining items

  14. thaJeztah commented on Feb 21, 2018

    @thaJeztah
    Member

    Can an entire directory recursively be copied? Otherwise .. the obvious question.. how can anything be bulk copied?

    recursive copy is supported;

    prepare a container having some files;

    mkdir repro-7710 && cd repro-7710
    docker run --name mycontainer busybox sh -c 'mkdir -p /foo/bar/baz; touch /foo/file /foo/bar/file /foo/bar/baz/file;'
    

    copy the contents of foo recursively;

    mkdir output
    docker cp mycontainer:/foo/. ./output
    tree output
    output
    ├── bar
    │   ├── baz
    │   │   └── file
    │   └── file
    └── file
    
    2 directories, 3 files
    

    copy foo, and its contents recursively;

    mkdir output2
    docker cp mycontainer:/foo ./output2/
    tree output2
    output2
    └── foo
        ├── bar
        │   ├── baz
        │   │   └── file
        │   └── file
        └── file
    
    3 directories, 3 files
    
  15. courtarro commented on Jul 10, 2018

    @courtarro

    A workaround for these limitations, at least with aufs, is to find the mount point of the container's path and copy files from there:

    • Find the ID of the aufs mount point for this container: sudo cat /var/lib/docker/image/aufs/layerdb/mounts/(container_id)/mount-id
    • Navigate to the path (as root). This requires that the container be running so that it's mounted: cd /var/lib/docker/aufs/mnt/(mount_id)
    • Copy to/from this path. Keep an eye on permissions.
  16. michaelarnauts commented on Mar 11, 2019

    @michaelarnauts

    Until this is implemented, I use the following workaround by tarring it in the container, and extracting it on the host.

    docker exec *container* sh -c "tar -cf - /var/log/queue.*.log" | tar --strip-components=2 -xf - -C output/
  17. Aypahyo commented on May 31, 2019

    @Aypahyo

    I have a immilar usecase for this.
    I have output files that I need to copy.

    the names in the container are:

    ./src/IntegrationTests/TestResults/TrxResults_2019-05-28_15-06-19-518.xml
    ./src/IntegrationTests/TestResults/TrxResults_2019-05-31_08-08-42-488.xml
    ./src/UnitTests/TestResults/TrxResults_2019-05-28_15-06-21-358.xml
    ./src/UnitTests/TestResults/TrxResults_2019-05-31_08-08-45-114.xml
    ./src/UnitTests/coverage.opencover.xml
    ./src/.sonarqube/out/.sonar/report-task.txt
    

    My container is not running so an exec hotfix can not be done.

    These commands would find the file in the container when I use an interactive terminal.

    find . -wholename "**/TestResults/*.xml"
    find . -wholename "**/coverage.opencover.xml"
    find . -name "report-task.txt"

    Following the pattern:

    docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
    

    I would like to write

    docker cp -wholename "**/TestResults/*.xml"  CONTAINER:src .
    docker cp -wholename "**/coverage.opencover.xml"  CONTAINER:src .
    docker cp -name "report-task.txt"  CONTAINER:src .

    With a limitation that SRC_PATH and DEST_PATH can only be folder names.
    The subfolder structure would be copied from the detected path.

    The expected copy result would be

    DEST_PATH/IntegrationTests/TestResults/TrxResults_2019-05-28_15-06-19-518.xml
    DEST_PATH/IntegrationTests/TestResults/TrxResults_2019-05-31_08-08-42-488.xml
    DEST_PATH/UnitTests/TestResults/TrxResults_2019-05-28_15-06-21-358.xml
    DEST_PATH/UnitTests/TestResults/TrxResults_2019-05-31_08-08-45-114.xml
    DEST_PATH/UnitTests/coverage.opencover.xml
    DEST_PATH/.sonarqube/out/.sonar/report-task.txt
    
  18. deiga commented on May 31, 2019

    @deiga

    @Aypahyo You can circumvent the "not running" part by commiting the container to an image and running the exec workaround on the new image.

  19. jpereira commented on Mar 25, 2020

    @jpereira

    +1 for this feature

  20. vinaygunnam commented on Feb 22, 2021

    @vinaygunnam

    One other alternative to achieve what is being asked from this enhancement is to use a dockerignore and docker cp together. I would think that this is far more powerful than equipping docker cp with wildcard support.

    As an example, @Aypahyo's use case can be solved using this inverse dockerignore file to whitelist the files of interest.

    File: Dockerfile.copy.dockerignore

    # ignore everything
    *
    
    # except these artifacts of interest
    !**/TestResults/*.xml
    !**/coverage.opencover.xml
    !**/report-task.txt
    

    Essentially, we can use docker to create a context (via daemon sock bind + docker_cli) from inside the final container to suit our needs and copy it to the host via docker cp. Kind of meta!
    File: Dockerfile.copy

    ARG RESULT_IMAGE
    FROM ${RESULT_IMAGE}
    WORKDIR /temporary
    
    # copy with same file names
    COPY . .
    
    # copy with a different file name and/or different folder
    COPY src/run-2021-02-22-01-10/stats.log results/final.txt
    

    Finally,

    docker cp <COPY_IMAGE_CONTAINER>:/temporary/src <path-mapped-to-the-host-target>
    

    This allows to solve any complex "copy the result" scenarios using Docker's ability to tailor a context as needed.
    (ex: monorepo build output and test results)
    Also not that this addresses both the aspects of the proposal from OP => "wildcards" and "destination names".

    I'm no expert with Docker, so I'm looking for any feedback folks might have. Does this approach fall into one of these buckets?

    1. This is a bad idea and we should not use this because _____ (ex: perf, security, etc.).
    2. This does not work for all use cases such as ____.
    3. This is too complex and/or an overkill to solve the problem at hand.
  21. signalogic commented on Feb 18, 2022

    @signalogic

    Evidently, after 7.x years, as of 2022, the docker cp command still does not support wildcards. Is it possible to at least give a better error message than ""docker cp" requires exactly 2 arguments" ? That would at least save time vs hunting for status of wildcard support on various forums

  22. kevinkopf commented on Feb 12, 2023

    @kevinkopf

    Evidently, after 7.x years, as of 2022, the docker cp command still does not support wildcards. Is it possible to at least give a better error message than ""docker cp" requires exactly 2 arguments" ? That would at least save time vs hunting for status of wildcard support on various forums

    One more year
    And we're still there
    Whilst I'm getting older
    Getting gray hair

  23. proof-of-reality commented on Oct 19, 2023

    @proof-of-reality

    Wow, this is wild !

  24. debilin commented on Jan 17, 2024

    @debilin

    +1 🙏

  25. iamjjanga-ouo commented on Apr 23, 2024

    @iamjjanga-ouo

    I'm also stucked... is there anybody in 2025? ping..

  26. cektom commented on May 1, 2024

    @cektom

    +1 🙏

  27. StiliyanKushev commented on Jun 28, 2024

    @StiliyanKushev

    +1

  28. Jwrede commented on Oct 30, 2026

    @Jwrede

    Until docker cp supports this, I wrote a small CLI that adds wildcards on top of it (it can also be installed as a Docker CLI plugin, docker cpg): https://github.com/Jwrede/docker-cpg

    It takes the fixed directory in front of the first wildcard, streams it with docker cp CONTAINER:DIR/. - and extracts only the matching entries on the host. Nothing runs inside the container, so it also works on stopped containers and on images without sh or tar, where the docker exec ... tar workaround from this thread fails.

    docker-cpg "web:/var/log/app/*.log" logs/
    docker-cpg -e old "web:/var/log/**/*.log" logs/    # recursive, skip old/
    docker-cpg src/*.py config/ web:/app                # several sources in one call

    Limits: it reads the whole fixed directory and filters on the host, so web:/**/*.conf streams the entire container filesystem. * and ** skip dotfiles, as in the shell. With a wildcard the destination is always a directory. No container-to-container copy. Tested on Linux with Docker 27 and 28.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiAPIarea/cliClientkind/enhancementEnhancements are not bugs or new features but can improve usability or performance.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions