ERROR: failed to build: failed to solve: process "/bin/sh -c ..." did not complete successfully: exit code: 1 is the last line of a failed RUN step, not the error itself. The command's own message sits a few lines higher, on the lines that carry the step number. Read it there, then rerun the command in a container started from the last stage that built.

In the case below the real error was mkdir: can't create directory '/app/data/logs': the parent folder did not exist. mkdir -p fixed it.

The error

#7 [final 1/1] RUN mkdir /app/data/logs && chown -R appuser /app/data
#7 0.359 mkdir: can't create directory '/app/data/logs': No such file or directory
#7 ERROR: process "/bin/sh -c mkdir /app/data/logs && chown -R appuser /app/data" did not complete successfully: exit code: 1
------
 > [final 1/1] RUN mkdir /app/data/logs && chown -R appuser /app/data:
0.359 mkdir: can't create directory '/app/data/logs': No such file or directory
------
Dockerfile:6
--------------------
   4 |
   5 |     FROM base AS final
   6 | >>> RUN mkdir /app/data/logs && chown -R appuser /app/data
   7 |     USER appuser
   8 |     CMD ["sh"]
--------------------
ERROR: failed to build: failed to solve: process "/bin/sh -c mkdir /app/data/logs && chown -R appuser /app/data" did not complete successfully: exit code: 1

Why it happens

A RUN line is handed to /bin/sh -c. When the shell exits with a code other than 0, the build stops and the last line reports only that code. The text the command printed is shown earlier: on the lines that start with the step number (#7 0.359) and again in the block between the two ------ lines. Build with --progress=plain so every line of the step is printed as plain text.

Here the step was mkdir /app/data/logs. mkdir without -p does not create missing parents, and /app/data did not exist, so it printed the message and returned 1. Because of && the chown never ran.

The fix

Build the stage before the failing step, then run the command in it by hand:

docker build --progress=plain --target base -t fix9-bld-c1-base .
...
PS> docker run --rm --name fix9-bld-c1run fix9-bld-c1-base sh -c "mkdir /app/data/logs"
mkdir: can't create directory '/app/data/logs': No such file or directory
exit code: 1
PS> docker run --rm --name fix9-bld-c1run fix9-bld-c1-base ls -la /app
total 8
drwxr-xr-x    2 root     root          4096 Oct 23 04:42 .
drwxr-xr-x    1 root     root          4096 Nov 10 03:21 ..
exit code: 0

The same error appears outside the build, and ls shows /app is empty. Try the change in the same container, then put it in the Dockerfile:

FROM alpine:latest AS base
WORKDIR /app
RUN adduser -D appuser

FROM base AS final
RUN mkdir -p /app/data/logs && chown -R appuser /app/data
USER appuser
CMD ["sh"]

The build ended with exit code: 0, and docker run --rm --name fix9-bld-c1chk fix9-bld-c1 ls -ld /app/data/logs printed the folder owned by appuser. The second-best route is to edit the line and rebuild after each guess; the container lets you try several commands in seconds.

How it was reproduced

A two-stage Dockerfile on alpine:latest (image id 294b683cb724), built with docker build --progress=plain -t fix9-bld-c1 . on Docker Desktop for Windows, client and engine 29.9.3, buildx v0.38.1. The commands were run from PowerShell 5.1; the image and container names are the test's own.

Frequently asked

Where is the real error when a Docker RUN step fails with exit code 1?
Above the last line. Look for the lines that start with the step number, such as #7 0.359, and the block between the two ------ lines; they hold what the command printed.
How do I see the full output of a failed docker build?
Add --progress=plain to docker build. The output of each RUN step is then printed line by line instead of being folded away.
How do I debug a failing RUN step in a Dockerfile?
Build the stage before it with --target, run a container from that image and type the command by hand. Fix it there, then copy the working line back into the Dockerfile.

More decoded errors in the Fixes category. When the code above the last line is 127 rather than 1, see '/bin/sh: 1: curl: not found' and exit code 127.