No Code Attached Yet
avatar SheevaPlug
SheevaPlug
15 Sep 2025

Is your feature request related to a problem? Please describe.

Yes, the problem has been filed in a bug report in [1].

I want to build immutable Docker images for Joomla in a reproducible, testable, automated way ready for a modern CI/CD solution. I've already built a small base image with (surprise) a base installation of Joomla out-of-the-box, but when I try to extend that base image in a subsequent build the installation of extensions fails.

Please see my bug report [1] for my links to my Dockerfiles, build and run scripts, and more information.

[1] #46101

Describe the solution you'd like

I'd like to build Joomla images with extensions and configuration in an automated, reproducible, testable way that is suited for modern CI/CD workflows. In fact, I'm asking for a different installation use case than what Joomla by now is built for and recommends.

Additional context

From my point of view, there are several suspicions against the official Joomla image, notably its size (which is a result of the huge PHP image it is built upon), security implications (the official image having Perl, Python, and a GNU Compiler Collection installed, which are very valuable tools for every successful attacker having broken my first line of defense), and then, that in a Docker context of immutable containers it is not a good solution to a) start a container and then change its contents with an online installer and b) allow a software to change itself, especially a software that must handle data from untrusted sources.

I understand that the use case Joomla is built for is very convenient for installations on bare metal and maybe even for a single Docker installation. But then, if you would want to run Joomla in a cloud environment like (for example) Docker Swarm or Kubernetes, there must be a complete, runnable and basically configured image in a Docker registry, and there is (to my knowledge) no way to convert a container with changed contents back into an image. Thus, every time the Joomla image is started on another node, it will fall into the installer.

avatar SheevaPlug SheevaPlug - open - 15 Sep 2025
avatar joomla-cms-bot joomla-cms-bot - change - 15 Sep 2025
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 15 Sep 2025
avatar LadySolveig
LadySolveig - comment - 15 Sep 2025

Thank you for your contribution @SheevaPlug.
Since this is more about structural considerations for the Docker image and not so much about the basic system, Perhaps your issue would be better addressed here.
https://github.com/joomla-docker/docker-joomla

avatar SniperSister
SniperSister - comment - 15 Sep 2025

@LadySolveig the described issue is not related to the official docker image provided by the project, but to an image that @SheevaPlug is building, so I think posting the issue in the CMS context makes sense

avatar brianteeman
brianteeman - comment - 15 Sep 2025

What is the intended purpose of VOLUME /opt/joomla/plugins

avatar Fedik
Fedik - comment - 15 Sep 2025

@SheevaPlug it is close to impossible to create read-only image with possibility to install extension for almost any CMS.
A possible path:

  • user create a local kind of writable CMS installation,
  • install all needed extensions, and applied all required configuration,
  • build a read-only image based on this installation,
  • deploy the read-only image.

The complicated part here is DB and migrations (for future updates).

avatar brianteeman
brianteeman - comment - 15 Sep 2025

You should probably looking at installing Joomla outside the web root using the provided method for doing that

avatar SniperSister
SniperSister - comment - 15 Sep 2025

The complicated part here is DB and migrations (for future updates).

That's exactly the point of this feature request: If we expose the DB migration logic for both and extensions in a CLI command, then it would be possible to build an updated image versions after a core or extension update and then update the persistent DB accordingly.

avatar Fedik
Fedik - comment - 15 Sep 2025

You should probably looking at installing Joomla outside the web root using the provided method for doing that

That is different topic.
The issue about running docker image on cluster node, which should be able to restart after crash. And each restart should not trigger full installation. Kind of thing.

avatar brianteeman
brianteeman - comment - 15 Sep 2025

it relates to how the op is creating mount points for media etc

avatar SheevaPlug
SheevaPlug - comment - 15 Sep 2025

Thank you all for your time and your answers.

Yes, Fedik, it is true that I cannot have a read-only container and then install extensions into it. This is why I would very much like to install extensions at image build time only, and explicitly not during container runtime.

Application state is, from my point of view, the contents of the database, images and maybe other media files such as videos or PDFs. These need to be persisted to some sort of persistent storage and must be writable for the application.

But then, I do not consider extensions as a sort of state, but as a part of code, and for reasons like automation, security and reproducibility, i do not want them to be changeable (lest be changed) by the running application. Yes, I could put them on persistend storage and then they'd survive container recreation, but then... extensions are (for the most part) executable code, and I strictly anticipate the idea of software being able to manipulate its own executable code.

