Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wp-content is owned by root on creation #436

Closed
drewcovi opened this issue Sep 24, 2019 · 22 comments · Fixed by #503
Closed

wp-content is owned by root on creation #436

drewcovi opened this issue Sep 24, 2019 · 22 comments · Fixed by #503
Labels
question Usability question, not directly related to an error with the image

Comments

@drewcovi
Copy link

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 .
@wglambert wglambert added the question Usability question, not directly related to an error with the image label Sep 24, 2019
@wglambert
Copy link

If you mount the parent directory as well it should have appropriate permissions

#426 (comment)

So when just the subdirectories of wp-content/ are mounted it makes wp-content owned by root and docker-entrypoint.sh doesn't do a wordpress install as it detects present files and assumed the wp-content is fully populated

@drewcovi
Copy link
Author

So is that a workaround? It seems like a common need and something that could be checked for in entrypoint.sh

@wglambert
Copy link

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

@drewcovi
Copy link
Author

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.

@lapkritinis
Copy link

lapkritinis commented Oct 24, 2019

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.

@filipecorrea
Copy link

I changed my docker-compose.yml to mount wp-content instead of the child directories but the problem persists.

@thomasplevy
Copy link

thomasplevy commented Jan 16, 2020

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

@01e9
Copy link

01e9 commented Jan 16, 2020

The place to start experimenting/debugging

user="${APACHE_RUN_USER:-www-data}"
group="${APACHE_RUN_GROUP:-www-data}"

@diogoterremoto
Copy link

diogoterremoto commented Feb 17, 2020

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.

noisysocks added a commit to WordPress/gutenberg that referenced this issue Feb 24, 2020
Makes the WordPress content directories (wp-content, wp-content/plugins,
wp-content/themes) owned by the www-data user. This ensures that WordPress
can write to these directories.

This is necessary when running wp-env with `"core": null` because Docker
will automatically create these directories as the root user when binding
volumes during `docker-compose up`, and `docker-compose up` doesn't support
the `-u` option.

See docker-library/wordpress#436.
noisysocks added a commit to WordPress/gutenberg that referenced this issue Feb 28, 2020
Makes the WordPress content directories (wp-content, wp-content/plugins,
wp-content/themes) owned by the www-data user. This ensures that WordPress
can write to these directories.

This is necessary when running wp-env with `"core": null` because Docker
will automatically create these directories as the root user when binding
volumes during `docker-compose up`, and `docker-compose up` doesn't support
the `-u` option.

See docker-library/wordpress#436.
@michaelperrin
Copy link

I made some changes to fix this issue in #474

jorgefilipecosta pushed a commit to WordPress/gutenberg that referenced this issue Mar 2, 2020
Makes the WordPress content directories (wp-content, wp-content/plugins,
wp-content/themes) owned by the www-data user. This ensures that WordPress
can write to these directories.

This is necessary when running wp-env with `"core": null` because Docker
will automatically create these directories as the root user when binding
volumes during `docker-compose up`, and `docker-compose up` doesn't support
the `-u` option.

See docker-library/wordpress#436.
jorgefilipecosta pushed a commit to WordPress/gutenberg that referenced this issue Mar 2, 2020
Makes the WordPress content directories (wp-content, wp-content/plugins,
wp-content/themes) owned by the www-data user. This ensures that WordPress
can write to these directories.

This is necessary when running wp-env with `"core": null` because Docker
will automatically create these directories as the root user when binding
volumes during `docker-compose up`, and `docker-compose up` doesn't support
the `-u` option.

See docker-library/wordpress#436.
@wesleyguirra
Copy link

Any solution to it?

@chongma
Copy link

chongma commented Aug 28, 2020

this is still a problem for me

@chongma
Copy link

chongma commented Aug 28, 2020

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"

@tianon
Copy link
Member

tianon commented Aug 28, 2020

It would help to have a minimal example to reproduce the issue if you want us to look into it. 😉

@chongma
Copy link

chongma commented Sep 2, 2020

@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

@yosifkit
Copy link
Member

yosifkit commented Sep 2, 2020

everything gets owned by root

Are you using a new enough image? #503 was added for this exact use case (and built with docker-library/official-images#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’t 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# 

@chongma
Copy link

chongma commented Sep 3, 2020

@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

@yosifkit
Copy link
Member

yosifkit commented Sep 3, 2020

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 😢 (#436 (comment))

@chongma
Copy link

chongma commented Sep 4, 2020

@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

@chongma
Copy link

chongma commented Sep 4, 2020

i can confirm that if i use a volume it works fine

@yosifkit
Copy link
Member

yosifkit commented Sep 4, 2020

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.

@gsusI
Copy link

gsusI commented Oct 25, 2020

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.

Problem

The parent docker-entrypoint.sh is ran after your Dockerfile and entrypoint.sh, overwritting the permissions you set.

Solution

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"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Usability question, not directly related to an error with the image
Projects
None yet