Search code examples
dockerpowershellgithub-actionscopy-item

How to copy a file from within a Docker Container to the host


Problem

I am running .NET Framework SDK to run GitHub Actions to build Releases of a project. I need to be able to copy the built project files from the Docker Container to the host and beyond to an external server.

On a non-Docker runner I was able to use the following command in PowerShell to copy the files: Copy-Item -Path "./ReleaseFolder*" -Destination "\\SERVERNAME\Destination" -Recurse -Force -PassThru

However, when running from within Docker, I get the following error:

Copy-Item : Access is denied
At C:\actions-runner\_work\_temp\58a0d5f5-1c21-468a-9cc1-6add157ef7da.ps1:2 char:1
+ Copy-Item -Path "./ReleaseFolder*" -Destination "\\SERVERNAME\Destination"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Copy-Item], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.CopyItemCommand

Error: Process completed with exit code 1.

What I have tried

I have tried turning off my firewall to see if that is the issue, but no luck.

I have also tried using the IP Address of the host (which I am able to ping) Copy-Item -Path "./ReleaseFolder*" -Destination "\\192.168.0.1\Destination" -Recurse -Force -PassThru But I get the same error message.

Through some googling I found host.docker.internal but I am unable to even ping it.

I am aware of the concept of volumes as a potential solution, as discussed in this question. However, since I need to copy beyond the host, to an external server, this does not solve my problem.

How do I allow access for the Docker Container to copy files to its host and beyond? Or is there a different way that I should be doing this?


Solution

  • When building inside a container, the standard approach is:

    1. Create a directory on the host, like output/, where you want the files
    2. Mount output/ in the container, obviously as RW (or use volumes if you want), some place like /host_output/
    3. In your container, make sure it's saving the artifacts in /host_output/

    Your container will not be aware that anything special is happening, but when it naively builds into "just a directory", the files will "magically" appear on the host as well.

    If you have an existing container where you cannot mess with the Dockerfile, then you can pull out individual files with something like docker exec foo_container cat /container_output/some_file.bin > /host_output/some_file.bin (the > is not part of docker exec, it will run on the host's shell). This is most useful for troubleshooting, the mount method is much less tedious and error-prone.