It seems we should be able to mount themes and plugins and uploads separately, but for some reason it appears that when I remove and re-create wordpress using docker-compose, wp-content is always owned by root.
wordpress:
depends_on:
- db
image: wordpress:latest
container_name: wordpress
restart: always
volumes:
- ./wordpress/themes:/var/www/html/wp-content/themes:rw
- ./wordpress/plugins:/var/www/html/wp-content/plugins:rw
- ./wordpress/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: xxx
WORDPRESS_DB_PASSWORD: xxx
WORDPRESS_DB_NAME: xxx
VIRTUAL_HOST: xxx
-rw-r--r-- 1 www-data www-data 4.7K Nov 30 2017 wp-trackback.php
-rw-r--r-- 1 www-data www-data 8.3K Nov 30 2017 wp-mail.php
-rw-r--r-- 1 www-data www-data 3.3K Nov 30 2017 wp-load.php
-rw-r--r-- 1 www-data www-data 369 Nov 30 2017 wp-blog-header.php
-rw-r--r-- 1 www-data www-data 420 Nov 30 2017 index.php
-rw-r--r-- 1 www-data www-data 3.0K Aug 17 2018 xmlrpc.php
-rw-r--r-- 1 www-data www-data 20K Jan 1 2019 license.txt
-rw-r--r-- 1 www-data www-data 3.8K Jan 9 2019 wp-cron.php
-rw-r--r-- 1 www-data www-data 6.8K Jan 12 2019 wp-activate.php
-rw-r--r-- 1 www-data www-data 2.5K Jan 16 2019 wp-links-opml.php
-rw-r--r-- 1 www-data www-data 31K Jan 16 2019 wp-signup.php
-rw-r--r-- 1 www-data www-data 2.3K Jan 21 2019 wp-comments-post.php
-rw-r--r-- 1 www-data www-data 19K Mar 28 19:04 wp-settings.php
-rw-r--r-- 1 www-data www-data 7.3K Apr 8 22:59 readme.html
-rw-r--r-- 1 www-data www-data 39K Jun 10 13:34 wp-login.php
drwxr-xr-x 9 www-data www-data 4.0K Sep 5 01:08 wp-admin
drwxr-xr-x 20 www-data www-data 12K Sep 5 01:08 wp-includes
drwxr-xr-x 1 root root 4.0K Sep 12 09:32 ..
drwxr-xr-x 4 root root 4.0K Sep 24 02:17 wp-content
-rw-r--r-- 1 www-data www-data 234 Sep 24 02:17 .htaccess
-rw-r--r-- 1 www-data www-data 2.8K Sep 24 02:17 wp-config-sample.php
-rw-r--r-- 1 www-data www-data 3.2K Sep 24 02:17 wp-config.php
drwxrwxrwx 5 www-data www-data 4.0K Sep 24 02:17 .
If you mount the parent directory as well it should have appropriate permissions
https://github.com/docker-library/wordpress/issues/426#issuecomment-527581895
So when just the subdirectories of
wp-content/are mounted it makeswp-contentowned by root anddocker-entrypoint.shdoesn't do a wordpress install as it detects present files and assumed thewp-contentis fully populated
So is that a workaround? It seems like a common need and something that could be checked for in entrypoint.sh
The parent wp-content directory doesn't exist in the image before the entrypoint is executed. So when subdirectories are mounted under it, then it needs to be created and is done so as root
makes sense. i just assumed there could be a one line script to just check for that folder afterwards and chown accordingly... but I'm admittedly somewhat green here.
I support it.. I do it a bit differently - I copy in advance wp-content folder and my chown commands gets totally ignored:
Here is my dockerfile:
FROM wordpress:5-php7.1-apache
COPY files/ /var/www/html
RUN chown -R www-data:www-data /var/www/html
I still get everything as root:root
Running under ECS fargate, there is no option to mount anything.
I changed my docker-compose.yml to mount wp-content instead of the child directories but the problem persists.
Does anyone have a working example of a docker-compose.yml that actually allows mounting a shared theme/plugin without causing permission issues in the docker container?
I've been running in circles for a long time now trying to switch to Docker for automated e2e testing and I just can't get past these permissions issues.
I now have it so it's mounting directories as 1000:1000 (the uid/gid of my host user) but the filesystem still doesn't work right as a result.
Edit: word
The place to start experimenting/debugging
I'm my case, because I'm only binding volumes in docker-compose, I've solved the issue by chowning before running Apache, like this:
command: bash -c "/bin/chown -R www-data:www-data /var/www/html && apache2-foreground"
EDIT: For some reason, the above doesn't work, as it fails to copy the contents from /usr/src/wordpress on container first run.
I made some changes to fix this issue in #474
Any solution to it?
this is still a problem for me
it works if i add to my docker-compose.yml
command: /bin/sh -c "chown www-data:www-data wp-content wp-content/plugins wp-content/themes && exec apache2-foreground"
It would help to have a minimal example to reproduce the issue if you want us to look into it. :wink:
@tianon this is the docker-compose.yml that worked for me:
version: '3.1'
services:
homeconvey:
image: wordpress
restart: always
environment:
WORDPRESS_DB_HOST: $WORDPRESS_DB_HOST
WORDPRESS_DB_USER: $WORDPRESS_DB_USER
WORDPRESS_DB_PASSWORD: $WORDPRESS_DB_PASSWORD
WORDPRESS_DB_NAME: $WORDPRESS_DB_NAME
WORDPRESS_TABLE_PREFIX: $WORDPRESS_TABLE_PREFIX
# WORDPRESS_AUTH_KEY:
# WORDPRESS_SECURE_AUTH_KEY:
# WORDPRESS_LOGGED_IN_KEY:
# WORDPRESS_NONCE_KEY:
# WORDPRESS_AUTH_SALT:
# WORDPRESS_SECURE_AUTH_SALT:
# WORDPRESS_LOGGED_IN_SALT:
# WORDPRESS_NONCE_SALT:
# WORDPRESS_DEBUG:
# WORDPRESS_CONFIG_EXTRA:
ports:
- '8080:80'
volumes:
- $VOLUME_PATH:/var/www/html
- /path/to/my/theme/:/var/www/html/wp-content/themes/homeconveytheme/:ro
- /path/to/my/plugin/:/var/www/html/wp-content/plugins/homeconveyplugin/:ro
command: /bin/sh -c "chown www-data:www-data wp-content wp-content/plugins wp-content/themes && exec apache2-foreground"
networks:
- mariadb-docker_backend
networks:
mariadb-docker_backend:
external: true
i am using docker to be able to see my plugin and theme read only during development.
without the chown command it seems everything gets owned by root so the installation cannot install any plugins or updates or anything. seems to happen when linking the bottom 2 volumes
everything gets owned by root
Are you using a new enough image? https://github.com/docker-library/wordpress/pull/503 was added for this exact use case (and built with https://github.com/docker-library/official-images/pull/8200). You'll likely need to have an empty $VOLUME_PATH to be able it to use it (and nocopy: false on the volume options if it is a mounted folder and not a docker volume)
When creating bind mounts, using the long syntax requires the referenced folder to be created beforehand. Using the short syntax creates the folder on the fly if it doesn鈥檛 exist.
- https://docs.docker.com/compose/compose-file/#long-syntax-3
So, if you use a host path in a docker-compose.yml for volumes and it does not already exist on the host, then dockerd will create it for you as root owned. If you create the directory first docker will not change the permissions or ownership and everything will just work (assuming the www-data user has access to the mounted directory & files).
wordpress:
image: wordpress
volumes:
- './theme:/var/www/html/wp-content/themes/homeconveytheme/:ro'
- './plugin:/var/www/html/wp-content/plugins/homeconveyplugin/:ro'
Not pre-creating the directories:
$ docker pull wordpress
Using default tag: latest
latest: Pulling from library/wordpress
...
Digest: sha256:93ee786387237f25705610977d5f506c87ea99b1f207aa2441a027b2b5f8a7a2
Status: Downloaded newer image for wordpress:latest
docker.io/library/wordpress:latest
$ docker-compose -f docker-compose.yml run wordpress bash
root@281136d991cb:/var/www/html# ls -la
total 12
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 .
drwxr-xr-x 1 root root 4096 Aug 5 04:17 ..
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:00 wp-content
root@281136d991cb:/var/www/html# ls -la wp-content/
total 16
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:00 .
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 ..
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 plugins
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 themes
root@281136d991cb:/var/www/html# ls -la wp-content/*
wp-content/plugins:
total 12
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 .
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:00 ..
drwxr-sr-x 2 root root 4096 Sep 2 16:59 homeconveyplugin
wp-content/themes:
total 12
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:00 .
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:00 ..
drwxr-sr-x 2 root root 4096 Sep 2 16:59 homeconveytheme
Pre-creating the directories:
$ sudo rmdir plugin/ theme/
$ mkdir plugin/ theme/
$ ls -ln
total 12
-rw-rw-r-- 1 1000 1000 960 Sep 2 09:59 docker-compose.yml
drwxr-sr-x 2 1000 1000 4096 Sep 2 10:06 plugin
drwxr-sr-x 2 1000 1000 4096 Sep 2 10:06 theme
$ docker-compose -f docker-compose.yml run wordpress bash
root@b1f7239f8720:/var/www/html# ls -la wp-content/*
wp-content/plugins:
total 12
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:07 .
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:07 ..
drwxr-sr-x 2 1000 1000 4096 Sep 2 17:06 homeconveyplugin
wp-content/themes:
total 12
drwxrwxrwx 3 www-data www-data 4096 Sep 2 17:07 .
drwxrwxrwx 4 www-data www-data 4096 Sep 2 17:07 ..
drwxr-sr-x 2 1000 1000 4096 Sep 2 17:06 homeconveytheme
root@b1f7239f8720:/var/www/html#
@yosifkit was your $VOLUME_PATH folder completely empty before running docker-compose build? the wp-content directory and sub folders get created as root on my end. i am pretty sure i am using the latest because i only just started using it in august
I was using an anonymous docker volume and not a host path for /var/www/html. If you are using a host path and it is empty before starting, then you need to use the long syntax along with volume: { nocopy: false } (https://docs.docker.com/compose/compose-file/#long-syntax-3).
volumes:
- type: bind
source: $VOLUME_PATH
target: /var/www/html
volume:
nocopy: true
EDIT: this doesn't work :cry: (https://github.com/docker-library/wordpress/issues/436#issuecomment-687290394)
@yosifkit in order to use long form i had to change to version 3.3 at the top of the docker compose file. i cleared the directory and ran it. there is no change as the wp-content directory is still owned by root. i am not even sure if the volume->nocopy applies to a type of bind as it isn't a volume? i might consider switching to a volume as i don't really need to bind to filesystem. or otherwise i can just stick with my solution. thanks
i can confirm that if i use a volume it works fine
Yeah, apparently Docker thought it wouldn't be useful to allow nocopy to apply to a bind mount (I assumed that it would apply).
So if you need to mount both the base wordpress dir, and custom themes/plugins directories, then the empty directories need to be created within the wordpress directory with the correct permissions. Alternatively, you could just use one mount and put the custom themes directly in your wordpress folder (assuming you didn't need the ro on your themes/plugins).
i can confirm that if i use a volume it works fine
Or just use a named docker volume.
I originally published this solution in Stackoverflow, but because they're referring to a similar issue I'll publish it also here in case it helps someone.
The parent docker-entrypoint.sh is ran after your Dockerfile and entrypoint.sh, overwritting the permissions you set.
Custom entrypoint executing a delayed command that sets the ownership after docker-entrypoint.sh has ran.
Your Dockerfile
FROM wordpress:php7.4-apache
[...]
ENTRYPOINT ["/entrypoint.sh"]
Your entrypoint.sh
# In 10 seconds set the ownership
$(sleep 10 && chown -R www-data:www-data /var/www/html/) &
# Run the parent's ENTRYPOINT and CMD as defined in its Dockerfile
# (https://github.com/gsusI/wordpress/blob/master/php7.4/apache/Dockerfile)
docker-entrypoint.sh apache2-foreground # run parent entrypoint.
Note: Invoking the parent's ENTRYPOINT and CMD manually means that if the parent Dockerfile alters its last two lines this solution might not work properly.
Therefore is recommendable that wheneber updating the your
FROM, you check the parent's Dockerfile to verify the last two lines are still:ENTRYPOINT ["docker-entrypoint.sh"] CMD ["apache2-foreground"]
Most helpful comment
I support it.. I do it a bit differently - I copy in advance wp-content folder and my chown commands gets totally ignored:
Here is my dockerfile:
I still get everything as root:root
Running under ECS fargate, there is no option to mount anything.