Jump to Content

Andrew M McCall

Andrew M McCall - Web Developer In Traverse City, Michigan

Fix Docker Container Access to Bind Mount

Some quick notes on getting file permissions to work in bind mounts for WordPress

Problem With WordPress Docker Container Not Being Able To Create or Update Files or Install Plugins in a Bind Mount

I run a WordPress site with Docker Compose, using three services: MariaDB, WordPress, and WP-CLI. For local development, I bind-mount ./themes and ./plugins so I can edit files on the host.

The main problem is that the container can’t create files and directories in those folders. Installing a plugin or creating uploads fails, and WordPress asks for FTP credentials.

The cause is ownership. A bind mount uses the host folder’s owner and permissions. The web server process inside the container runs as a specific user ID. In the official WordPress image, that’s www-data, which is UID 33. If that ID can’t write to the host folder, WordPress falls back to FTP.

Solution

This setup keeps the image’s default user (www-data, UID 33) and shares the folders with your host user through a group.

1. Update the compose file

Remove any user: line from the wp and wp-cli services. Keep the bind mounts and the :z suffix, which handles SELinux labels on Fedora.

Don’t use UID=$(id -u) in a shell. UID is a read-only bash variable, so the assignment fails. This setup doesn’t need a .env file or group_add.

2. Find the web server group and add yourself to it

getent group 33

The group name depends on the distro. On Fedora it’s usually tape. On Debian and Ubuntu it’s usually www-data. Use the name the command prints, and add yourself to it:

sudo usermod -aG tape $USER

Apply the new group without logging out:

newgrp tape

Or log out and back in. Confirm with:

id -nG

3. Create the folders and set ownership

mkdir -p plugins themes mu-plugins
sudo chown -R 33:tape plugins themes mu-plugins
sudo chmod -R g+rwX plugins themes mu-plugins
sudo find plugins themes mu-plugins -type d -exec chmod g+s {} +

Replace tape if your group has a different name.

Don’t use 777. It lets any user on the system change the files.

4. Fix wp-content/upgrade inside the named volume

WordPress core lives in the wp_data named volume at /var/www/html, not on the host. Plugin installs download to wp-content/upgrade before they move files into plugins. If that folder isn’t writable, the FTP prompt can appear even when plugins is fine.

Fix it from inside the container:

docker compose exec wp sh -c 'mkdir -p wp-content/upgrade && chown -R www-data:www-data wp-content/upgrade'

5. Test as the web server user

docker compose exec -u www-data wp sh -c 'for d in wp-content/plugins wp-content/themes wp-content/upgrade; do touch $d/t && rm $d/t && echo "$d ok" || echo "$d FAILED"; done'

Use -u www-data. Without it, exec runs as root, which can write anywhere, so the test proves nothing.

6. Check that you can edit without sudo

find themes plugins ! -writable

No output means you can edit everything. If files are listed, they’re still owned by someone else, probably root from an earlier run. Fix them:

sudo chgrp -R tape themes
sudo chmod -R g+rwX themes
sudo find themes -type d -exec chmod g+s {} +

Repeat with plugins if needed. Restart your editor afterward so it picks up the new permissions.

7. Recreate the containers and test

docker compose up -d --force-recreate wp wp-cli

Then install a plugin from the WordPress admin. If the FTP prompt still appears, check for a forced filesystem method:

docker compose exec wp grep -n "FS_METHOD" /var/www/html/wp-config.php

No output is the expected result. If you see ftp or ssh2, remove that setting.

Tags: