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

Upgrade of plugins doesn't work if they are on a mounted volume #352

Closed
controlcde opened this issue Dec 3, 2018 · 10 comments
Closed

Upgrade of plugins doesn't work if they are on a mounted volume #352

controlcde opened this issue Dec 3, 2018 · 10 comments
Labels
question Usability question, not directly related to an error with the image

Comments

@controlcde
Copy link

controlcde commented Dec 3, 2018

I´m using docker compose to create all my wordpress container. If I create my container with mount volumes for plugins, themes and languages I can´t update/upgrade all of this. Here are my configurations:

 wordpress:
    image: wordpress:latest
    volumes:
      - ./wp-content/plugins:/var/www/html/wp-content/plugins
      - ./wp-content/themes:/var/www/html/wp-content/themes
      - ./wp-content/languages:/var/www/html/wp-content/languages
      - ./wp-content/uploads:/var/www/html/wp-content/uploads

Normally all setting should be fixed with creation, but I think it doesn't work well.

docker exec -it wordpress ls -la
total 212
drwxrwxrwx  5 www-data www-data  4096 Dec  3 13:06 .
drwxr-xr-x  1 root     root      4096 Nov 28 22:47 ..
-rw-r--r--  1 www-data www-data   235 Dec  2 09:53 .htaccess
-rw-r--r--  1 www-data www-data   418 Sep 25  2013 index.php
-rw-r--r--  1 www-data www-data 19935 Jan  6  2018 license.txt
-rw-r--r--  1 www-data www-data    71 Apr 25  2018 php.ini
-rw-r--r--  1 www-data www-data  7415 Mar 18  2018 readme.html
-rw-r--r--  1 www-data www-data  5458 May  1  2018 wp-activate.php
drwxr-xr-x  9 www-data www-data  4096 Aug  2 20:39 wp-admin
-rw-r--r--  1 www-data www-data   364 Dec 19  2015 wp-blog-header.php
-rw-r--r--  1 www-data www-data  1889 May  2  2018 wp-comments-post.php
-rw-r--r--  1 www-data www-data  2853 Dec 16  2015 wp-config-sample.php
-rw-r--r--  1 www-data www-data  3730 Dec  2 11:01 wp-config.php
drwxr-xr-x  7 root          root             4096 Dec  3 13:05 wp-content
-rw-r--r--  1 www-data www-data  3669 Aug 20  2017 wp-cron.php
drwxr-xr-x 18 www-data www-data 12288 Aug  2 20:39 wp-includes
-rw-r--r--  1 www-data www-data  2422 Nov 21  2016 wp-links-opml.php
-rw-r--r--  1 www-data www-data  3306 Aug 22  2017 wp-load.php
-rw-r--r--  1 www-data www-data 37794 Jul 16 14:14 wp-login.php
-rw-r--r--  1 www-data www-data  8048 Jan 11  2017 wp-mail.php
-rw-r--r--  1 www-data www-data 16246 Oct  4  2017 wp-settings.php
-rw-r--r--  1 www-data www-data 30091 Apr 29  2018 wp-signup.php
-rw-r--r--  1 www-data www-data  4620 Oct 23  2017 wp-trackback.php
-rw-r--r--  1 www-data www-data  3065 Aug 31  2016 xmlrpc.php

If I temporary disable the volumes the wp-content directory has the right permissions.

@controlcde controlcde changed the title Upgrade of plugins doesn#t work if they are on a mounted volume Upgrade of plugins doesn't work if they are on a mounted volume Dec 3, 2018
@wglambert wglambert added the Issue label Dec 3, 2018
@strindhaug
Copy link

strindhaug commented Dec 4, 2018

I seem to have the same or a related issue...

I've been using a dockerfile like this (slightly shortened and anonymized):

FROM wordpress:4.9.8-php7.2-apache
RUN apt-get update && apt-get install -y wget unzip

# copy custom plugin
COPY plugins/somecustomplugin /usr/src/wordpress/wp-content/plugins/somecustomplugin
# copy configs
COPY wp-config-sample.php /usr/src/wordpress/wp-config-sample.php
COPY ./htaccess /usr/src/wordpress/.htaccess

COPY supercache/advanced-cache.php /usr/src/wordpress/wp-content/advanced-cache.php
COPY supercache/wp-cache-config.php /usr/src/wordpress/wp-content/wp-cache-config.php

# copy theme
COPY mythemename /usr/src/wordpress/wp-content/themes/mythemename

# install plugins

