首页 文章

将文件从Docker容器复制到主机

提问于
浏览
985

我正在考虑使用Docker在持续集成(CI)服务器上构建我的依赖项,这样我就不必在代理本身上安装所有运行时和库 . 为了实现这一点,我需要将容器内部构建的构建工件复制回主机 .

那可能吗?

14 回答

  • 0

    要将文件从容器复制到主机,可以使用该命令

    docker cp <containerId>:/file/path/within/container /host/path/target
    

    这是一个例子:

    [jalal@goku scratch]$ sudo docker cp goofy_roentgen:/out_read.jpg .
    

    这里goofy_roentgen是我从以下命令获得的名称:

    [jalal@goku scratch]$ sudo docker ps
    [sudo] password for jalal:
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                            NAMES
    1b4ad9311e93        bamos/openface      "/bin/bash"         33 minutes ago      Up 33 minutes       0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp   goofy_roentgen
    
  • -1

    我使用PowerShell(Admin)使用此命令 .

    docker cp {container id}:{container path}/error.html  C:\\error.html
    

    Example

    docker cp ff3a6608467d:/var/www/app/error.html  C:\\error.html
    
  • 6

    如果您没有正在运行的容器,只有图像,并且假设您只想复制文本文件,则可以执行以下操作:

    docker run the-image cat path/to/container/file.txt > path/to/host/file.txt
    
  • 1
  • 19

    你不需要使用 docker run

    你可以用 docker create 做到这一点

    来自文档 The docker create command creates a writeable container layer over the specified image and prepares it for running the specified command. The container ID is then printed to STDOUT. This is similar to docker run -d except the container is never started.

    所以,你可以做到

    docker create -ti --name dummy IMAGE_NAME bash
    docker cp dummy:/path/to/file /dest/to/file
    docker rm -fv dummy
    

    在这里,你永远不会启动容器 . 这看起来对我有益 .

  • 1797

    我正在为使用Docker for Mac的任何人发布此信息 . 这对我有用:

    $ mkdir mybackup # local directory on Mac
    
     $ docker run --rm --volumes-from <containerid> \
        -v `pwd`/mybackup:/backup \  
        busybox \                   
        cp /data/mydata.txt /backup
    

    请注意,当我使用 -v 挂载时,会自动创建 backup 目录 .

    我希望有一天这对某人有用 . :)

  • 12

    大多数答案并未表明容器必须在 docker cp 工作之前运行:

    docker build -t IMAGE_TAG .
    docker run -d IMAGE_TAG
    CONTAINER_ID=$(docker ps -alq)
    # If you do not know the exact file name, you'll need to run "ls"
    # FILE=$(docker exec CONTAINER_ID sh -c "ls /path/*.zip")
    docker cp $CONTAINER_ID:/path/to/file .
    docker stop $CONTAINER_ID
    
  • 13

    作为更通用的解决方案,there's a CloudBees plugin for Jenkins to build inside a Docker container . 您可以从Docker注册表中选择要使用的映像,或者定义要构建和使用的Dockerfile .

    它会将工作区作为卷(使用适当的用户)安装到容器中,将其设置为工作目录,执行您请求的任何命令(在容器内) . 您还可以使用docker-workflow插件(如果您更喜欢基于UI的代码)使用image.inside(){}命令执行此操作 .

    基本上所有这些,烘焙到您的CI / CD服务器然后一些 .

  • 2

    在主机系统(容器外部)上创建数据目录,并将其安装到容器内可见的目录中 . 这会将文件放在主机系统上的已知位置,并使主机系统上的工具和应用程序可以轻松访问这些文件

    docker run -d -v /path/to/Local_host_dir:/path/to/docker_dir docker_image:tag
    
  • 10

    如果您只想从图像(而不是正在运行的容器)中提取文件,则可以执行以下操作:

    docker run --rm <image> cat <source> > <local_dest>

    这将打开容器,写入新文件,然后删除容器 . 但是,一个缺点是不保留文件权限和修改日期 .

  • 5

    创建要复制文件的路径,然后使用:

    docker run -d -v hostpath:dockerimag
    
  • 0

    挂载“卷”并将工件复制到那里:

    mkdir artifacts
    docker run -i -v ${PWD}/artifacts:/artifacts ubuntu:14.04 sh << COMMANDS
    # ... build software here ...
    cp <artifact> /artifacts
    # ... copy more artifacts into `/artifacts` ...
    COMMANDS
    

    然后,当构建完成且容器不再运行时,它已将构建中的工件复制到主机上的 artifacts 目录中 .

    编辑:

    CAVEAT:执行此操作时,您可能会遇到与当前正在运行的用户的用户ID匹配的docker用户的用户ID问题 . 也就是说, /artifacts 中的文件将显示为用户拥有的,其中包含在docker容器内使用的用户的UID . 解决这个问题的方法可能是使用调用用户的UID:

    docker run -i -v ${PWD}:/working_dir -w /working_dir -u $(id -u) \
        ubuntu:14.04 sh << COMMANDS
    # Since $(id -u) owns /working_dir, you should be okay running commands here
    # and having them work. Then copy stuff into /working_dir/artifacts .
    COMMANDS
    
  • 62

    tldr;

    $ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
    chown $(id -u):$(id -g) my-artifact.tar.xz
    cp -a my-artifact.tar.xz /host-volume
    EOF
    

    长...

    docker run 带有主机卷, chown 工件, cp 工件到主机卷:

    $ docker build -t my-image - <<EOF
    > FROM busybox
    > WORKDIR /workdir
    > RUN touch foo.txt bar.txt qux.txt
    > EOF
    Sending build context to Docker daemon  2.048kB
    Step 1/3 : FROM busybox
     ---> 00f017a8c2a6
    Step 2/3 : WORKDIR /workdir
     ---> Using cache
     ---> 36151d97f2c9
    Step 3/3 : RUN touch foo.txt bar.txt qux.txt
     ---> Running in a657ed4f5cab
     ---> 4dd197569e44
    Removing intermediate container a657ed4f5cab
    Successfully built 4dd197569e44
    
    $ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
    chown -v $(id -u):$(id -g) *.txt
    cp -va *.txt /host-volume
    EOF
    changed ownership of '/host-volume/bar.txt' to 10335:11111
    changed ownership of '/host-volume/qux.txt' to 10335:11111
    changed ownership of '/host-volume/foo.txt' to 10335:11111
    'bar.txt' -> '/host-volume/bar.txt'
    'foo.txt' -> '/host-volume/foo.txt'
    'qux.txt' -> '/host-volume/qux.txt'
    
    $ ls -n
    total 0
    -rw-r--r-- 1 10335 11111 0 May  7 18:22 bar.txt
    -rw-r--r-- 1 10335 11111 0 May  7 18:22 foo.txt
    -rw-r--r-- 1 10335 11111 0 May  7 18:22 qux.txt
    

    这个技巧有效,因为heredoc中的 chown 调用从正在运行的容器外部获取 $(id -u):$(id -g) 值;即,码头主机 .

    docker cp 的好处是:

    • 之前你没有 docker run --name 你的容器

    • 之后你不必 docker container rm

  • 3

    装载卷,复制工件,调整所有者ID和组ID:

    mkdir artifacts
    docker run -i --rm -v ${PWD}/artifacts:/mnt/artifacts centos:6 /bin/bash << COMMANDS
    ls -la > /mnt/artifacts/ls.txt
    echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -u)
    chown -R $(id -u):$(id -u) /mnt/artifacts
    COMMANDS
    

相关问题