If we don't want to run cypress/included
image as built-in default root
user, we can use node
user that already exists in the image thanks to the very base node
image. But, if that user creates any files on the host machine, then these files are owned by the node
user id and group that might NOT even be present on the host machine.
We want to run inside the Docker container as the non-root user from the host machine with the same id and group id. Then when the container exits, any new files are "magically" owned by the host machine's user.
Read Running Docker Containers as Current Host User for general approach. In general we are going to:
- find out the user id and group on the host machine
- build a custom Docker image from
cypress/included
image - in the custom image we will create a new user with matching user and group id (if possible)
- run tests as the new user which matches the user on the host machine
Any files generated by the new user during Cypress run will be owned the non-root user on the host machine.
See Dockerfile that you can build using build.sh. You can pass your own user and group ids via arguments, I will use default value 501 for the user id, which is my id on current Mac.
$ ./build.sh
...
id
uid=501(appuser) gid=999(appuser) groups=999(appuser)
So the appuser
inside the container has same user ID as my host user.
Let's demonstrate the permissions are set correctly. I will start the shell inside the container.
$ docker run -it -v $PWD/src:/test -w /test -u appuser --entrypoint /bin/sh cypress/example
$ ls -la
total 12
drwxr-xr-x 5 appuser appuser 160 Dec 18 20:26 .
drwxr-xr-x 1 root root 4096 Dec 18 20:33 ..
drwxr-xr-x 4 appuser appuser 128 Dec 18 20:09 cypress
-rw-r--r-- 1 appuser appuser 78 Dec 18 20:09 cypress.json
-rw-r--r-- 1 appuser appuser 58 Dec 18 20:09 index.html
Great, all files inside the container are mapped from the host machine - and yet they have the right user and group, since the numbers match the host user id. Here is for example the same folder on the host machine:
$ ls -la src
total 16
drwxr-xr-x 5 gleb staff 160 Dec 18 15:26 .
drwxr-xr-x 7 gleb staff 224 Dec 18 15:09 ..
drwxr-xr-x 4 gleb staff 128 Dec 18 15:09 cypress
-rw-r--r-- 1 gleb staff 78 Dec 18 15:09 cypress.json
-rw-r--r-- 1 gleb staff 58 Dec 18 15:09 index.html
We can run Cypress using test.sh to confirm the tests pass.
$ ./test.sh
Running tests against cypress/example
Running as a non-root user 'appuser' mapped to host user
++ docker run -it -v ...included-as-non-root-mapped/src:/test -w /test -u appuser cypress/example
The generated video of the test run is owned by the user on the host machine
$ ls -la src/cypress/videos/
total 64
drwxr-xr-x 3 gleb staff 96 Dec 18 15:35 .
drwxr-xr-x 4 gleb staff 128 Dec 18 15:09 ..
-rw-r--r-- 1 gleb staff 32299 Dec 18 15:35 spec.js.mp4