RUN wget https://downloads.wordpress.org/plugin/simple-image-sizes.3.2.0.zip -O /tmp/simple-image-sizes.zip \
&& unzip /tmp/simple-image-sizes.zip -d /usr/src/wordpress/wp-content/plugins/

RUN wget https://downloads.wordpress.org/plugin/wp-super-cache.1.6.4.zip -O /tmp/wp-super-cache.zip \
&& unzip /tmp/wp-super-cache.zip -d /usr/src/wordpress/wp-content/plugins/
# etc. etc...

Today I've updated a few plugin without changing the tag number for wordpress itself, and now it doesn't update and wp-supercache is complaining:

Error: Your cache directory (/var/www/html/wp-content) did not exist and couldn’t be created by the web server. Check /var/www/html/wp-content permissions.
Cannot continue... fix previous problems and retry.

etc.

Has someone changed the image without changing the tag somehow?

I thought the point of tags were that they should be immutable, but it seems even a fairly specific tag such as 4.9.8-php7.2-apache can change without warning? If using 4.9.8-php7.2-apache isn't deterministic at all I might as well just use the latest tag; since specific tags apparently may just change at any time anyway.

I tried manually chmod'ing some specific plugins to enable them to update, such as:
RUN chmod 766 /usr/src/wordpress/wp-content/plugins/akismet/
but it didn't work. I considered just recursively chmod the whole /usr/src/wordpress/wp-content but that seems like a very dirty hack, and it should not be needed as every other wordpress site we host use much the same setup and has no problems updating itself (and neither did this specific site before i changed one version number for a plugin and rebuilt it)

@strindhaug
Copy link

strindhaug commented Dec 4, 2018

Actually I just tried adding

RUN chmod 766 -R /usr/src/wordpress/wp-content

at the bottom of my dockerfile, and this made things worse, all I now get at /wp-admin/ is:


Warning: include(/usr/src/wordpress/wp-content/plugins/wp-super-cache/wp-cache-base.php): failed to open stream: Permission denied in /var/www/html/wp-content/plugins/wp-super-cache/wp-cache.php on line 92

Warning: include(): Failed opening '/usr/src/wordpress/wp-content/plugins/wp-super-cache/wp-cache-base.php' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/wp-content/plugins/wp-super-cache/wp-cache.php on line 92

Warning: include_once(/usr/src/wordpress/wp-content/plugins/wp-super-cache/ossdl-cdn.php): failed to open stream: Permission denied in /var/www/html/wp-content/plugins/wp-super-cache/wp-cache.php on line 116

Warning: include_once(): Failed opening '/usr/src/wordpress/wp-content/plugins/wp-super-cache/ossdl-cdn.php' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/wp-content/plugins/wp-super-cache/wp-cache.php on line 116

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/wp-super-cache/wp-cache.php:92) in /var/www/html/wp-includes/pluggable.php on line 1219

Btw, I'm not even sure if our setup really has the plugin dirs etc in a "mounted volume" the only mention of
/var/www/html/wp-content anywhere in my config is this part of my statefulset.yml:

        volumeMounts:
        - name: mysite-storage
          mountPath: /var/www/html/wp-content/uploads/

and it's supposed to only map the uploads dir to a persistent volume.

@strindhaug
Copy link

strindhaug commented Dec 4, 2018

Ah... Found this article: https://renovatebot.com/blog/docker-mutable-tags Weirdly, it seems that docker tags are not meant to be immutable. (They really should have called them "branches" then, and displayed a list of digests next to each branch on dockerhub if you ask me).

Anyway...
If you are having this issue, you can solve it temporarily by pinning the version to a digest of a previously successful build, like so:

FROM wordpress:4.9.8-php7.2-apache@sha256:54ccbf55f2f303caae2aa8ebb644796b9240a0541831c0ac51bf372de008da24

There are probably newer versions that work, but this is the digest that happened to be used last time I built my site ca. 2 months ago.

Using this I can now update translations and plugins again, and supercache is not complaining anymore.
I'll probably start pinning all my docker files from now on.

@wglambert wglambert added question Usability question, not directly related to an error with the image and removed Issue labels Dec 4, 2018
@wglambert
Copy link

For the original issue did you set the correct permissions for those directories on the host, I'm not able to reproduce an issue when setting appropriate permissions/ownership
https://github.com/docker-library/docs/tree/master/wordpress#include-pre-installed-themes--plugins

Ensure read/write/execute permissions are in place for the user.

 

