Wordpress: Adding custom volume changes wp-content owner to root

Created on 15 Dec 2018  路  8Comments  路  Source: docker-library/wordpress

I am using docker-compose to install WordPress.
When I add the volume with my custom developed theme, wp-content and wp-content/themes directories owner changes to root. So I can't upload images and update core.

Using docker just for developing I want to have ability to set my custom theme's owner to www-data, but I can't to set in on my host system, because I don't have such a system user.

version: '3'
services:
  database:
    image: mysql:5.7
    volumes:
        - database:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
    networks:
      - back

  wordpress:
    depends_on:
      - database
    image: wordpress:latest
    restart: always
    volumes:
      - wordpress:/var/www/html/wp-content:rw
      - ./app:/var/www/html/wp-content/themes/instapress:ro
    environment:
      WORDPRESS_DB_HOST: database:3306
      WORDPRESS_DB_PASSWORD: wordpress
    ports:
      - 80:80
    networks:
      - back

volumes:
  database: {}
  wordpress: {}

networks:
  back:

Help me to understand how I can change dynamically my custom theme directory owner, please

docker

question

All 8 comments

You're running Docker as the root user, I'm guessing Docker made your wordpress named volume owned by root somewhere along the way, however I'm not able to reproduce your issue even while running docker as root. I'd recommend adding a non-superuser to the docker group and using that. Using a named volume shows the /var/www/html/wp-content/ directory owned by www-data for me.

version: "3"

services:

 mysql:
    image: mysql:5.7
    volumes:
       - ./mysql/data:/var/lib/mysql
    environment:
       MYSQL_DATABASE: exampledb
       MYSQL_USER: exampleuser
       MYSQL_PASSWORD: examplepass
       MYSQL_RANDOM_ROOT_PASSWORD: '1'

 wordpress:
    image: wordpress:latest
    ports:
      - 8080:80
    volumes:
            - wp-content:/var/www/html/wp-content:rw
            - ./app:/var/www/html/wp-content/themes/instapress:ro
    environment:
       WORDPRESS_DB_HOST: mysql
       WORDPRESS_DB_USER: exampleuser
       WORDPRESS_DB_PASSWORD: examplepass
       WORDPRESS_DB_NAME: exampledb

volumes:
  wp-content:
$ docker-compose up -d
Creating network "wordpress-358_default" with the default driver
Creating wordpress-358_wordpress_1 ... done
Creating wordpress-358_mysql_1     ... done
$ docker exec -it wordpress-358_wordpress_1 ls -l /var/www/html
total 196
-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  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  2764 Dec 17 18:27 wp-config-sample.php
-rw-r--r--  1 www-data www-data  3156 Dec 17 18:27 wp-config.php
drwxr-xr-x  4 www-data www-data  4096 Aug  2 20:39 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

Thanks for reply @wglambert.

I am using macOS docker version. So it seems that I have no docker group at all.
Anyway I will try to dig this way.

I finally found a solution.
My app directory for some reason has extra attribute com.docker.owner.
If you delete this attribute with xattr -c app command, permissions will set correctly.

Related support. Hope it helps.

Hi @antonlukin, I'm having the same issue, which app directory are you reffering to?

@ericmulder take a look at my first message code, please.
I was talking about this code:

volumes:
      - wordpress:/var/www/html/wp-content:rw
      - ./app:/var/www/html/wp-content/themes/instapress:ro

Anyway I still haven't solved this problem.
You can try to upgrade docker-compose file this way to solve the problem:

https://github.com/WordPress/health-check/blob/master/docker-compose.yml#L40

I am experiencing the same thing. I am mounting

volumes:
      - wp-themes:/var/www/html/wp-content/themes

which results in the folder wp-content being owned by root, so now www-data has no write permissions on the uploads and plugins folder.

I can find no solution :(

@ericmulder take a look at my first message code, please.
I was talking about this code:

volumes:
      - wordpress:/var/www/html/wp-content:rw
      - ./app:/var/www/html/wp-content/themes/instapress:ro

Anyway I still haven't solved this problem.
You can try to upgrade docker-compose file this way to solve the problem:

https://github.com/WordPress/health-check/blob/master/docker-compose.yml#L40

I'm confused. What does the environment have to do with it?

Ok, I will attempt to make the permissions clear when using volumes. Here are Docker's "basic" rules for folder permissions (and ownership):

Named or unnamed Volumes:

  • examples:
    console $ docker volume create some-volume $ docker run -v some-volume:/container/path [other docker run arguments] $ docker run --mount 'type=volume,[other mount args]' [other docker run arguments]
  • new volumes created at docker run/docker service create time get the permissions of the folder that they map on top of in the image (the destination folder)
  • folders that do not exist in the image are created owned by root:root with permissions 0755

    • this applies to all folders in the path that do not exist

Bind mount (see also: service create --mount):

  • examples:
    console $ docker run -v /host/path/:/container/path [other docker run arguments] $ docker run --mount 'type=bind,src=/host/path/,dst=/container/path' [other docker run arguments]
  • ownership and permission of the destination (e.x. /container/path) becomes the ownership and permissions of the source (e.x. /host/path) since it is a bind mount
  • for any directories leading up to the destination path that do not exist, they will be created owned by root:root with permissions 0755

    • technically the destination is created with the same permissions, but the bind mount hides that ownership and permissions

  • if the source does not exist on the host it will be created owned by root:root with permissions 0755

    • this applies to all folders in the path that do not exist


Now let's apply them to this compose yaml snippet:

volumes:
      - wordpress:/var/www/html/wp-content:rw
      - ./app:/var/www/html/wp-content/themes/instapress:ro

For the named volume wordpress, /var/www/html/ does exist but does not contain wp-content, so wp-content is created owned by root:root with permissions 0755.

For the host ./app directory, let's assume it exists before the run and is owned by 1000:1000 and permissions 755. So, in the container, themes and themes/instapress folders do not exist and are created owned by root:root with permissions 0755 (wp-content was already created by the previous volume). The host ./app directory is mounted over the instapress container directory and so it is owned by 1000:1000 and permissions 755.

Was this page helpful?
0 / 5 - 0 ratings