TL;DR: To increase the WordPress file upload limit when using the official Docker image, create an .ini
file with the desired limits, mount it via a Docker volume, and override the container’s ENTRYPOINT
to copy it into place before startup.
Do a quick Google search on increasing the max file upload size in WordPress and you’ll no doubt find multiple ways to achieve it. These options tend to be more geared towards users hosting WordPress through a hosting provider like Bluehost, but as someone self-hosting WordPress using the official Docker image, I needed a solution that was a bit different.
The official Docker image has a 2 MB limit by default and doesn’t support an environment variable for changing this in your compose file directly. While editing .htaccess
or php.ini
files works, those changes are only temporary: restarting, recreating, or updating the container will wipe them out due to how Docker containers operate.
One way to achieve this would be building a custom WordPress Docker image which, while that very well could be something I try someday, is not something I’ve tried before and am not prepared to do just yet. What I was left with then as my option for achieving this was some sort of storage mount, such as a Bind Mount or a Docker Volume.
Option 1: Bind Mount
A bind mount is fairly straightforward: it allows you to link a specific file or directory from your host machine directly into the container’s filesystem. For instance, let’s say you have a custom PHP config file saved at /home/user/docker/wordpress/custom.ini
on your host. You can bind mount that into the container like so:
volumes:
- /home/user/docker/wordpress/custom.ini:/usr/local/etc/php/conf.d/custom.ini
This tells Docker to mount your local .ini
file directly into the container’s PHP config directory (/usr/local/etc/php/conf.d), which is where PHP automatically loads additional config files at startup.
Bind mounts are simple and flexible, but they rely on specific host paths, which makes portability and backups more cumbersome. Since I back up all of my Docker volumes using offen/docker-volume-backup, bind mounts don’t really fit into my current backup strategy. As such, I turned to Docker volumes instead.
Option 2: Docker Volume
Docker volumes, on the other hand, are storage mounts that are handled entirely by Docker itself, so they’re much more portable and easier to backup. Instead of referencing a path on the host, you define a named volume—like wordpress_customization
—and mount it into the container.
However, Docker volumes come with one key limitation: you can’t mount a single file from a volume. Instead, you have to mount the whole directory. And when you do that, the contents of the volume mask the target directory in the container. That means that any files already in /usr/local/etc/php/conf.d
(which includes important default PHP config files) will be hidden if you mount over it—leaving only your custom file. So, while Docker volumes are the better option for me, mounting one directly to /conf.d
would wipe out all the default .ini files that we need to keep.
Okay, so now what? I’ve decided Docker volumes are the best storage mount option for me given my backup strategy. But I’ve also now uncovered my next hurdle which is that I don’t want to wipe out the pre-populated .ini
files in the /conf.d
directory. And I also can’t mount individual files when using Docker volumes.
The Solution: Inject Custom Config File at Startup
Here’s what I decided to do:
- Mount the Docker volume to a different location inside the container (e.g., /customization) to avoid overwriting the pre-populated
.ini
files in the/conf.d
directory. - Copy the custom
.ini
file from/customization
into/conf.d
before PHP starts, so it’s loaded as part of the startup process.
This is important because PHP only loads configuration files from /conf.d
during startup. If the file isn’t present at that point, it won’t be recognized (even if it’s added later). To ensure this happens at the right time, we need to insert a copy command into the container’s startup process so that our config file is copied into place before anything else happens to ensure it’s recognized when WordPress launches.
We can achieve this by modifying the container’s ENTRYPOINT
. The ENTRYPOINT
defines the command that runs when the container starts. By default, the WordPress image runs docker-entrypoint.sh
, which handles setup tasks and starts Apache. We’ll modify the ENTRYPOINT
to first copy our .ini
file, then proceed with the original script.
Steps:
- Create the Docker volume. I’ve named mine
wordpress_customization
. - Create the custom .ini file inside the Docker volume. I’ve named mine
upload-limit.ini
with the following contents:
upload_max_filesize = 32M
post_max_size = 64M
- Update your compose file. Mount the volume and add the
ENTRYPOINT
command:
volumes:
- wordpress_customization:/customization
entrypoint: >
sh -c "cp /customization/upload-limit.ini /usr/local/etc/php/conf.d/upload-limit.ini && docker-entrypoint.sh apache2-foreground"
This command tells the container to:
- Run a shell (sh -c)
- Copy
upload-limit.ini
into/usr/local/etc/php/conf.d
- Run the original WordPress startup script
The Result
Now, every time your container is started or recreated:
- Your custom
.ini
file is injected into PHP’s config directory - Default
.ini
files from the image remain intact - Your changes persist across restarts, and your backup strategy remains clean and volume-based
I think this is a great example of how a seemingly simple goal can get tricky really fast when you’re self-hosting and building a homelab. But it’s also part of what makes self-hosting so valuable and rewarding—it pushes you to understand how things work under the surface and learn new things that you otherwise wouldn’t.
If you found this helpful, or ran into any issues getting it set up, feel free to reach out or drop a comment—I’m always happy to learn from others or help if I can.
Leave a Reply