For @strindhaug's issue I'm not able to reproduce any problem either, I set appropriate permissions on the host directories and when they're copied into the container at /usr/src/wordpress their permissions remain appropriate. Then anything mounted there will be copied over to /var/www/html/ and the contents are modified with --owner "$user" --group "$group" so the only thing necessary is for appropriate permissions to be in place.

sourceTarArgs=(
--create
--file -
--directory /usr/src/wordpress
--owner "$user" --group "$group"
)
targetTarArgs=(
--extract
--file -
)
if [ "$user" != '0' ]; then
# avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted"
targetTarArgs+=( --no-overwrite-dir )
fi
tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"
echo >&2 "Complete! WordPress has been successfully copied to $PWD"
if [ ! -e .htaccess ]; then
# NOTE: The "Indexes" option is disabled in the php:apache base image
cat > .htaccess <<-'EOF'
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
EOF
chown "$user:$group" .htaccess

Updating akismet with it being owned by root, undergone a chmod 777, and being mounted to /usr/src/wordpress which will copy and chown to $user:$group in the container

$ ls -l | grep plugins
drwxrwxrwx 4 root     root     4096 Dec  4 13:42 plugins/

$ ls -l plugins
total 16
drwxrwxrwx 4 root root 4096 Dec  4 13:42 akismet/
drwxrwxrwx 7 root root 4096 Dec  4 13:42 gutenberg/
-rwxrwxrwx 1 root root 2230 Dec  4 13:42 hello.php*
-rwxrwxrwx 1 root root   28 Dec  4 13:42 index.php*

wordpress_plugin

The Dockerfile
FROM wordpress:4.9.8-php7.2-apache
RUN apt-get update && apt-get install -y wget unzip

# copy custom plugin
COPY plugins /usr/src/wordpress/wp-content/plugins
# copy configs
COPY wp-config-sample.php /usr/src/wordpress/wp-config-sample.php
COPY ./htaccess /usr/src/wordpress/.htaccess

# copy theme
COPY mythemename /usr/src/wordpress/wp-content/themes/mythemename

# install plugins

RUN wget https://downloads.wordpress.org/plugin/simple-image-sizes.3.2.0.zip -O /tmp/simple-image-sizes.zip \
&& unzip /tmp/simple-image-sizes.zip -d /usr/src/wordpress/wp-content/plugins/

RUN wget https://downloads.wordpress.org/plugin/wp-super-cache.1.6.4.zip -O /tmp/wp-super-cache.zip \
&& unzip /tmp/wp-super-cache.zip -d /usr/src/wordpress/wp-content/plugins/

@strindhaug
Copy link

strindhaug commented Dec 5, 2018

I'm not explicitly installing akismet, it's included in the standard wordpress install; so it's mode flags should be exactly as intended. I'm not even using it, but it's an example of a plugin that definitely should work straight out of the box since it's not something I'm modifying in any way from the wordpress image.

The build 2 moths ago was on 15. october so presumably the changes that made it stop working is somewhere in this diff here:
668fe24...master

The only obvious changes I notice besides some structural refactoring, is the removal of the argument --one-file-system from the tar command, and the addition of:

				# strip off any '#' symbol ('#1000' is valid syntax for Apache)
				pound='#'
				user="${user#$pound}"
				group="${group#$pound}"

to some code I do not understand at all.


All i know is that the digest as of 15. october:

FROM wordpress:4.9.8-php7.2-apache@sha256:54ccbf55f2f303caae2aa8ebb644796b9240a0541831c0ac51bf372de008da24

works just fine, and the current digest:

FROM wordpress:4.9.8-php7.2-apache@sha256:7e476394586459bb622d3f37448cd07e703ec6906257d232542f2f51ff073da7

does not.

BTW, plugins installed explicitly in my Dockerfile like so:

RUN wget https://downloads.wordpress.org/plugin/better-wp-security.7.2.0.zip -O /tmp/better-wp-security.zip \
&& unzip /tmp/better-wp-security.zip -d /usr/src/wordpress/wp-content/plugins/

has never been possible to update automatically, so presumably unzip doesn't set suitable mode flags; but I don't think subfolders of wp-content with weird mode flags should cause the wp-content folder itself to be write protected?


