Sharing host OS www-data
directories as a volume is tricky for Alpine images. User ID (UID) and Group ID (GID) are different.
UID/GID | Ubuntu | Alpine |
---|---|---|
33 | www-data | xfs |
82 | - | www-data |
tl;dr run
chown 82:82 app.log
on Host OS.
Example - sharing sessions/logs directory
- php-fpm worker runs as www-data
- volume mounts a log
app.log
$ echo HOST > app.log
$ cat app.log
HOST
$ sudo chown www-data:www-data app.log
$ ls -l app.log
-rw-rw-r-- 1 www-data www-data 0 čen 22 09:21 app.log
$ ls -n app.log
-rw-rw-r-- 1 33 33 0 čen 22 09:21 app.log
- immediately works because
www-data
has same UID/GID on Host and Docker
docker run --rm -it \
--volume "$(realpath app.log):/var/www/html/app.log" \
--user www-data \
php:7.0-fpm sh
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ ls -l app.log
-rw-rw-r-- 1 www-data www-data 4 Jun 22 07:26 app.log
$ ls -n app.log
-rw-rw-r-- 1 33 33 4 Jun 22 07:26 app.log
$ echo DEBIAN >> app.log
$ cat app.log
HOST
DEBIAN
Permission denied
- www-data (UID82
) is trying to access xsf (UID33
) file
docker run --rm -it \
--volume "$(realpath app.log):/var/www/html/app.log" \
--user www-data \
php:7.0-fpm-alpine sh
$ id
uid=82(www-data) gid=82(www-data) groups=82(www-data)
$ ls -l app.log
-rw-rw-r-- 1 xfs xfs 5 Jun 22 08:24 app.log
$ ls -n app.log
-rw-rw-r-- 1 33 33 5 Jun 22 08:24 app.log
$ echo ALPINE >> app.log
sh: can't create app.log: Permission denied
$ cat /etc/passwd | grep www-data
www-data:x:82:82:Linux User,,,:/home/www-data:/bin/false
$ cat /etc/group | grep www-data
www-data:x:82:www-data
- use
chown
in Docker after:- a container has started
- file permissions have changed on Host OS
docker run --rm -it \
--volume "$(realpath app.log):/var/www/html/app.log" \
--user root \
php:7.0-fpm-alpine sh
$# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
$# chown www-data:www-data app.log
$# ls -l app.log
-rw-rw-r-- 1 www-data www-data 5 Jun 22 08:24 app.log
$# ls -n app.log
-rw-rw-r-- 1 82 82 5 Jun 22 08:24 app.log
$# echo ALPINE >> app.log
$# cat app.log
HOST
ALPINE
$# exit
# Host OS now has UID/GID 82 too
$ ls -l app.log
-rw-rw-r-- 1 82 82 12 čen 22 10:27 app.log
$ ls -n app.log
-rw-rw-r-- 1 82 82 12 čen 22 10:27 app.log
- USER - works if a container is running as a root
docker exec -u root -t container chown www-data:www-data app.log
- need to ensure that
www-data (82)
has access to whatever UID/GID from Host OS - the simplest solution is adding
www-data
toxsf
group in a custom docker imageaddgroup www-data xfs
cat > Dockerfile << EOF
FROM php:7.0-fpm-alpine
RUN addgroup www-data xfs
EOF
docker build --file Dockerfile --tag php-fpm-wwwdata:test ./
docker run --rm -it \
--volume "$(realpath app.log):/var/www/html/app.log" \
--user www-data \
php-fpm-wwwdata:test sh
$ id
uid=82(www-data) gid=82(www-data) groups=33(xfs),82(www-data)
$ ls -l app.log
-rw-rw-r-- 1 xfs xfs 12 Jun 22 08:27 app.log
$ ls -n app.log
-rw-rw-r-- 1 33 33 12 Jun 22 08:27 app.log
$ echo ALPINE >> app.log
$ cat app.log
Unfortunately no. Linux console works well, but the php-fpm work doesn't work! I came across many issues:
- php-fpm worker ignores secondary groups
- SessionHandler::write(): open(..., O_RDWR) failed: Permission denied
- Session data file is not created by your uid
It's a solvable. You can listen.group = xfs
. You can handle file permissions by chmod -R g+rw
and chown -R 82:www-data
. It's a lot of troubles for keeping a mapping between Ubuntu and Alpine OS. It's very complex and error-prone.
Linux file can be owned by a non-existent user! Don't try to map user names (www-data
), map the user ids. Set the UID from Docker image on Host OS. No custom docker image. No addgroup
. chown 82:82
. KISS.
sudo chown 82:82 app.log
docker run --rm -it \
--volume "$(realpath app.log):/var/www/html/app.log" \
--user www-data \
php:7.0-fpm-alpine sh
$ id
uid=82(www-data) gid=82(www-data) groups=82(www-data)
$ ls -l app.log
-rw-rw-r-- 1 www-data www-data 19 Jun 22 08:30 app.log
$ ls -n app.log
-rw-rw-r-- 1 82 82 19 Jun 22 08:30 app.log
$ echo ALPINE >> app.log
$ cat app.log
HOST
ALPINE
It works for us. No extra config inside Docker. Root user on Host OS can backup shared folders.
We don't mind "hacked" UID/GID on Host OS. So we've replaced www-data
by the corresponding UID.
# old code before introducing Alpine images
chown -R www-data:www-data $SOME_PATH
# new code
if [ -z "$HAS_ALPINE_OS" ]; then
chown -R 33:33 $SOME_PATH
else
chown -R 82:82 $SOME_PATH
fi
It seems so obvious in hindsight...
- Homogenize www-data between builds
- Add ability to mount volume as user other than root
- How to change the nginx process user of the official docker image nginx?
- I have a shared volume, that is used by multiple containers - php-fpm that I'm running as www-data and nginx. The owner of the files/directories in the shared volume is www-data:www-data and nginx has trouble accessing that.
- docker - example adding www-data user to alpine images