I know that this is very common in the PHP community and yes, I am sure that many if not most users find it very attractive and convenient. But I suspect that this approach is, from my perspective, a security nightmare.

And then... well, there are tools to install Joomla itself on the command line, and for some administrative tasks like the installation of extensions. Call me naive, but if there are such tools, then I'd expect them to work. :-)

avatar brianteeman
brianteeman - comment - 15 Sep 2025

The tools do work, it's your config/setup that is broken which prevents them from working

avatar SniperSister
SniperSister - comment - 15 Sep 2025

The tools do work, it's your config/setup that is broken which prevents them from working

The tools work for the intended usecase; this usecase however is new and different – and with the experience gathered in non-joomla projects, I consider it a valid one.

avatar brianteeman
brianteeman - comment - 15 Sep 2025

Exactly. But when you say they don't work and don't respond to questions about the setup it's a bit cheeky to complain they don't work

avatar SniperSister
SniperSister - comment - 15 Sep 2025

Ah I see, you are referring to the last sentence; Well, that's being discussed in #46101

Let's keep this ticket for the blocking item for such a setup in general, the inability to manually perform DB migrations in a non-web environment.

avatar brianteeman
brianteeman - comment - 15 Sep 2025

Better and more important things to work on

avatar SniperSister
SniperSister - comment - 15 Sep 2025

Feel free to invest your time into other issues that are more relevant to you.

avatar Fedik
Fedik - comment - 15 Sep 2025

This is why I would very much like to install extensions at image build time only, and explicitly not during container runtime.

It is impossible to do during build. The CMS is a web application which is requiring web server + database (or at least php cli + database). We from our side cannot do much about it.

The way it can work I wrote in previous comment.
Do local installation, then during build COPY /path/to/local/installation /var/www/html
Only thing that is need to figure out is database migration.
The database usually is a separate container wich run as service.

If we expose the DB migration logic for both and extensions in a CLI command, then it would be possible to build an updated image versions after a core or extension update and then update the persistent DB accordingly.

There many thing need to cover.
Should we care only the database schema.
Should we care about menu and modules and plugins and other extensions and such kind of stuff.
Should we care about user content.

I have no idea how to do all of that :)

avatar SniperSister
SniperSister - comment - 15 Sep 2025

It is impossible to do during build.

Currently: yes! That's the actual point being made in this ticket:

The installation of both, core and extensions, include two steps:

  1. copy around a bunch of files -> that should happen on build time when the image is created
  2. perform DB-related task -> creating an #__extensions row, creating ACL assets, running extension SQL files -> that can't happen on run time (as there is no DB), but it could easily be part of some sort of "bootstrapping" script that's executed once the container is started: disover and install "new" extensions, detect version changes for already installed extensions and run SQL migrations for both core and extensions

All other mentioned steps (configuring the installed extensions, creating menus and content etc) can then happen via the web interface.

avatar SheevaPlug
SheevaPlug - comment - 17 Sep 2025

Thank you for your time and answers.

Brianteeman wrote:

What is the intended purpose of VOLUME /opt/joomla/plugins

That is just a leftover from my tests, please ignore it.

Brianteeman wrote:

But when you say they don't work

Please excuse me, but we are talking about a command line program (cli/joomla.php). This program does (as far as I have explored it yet) only work in an interactive environment with a tty(4), even though it is not interactive and thus has no hard dependency on an interactive environment. It fails in a non-interactive environment, but despite being set to maximum verbosity, it does not say why. This will break other automation and configuration management tools like Ansible, too.

Fedik wrote:

It is impossible to do during build. The CMS is a web application which is requiring web server + database (or at least php cli + database). We from our side cannot do much about it.

In fact, at install time I do have the PHP cli and the database (and even though I would not like that, i could even run the webserver in the background). But the CLI installer installation/joomla.php that i use in JoomlaBase needs the database to connect to it, and create and fill Joomla's tables. That is not a problem, and it works, as you can see in the src/Dockerfile:43 in my JoomlaBase repo.

A bit more problematic is that the installer/joomla.php program renames existing tables with a "bak_" prefix and recreates the tables. I'd prefer some "--migrate" switch to not recreate, but update the existing tables. To my knowledge (please correct me if i'm wrong) Joomla is built upon Symfony and thus uses Doctrine as OR mapper, and to my knowledge (please correct... you get the idea), Doctrine supports database migrations. But I have not worked with PHP since 15 or 20 years, and so do not know how well these work. So, I too have no clue how hard it would be.

