dockerdockerfiledebiandocker-buildkit

"Read-only filesystem" error during docker build


I was following the "Build with Docker" guide from the official documentation (https://docs.docker.com/build/guide/test/), which suggests that one can utilize bind mounts to generate files during the build of a Docker image and export them to the filesystem.

However, I am running into the following error:

[lint-base 2/2] RUN --mount=type=bind,target=.     echo "test" > lint-result:
0.258 /bin/sh: 1: cannot create lint-result: Read-only file system
...
ERROR: failed to solve: process "/bin/sh -c echo \"test\" > lint-result" did not complete successfully: exit code: 2

Here is the relevant part of the Dockerfile:

FROM scratch as lint-base
RUN --mount=type=bind,target=. \
    echo "test" > lint-result

And this was the command for building this layer:

docker build --output=. --target=lint-base -t lint-debug --progress=plain .

I'm using Debian, and Docker was installed using apt. The Docker version is 25.0.4.

Is this permission issue stemming from the way I installed Docker, or is it normal that during docker builds, it is not allowed to write changes to the filesystem mounted by bind?


Solution

  • Even if you use a bind mount in a Dockerfile, it still can't write out files to the host.

    The Dockerfile RUN --mount=type=bind documentation notes

    A bind mount is read-only by default.

    which is consistent with the "read-only filesystem" error you're getting. There is an additional option to make it read-write, but (emphasis mine)

    rw,readwrite: Allow writes on the mount. Written data will be discarded.

    The documentation page you link to does say you can export test results

    ...no different[ly from] exporting binaries, as shown in the previous section of this guide

    More specifically the Export binaries documentation suggests a docker build --output=. option that can use the Docker image builder but produce artifacts on the host by exporting the container filesystem. If the image is built FROM scratch then "the container filesystem" will only include specific files you choose. That also means the image doesn't contain any tools at all, so you have to construct the files in an earlier build stage and COPY them into the final image.

    For your example this might look like:

    FROM ubuntu AS build
    WORKDIR /app
    RUN echo test > lint-result
    
    FROM scratch AS export
    COPY --from=build /app/lint-result /
    
    docker build --output=. --target=export .
    

    I probably wouldn't use Docker here, but instead a shell script or Makefile to work with code and create files on the host.