I'm trying to use ssh
to load a docker image file stored on a Windows 2022 machine to a Linux machine with docker.
From Windows WSL, this command works perfectly:
cat /mnt/c/temp/my_docker_image.tar.gz | ssh -l matt 192.168.1.250 docker image load
However, I don't want to install WSL just for this (I don't need it otherwise); I just want to use PowerShell. I tried this command in PowerShell and it hangs with PowerShell using up large amounts of memory.
Get-Content -Path C:\temp\my_docker_image.tar.gz -Raw -Encoding Byte | ssh -l matt 192.168.1.250 docker image load
Is there a way to get the PowerShell command working? Or a different command other than Get-Content?
I'm trying to use ssh
to load a docker image file stored on a Windows 2022 machine to a Linux machine with docker.
From Windows WSL, this command works perfectly:
cat /mnt/c/temp/my_docker_image.tar.gz | ssh -l matt 192.168.1.250 docker image load
However, I don't want to install WSL just for this (I don't need it otherwise); I just want to use PowerShell. I tried this command in PowerShell and it hangs with PowerShell using up large amounts of memory.
Get-Content -Path C:\temp\my_docker_image.tar.gz -Raw -Encoding Byte | ssh -l matt 192.168.1.250 docker image load
Is there a way to get the PowerShell command working? Or a different command other than Get-Content?
Share Improve this question asked Feb 8 at 4:21 MattMatt 4046 silver badges21 bronze badges 5 |1 Answer
Reset to default 1Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1) and PowerShell (Core) 7 up to v7.3.x only "speak text" when communicating with external programs such as
ssh
, resulting in misinterpretation of binary data.[1]In PowerShell (Core) 7 v7.4+,
[byte]
data now can be sent to external programs:# PowerShell 7.4+ only. # Note the use of -AsByteStream instead of -Encoding Byte Get-Content C:\temp\my_docker_image.tar.gz -AsByteStream | ssh -l matt 192.168.1.250 docker image load
Note the omission of
-Raw
, which is what makes the solution memory-efficient, because the bytes are relayed one by one, in a streaming fashion.That said, it is precisely this byte-by-byte processing that makes this this approach quite slow, so even in 7.4+ you may consider the alternative solution below (while use of
-Raw
is much faster, it invariably entails reading the entire file in memory, up front, which causes problems with large files, as in your case).
Workaround for Windows PowerShell and PowerShell (Core) 7 versions up to v7.3.x:
Take advantage of the fact that cmd.exe
's pipeline is a raw byte conduit (as in POSIX-compatible shells such as bash
), so pass an equivalent command line to it:
cmd /c 'type C:\temp\my_docker_image.tar.gz | ssh -l matt 192.168.1.250 docker image load'
As noted, you may choose to continue to use this approach in PowerShell 7.4+, for performance reasons.
For detailed background information, see the bottom section of this answer.
[1] Even if you read the input file as binary data (a [byte[]]
array), on sending this data through the pipeline it is treated as text in PowerShell versions before 7.4. (each [byte]
instance is converted to its decimal string representation, and the instances are separated with newlines).
-Encoding Byte
argument? So you would get something likeGet-Content -Path C:\temp\my_docker_image.tar.gz -Raw -AsByteStream
– vht981230 Commented Feb 8 at 5:25scp
first and then load the image.Get-Content
will try to read the entire file in memory. – Diego Torres Milano Commented Feb 8 at 6:16-AsByteStream
only works in PowerShell (Core) 7; Windows PowerShell requires-Encoding Byte
. Neither works as intended in this case in PowerShell versions lower than 7.4.0, because they don't allow you to send binary data through the pipeline. Also, the use of-Raw
is what causes the memory problems. – mklement0 Commented 2 days agoGet-Content
only reads the entire file into memory by opt-in via-Raw
(however, even omitting-Raw
won't help in this case, because Matt is running Windows PowerShell). – mklement0 Commented 2 days ago