My Dockerfile is built using circle-ci, running within a alpine-based image, and deployed to a kubernetes cluster on aws, if that has any effect on it. (I should think it would not, since the whole point of docker images as far as I can tell is that they are self-contained images that should behave identically no matter where they're run. But I also naively thought that tags with a specific name should stay the same as well, so I guess I cannot trust my intuition with anything Docker related... ;) )

@strindhaug
Copy link

Maybe it's the --no-overwrite-dir that is causing the issues, see #351 (comment)

Presumably this prevents tar from updating flags on existing directories as well as overwriting them.
And since my statefulset maps a persistent volume at /var/www/html/wp-content/uploads/ then /var/www/html/wp-content/ has to exist and is probably initialized with a bad owner and/or permission flags.

@strindhaug
Copy link

strindhaug commented Dec 5, 2018

Oh, I think I've got it...
The argument --one-file-system probably prevented mounted volumes from being overwritten. Removing it in #345 probably caused tar to try to modify mounted volumes in /var/www/html/wp-content/ and the fix for this new issue (nevermind I don't think this makes any difference)

While #351 is preventing tar from creating access denied errors when modifying existing files, it also prevents tar from setting the correct owner on /var/www/html/wp-content/ itself.

If the current behavior is more useful, there should probably be added a few separate chown and/or chmod calls to the end of the wntrypoint.sh to ensure important directories like
/var/www/html/wp-content/ has the expected owners and flags even if they exists prior to copying wordpress.

This explains why my attempts at explicitly setting flags to /usr/src/wordpress/wp-content/ or subfolders and files had no effect on the newest version, since the --no-overwrite-dir argument prevents it from copying flags onto existing dirs anyway. (And my recursive chmod experiment probably failed cause it removed executable flags on important files or folders.)

@strindhaug
Copy link

strindhaug commented Dec 5, 2018

I guess both docker-compose and kubernetes when mounting volumes ensures the parent directories of the mountpath exists running mkdir -p /path/to/mount-point/ running as root, but the mounted volume itself probably already has the proper permissions from last time they were mounted.

@tianon
Copy link
Member

tianon commented Dec 5, 2018

@controlcde your deployment would probably be simpler if you just mounted the full wp-content directory from your host instead of each of the individual sub-directories (since there's not really much else in a normal wp-content directory anyhow)

I'm a little bit confused at the use case here (mounting just plugins and still expecting them to be able to update), but from what I can tell all the issues listed above are related to permissions, specifically on directories?

If the issue is that /var/www/html is a VOLUME, you might be interested in https://github.com/docker-library/docs/blob/589ea9cfe97a75ac30c0515d67d579f094a4955c/php/README.md#changing-documentroot-or-other-apache-configuration (which can change Apache's directory from /var/www/html over to something else that isn't a VOLUME, bypassing that restriction).

If you want to run a production WordPress instance within Docker, I would highly recommend mounting the entire WordPress directory as upstream recommends and letting WordPress auto-update DTRT automatically.

If you want new installs to have certain plugins pre-installed, put them under /usr/src/wordpress and they will be auto-copied to /var/www/html on first start.

The ability to mount/use plugins directly in /var/www/html/wp-content is frankly intended for plugin/theme development where updates certainly aren't something desirable.

Regardless of all this, setting appropriate permissions in an odd setup like that are the purview of the user and not something the image will automatically resolve for you.

For further help debugging your deployment or developing your Dockerfiles, I'd recommend the Docker Community Forums, the Docker Community Slack, or Stack Overflow.

@tianon tianon closed this as completed Dec 5, 2018
@strindhaug
Copy link

strindhaug commented Jan 16, 2019

In case someone else finds this issue and have the same problem as I had:

It works fine if you just move the mount-point for your uploads folder to just outside the wp-content content directory something like this:

Change the mountPath in k8s/statefulset.yml like this:

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: myappname
spec:
  replicas: 1
  serviceName: myappname
  template:
    metadata:
      labels:
        app: myappname
    spec:
      containers:
      - name: myappname
        # [...]
        volumeMounts:
        - name: myappname-storage
          # old value:
          # mountPath: /var/www/html/wp-content/uploads/
          # new value:
          mountPath: /var/www/html/uploads/
  volumeClaimTemplates:
  - metadata:
      name: myappname-storage
      # [...]

Add this line to wp-config-sample.php:

define('UPLOADS', 'uploads'); // use custom uploads mount point (default is "wp-content/uploads") 

(Note that unless you have some other url remapping configured, the image url will contain the text from the UPLOADS definition, like so:https://www.example.com/uploads/2016/04/example-logo-350x73.png, so if you care about how the url looks use something sensible as directory name. And dont have a trailing slash on the UPLOADS definition; it will still work but you'll get a strange double slash in the urls if you do.)

Don't use the pinned old version of wordpress I suggested above as a hack (though it's good to know about the option of using the digest to specify a version as a workaround if some other bug appears in an update on a previously working tag)

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
Development

No branches or pull requests

4 participants