Do local installation, then during build COPY /path/to/local/installation /var/www/html

This would need manual steps. Manual steps are error-prone and lead, earlier or later, to inconsistencies. Therefore, I'd like to avoid any manual intervention -- in fact, this is what this is all about.

There many thing need to cover. I have no idea how to do all of that :)

Yes, I know, and all i can do is to offer my help. :-(

avatar Llewellynvdm
Llewellynvdm - comment - 17 Sep 2025

Joomla is fundamentally a stateful, database-driven CMS. Its core design assumes that:

  • Code lives on disk and is writable (so that extensions, templates, updates can be added/removed at runtime).
  • State lives in the database, and a lot of what you might consider “configuration” (menus, modules, plugins, extensions being enabled, ACL, even some template overrides) is stored there.
  • The application is designed to mutate itself: extension manager copies files, updates DB schema, and adjusts configuration live.

Trying to make it fully immutable (code + DB schema frozen, no writes except media) is a paradigm shift, not just a Docker build tweak. It would require:

  • Disabling runtime extension manager and core updater.
  • Providing a repeatable CLI migration system for schema updates that can run outside the web context.
  • Separating configuration from content more clearly so you can ship config with code and not rely on the DB for everything.

None of this is how Joomla is built today — it would effectively turn it into something closer to a statically compiled CMS (think WordPress Bedrock + Composer, or even statically built sites like Hugo), where deployments are fully declarative and reproducible.

Practical takeaway

  • You can get closer to immutability (preinstall extensions at build time, disable online updates, ship migrations in CI/CD).
  • But full immutability would require core-level architectural changes — separating code from runtime state more rigorously, and exposing a proper non-interactive migration framework.

Freedom

While I appreciate the discussion about making Joomla more “immutable” and CI/CD-friendly, I want to express a different perspective:

One of Joomla’s biggest strengths is the freedom it gives us as site builders and developers — the ability to install, configure, and adapt extensions directly in the application at runtime. This flexibility is a huge part of why many of us choose Joomla over other systems.

Moving Joomla toward a model where the core and extensions are fully locked down and all changes must be done through a build pipeline would, for many of us, take away the very freedom that makes Joomla enjoyable. If Joomla ever went in that direction by default, I suspect many in the community (myself included) would be hesitant to follow.

I’d personally like to see Joomla continue to support both approaches: keep the current flexible runtime model for those of us who value it, and optionally offer tools or patterns for teams who want to run Joomla in a more immutable, CI/CD-style workflow.

avatar SniperSister
SniperSister - comment - 17 Sep 2025

I’d personally like to see Joomla continue to support both approaches: keep the current flexible runtime model for those of us who value it, and optionally offer tools or patterns for teams who want to run Joomla in a more immutable, CI/CD-style workflow.

+1, that's exactly what I would like to see happen too! And you mentioned the essential building block:

Providing a repeatable CLI migration system for schema updates that can run outside the web context.

For me, that sounds like two new Joomla CLI commands to perform the necessary migrations for both core and extensions.

avatar brianteeman
brianteeman - comment - 17 Sep 2025

... and modify lots of core behaviour that requires "mutation" and then ensure that all future core cms development doesnt introduce new steps that require "mutation". CLI commands alone will never be enough without significant changes to core functionality @Llewellynvdm only touched on some of the areas that would need to be rewritten OR disabled in an "immutable" environment.

avatar SniperSister
SniperSister - comment - 17 Sep 2025

Other relevant areas are:

  • file uploads in core (media management) or extensions (download extensions, product images in shops etc) - however that's not application data being uploaded but actual content and therefore an expected usecase for mutations; can be solved by mounting a volume in the respective areas
  • caching - default file cache would mutate the filesystem, easy workaround (and way to go in such a setup anyways) would be a redis cache
  • logging - probably needs some sort of "stdout" driver on the long term; first step would be mounting a volume for the logs
  • extension management
  • template file management
  • stuff that's written into the tmp folder - again, potentially a volume

My point is: there are workarounds (volumes, redis for caching, do not upload or update extensions on the running site) for the apparent issues, but no workaround for the migration stuff. It's a total blocker.

avatar SheevaPlug
SheevaPlug - comment - 17 Sep 2025

Thank you all for your time and your thoughts.

Llewellynvdm wrote:

One of Joomla’s biggest strengths is the freedom it gives us as site builders and developers — the ability to install, configure, and adapt extensions directly in the application at runtime. This flexibility is a huge part of why many of us choose Joomla over other systems.

Moving Joomla toward a model where the core and extensions are fully locked down and all changes must be done through a build pipeline would, for many of us, take away the very freedom that makes Joomla enjoyable.

Yes, sure, i am fully aware of that. Even though i am afraid of self-modifying code that otherwise has to handle data from untrusted sources, i do know that this freedom is very important for many users. So i'm explicitly not asking to remove any features providing the freedoms you -- and, i am sure, many other people -- do like, want, need and use.

But then, I think or at least hope that these possibilities can coexist: providing the freedom for those who want it, but then have an option to disable them for automation purposes (and for cowards like me). Because in the end, implementing this possibility would not only ease buildtime automation, but also enhance runtime security.

Thanks to Brians link to issue #161, i can see that the automation idea is around since 2023, and my proposal seems to be similar to what ReinerNippes asks for.

avatar SheevaPlug
SheevaPlug - comment - 17 Sep 2025

SniperSister wrote:

* file uploads in core (media management) or extensions (download extensions, product images in shops etc) - however that's not application data being uploaded but actual content and therefore an expected usecase for mutations; can be solved by mounting a volume in the respective areas

Yes, this would be done with a volume.

* logging - probably needs some sort of "stdout" driver on the long term; first step would be mounting a volume for the logs

Absolutely, logging should go to stdout or stderr.

* caching - default file cache would mutate the filesystem, easy workaround (and way to go in such a setup anyways) would be a redis cache
* stuff that's written into the tmp folder - again, potentially a volume

Sorry for reordering your points, but from my point of view, these two are both temporary files that do not need to get persisted, and so should go to tmpfs mounts.

My point is: there are workarounds (volumes, redis for caching, do not upload or update extensions on the running site) for the apparent issues, but no workaround for the migration stuff. It's a total blocker.

Would you please be so kind to elaborate on that? As far as i know, Joomla uses Doctrine via the Symfony framework, and if i remember correctly, Doctrine supports at database migrations. Isn't that true anymore or is there something that blocks Joomlas cli/joomla.php from using these? I mean... even if one does an online update, there must be something to migrate her databases' schema and contents, or am i wrong?

avatar SniperSister
SniperSister - comment - 17 Sep 2025

Joomla does not use Doctrine, it uses a self-baked solution for it's db-related logic.

even if one does an online update, there must be something to migrate her databases' schema and contents, or am i wrong?

Yes, there is existing migration logic, but it's limited to web contexts.

avatar SheevaPlug
SheevaPlug - comment - 19 Sep 2025

Joomla does not use Doctrine, it uses a self-baked solution for it's db-related logic.

Oh, i had supposed so, thank you for the clarification.

Yes, there is existing migration logic, but it's limited to web contexts.

Too sad... For the moment I understand that Joomla does not support my use case very well. There seems to be an older discussion on that (thank you for the link, Brian), but -- as far as I can see -- there are no tangible plans and it seems that it would require a lot of work, even architectural changes to implement it.

I understand that the Joomla project rather focuses on its original use case. So for now, I am sad because I really like Joomla, but please understand that, under these circumstances, i must abandon Joomla for now. But i still like Joomla very much and will keep it in mind -- for other use cases and / or the case Joomla will support my current one in the future.

And then, I'll open an issue in the docker-joomla [1] repository that LadySolveig kindly mentioned. I hope an overworked version of my JoomlaBase Docker image can help and would be glad if not all of my work would be lost.

Thank you all very much for the avid discussion and your participation in it. I'll leave it open for now in case someone else wants to add some, and then close it in some days.

[1] https://github.com/joomla-docker/docker-joomla

avatar SheevaPlug SheevaPlug - change - 21 Sep 2025
Status New Closed
Closed_Date 0000-00-00 00:00:00 2025-09-21 12:33:50
Closed_By SheevaPlug
avatar SheevaPlug SheevaPlug - close - 21 Sep 2025
avatar SheevaPlug
SheevaPlug - comment - 21 Sep 2025

Unfortunately, Joomla at this time does not support my special use case, thus i am closing the discussion here.

But hoping my work can help the Joomla Docker project i have opened another issue [1] there.

Thank you all again for your time, participation, and all the information you have shared with me.

[1] joomla-docker/docker-joomla#215

avatar brianteeman
brianteeman - comment - 21 Sep 2025

thanks

Add a Comment

Login with GitHub to post a comment