WSL containers: build an image and save files to Windows

Once you can run a ready-made image with WSL containers, the next step is often to put your own files into an image. There is another practical question: how do you keep a file produced by the container on Windows after the container exits?

This example builds a small image containing a shell script, then writes a result into a dedicated Windows folder. You can follow the path of the files without starting a web server.

Create a working folder

Use PowerShell on Windows 11 with WSL containers already working. These examples use the syntax available in WSLc 3.0.1. Follow Microsoft’s setup guide to get to the point where you can run a container.

Open PowerShell in a writable location and create a new folder for this example. If the name is already in use, choose a new one rather than putting the sample into an existing project.

New-Item -ItemType Directory -Path './wslc-file-demo' -ErrorAction Stop | Out-Null
Set-Location './wslc-file-demo'

Save two files in this folder with a text editor: Dockerfile and hello.sh. Check that the first filename has not become Dockerfile.txt.

Put this in Dockerfile:

FROM alpine:3.22
WORKDIR /app
COPY hello.sh /app/hello.sh
CMD ["/bin/sh", "/app/hello.sh"]

Put this in hello.sh:

printf 'Hello from WSL containers\n'

Save hello.sh as UTF-8 without a BOM, using LF line endings. The image reads it with /bin/sh, so this example does not need a shebang or an executable permission change.

FROM selects the Alpine Linux base image, WORKDIR sets the working directory inside the container, and COPY adds the script. CMD supplies the command to run when the container starts. Copying a file into the image does not keep it synchronized with the original Windows file.

Build and run the image

Run these commands in the folder containing the two files. The final . selects the build context, while wslc-file-demo:1 is the image name and tag. The first build needs access to the public registry to obtain Alpine.

wslc build --progress plain -t wslc-file-demo:1 .
wslc run --rm --network none --cpus 1 --memory 128M wslc-file-demo:1

After a successful build, the script prints:

Hello from WSL containers

If the build fails, resolve that error before running the image. --rm removes the container when it exits, while the image remains available for another run. --network none disables networking during the run; it does not disable image downloads during the build. This example publishes no ports.

--cpus 1 and --memory 128M set runtime resource limits. Some environments warn that swap limits are unavailable, so the memory option does not necessarily limit swap as well.

Write the result into a Windows folder

A file saved only in the container’s writable layer is lost when that container is removed. A bind mount gives the container a path into a host folder, allowing it to save the result directly on Windows.

Continue in the same PowerShell session. Create a new share folder for this sample and turn its path into an absolute path with Resolve-Path. The mount makes it available inside the container at /data.

New-Item -ItemType Directory -Path './share' -ErrorAction Stop | Out-Null
$sharePath = (Resolve-Path -LiteralPath './share').Path
$mount = "type=bind,source=$sharePath,target=/data"
wslc run --rm --network none --cpus 1 --memory 128M --mount $mount wslc-file-demo:1 /bin/sh -c 'printf "saved by container\n" > /data/result.txt; cat /data/result.txt'
saved by container

The command after the image name replaces CMD for this run. It writes result.txt and then prints the contents with cat. It does not modify hello.sh or rebuild the image.

When the container exits, read the file from Windows:

Get-Content -LiteralPath './share/result.txt'
saved by container

Seeing the same text means the container wrote into the dedicated Windows folder. Bind mounts are writable by default, so pass only the folder needed for the task rather than your whole Documents folder. Running the write command again overwrites result.txt.

Choose where files should live

To change what the script does, edit hello.sh and build the image again with the same build command. A file added with COPY reflects its contents at build time.

To keep a result for use on Windows, save it under the mounted path, such as /data. This lets you remove a temporary container while retaining its output. Choose a host location for files you want to keep instead of treating the container’s writable layer as a long-term backup.

References: Microsoft Learn: build and run WSL containers; Docker Docs: bind mounts.