Forum OpenACS Development: Docker NaviServer and OpenACS suite on GitHub

Dear all,

as a small Christmas present, I’ve put together the full suite of Docker containers for NaviServer and OpenACS, including Dockerfiles, init scripts, and documented example docker-compose setups, and published everything on GitHub:

https://github.com/gustafn/docker-ns/tree/main

The OpenACS examples include two complementary setups:

  • a fully containerized setup, where OpenACS, NaviServer, and the database all run inside containers, and

  • a production-style setup, where NaviServer and its infrastructure (mail relay, Munin, etc.) run in containers, while data remains outside the containers (database, scripts, log files, content repository). This second setup is particularly useful for development and testing, for example when experimenting with new Tcl/NaviServer versions or when multiple developers share the same source tree.

Feedback, questions, and improvements are very welcome.

All the best,
— Gustaf

Collapse
Posted by Gustaf Neumann on

Dear all,

here is a short update on the Docker images for OpenACS / NaviServer.

Over the last days, I have worked on a larger cleanup and consolidation effort, with the following results:

  • All container images now come with a complete and documented build environment (naviserver, naviserver-pg, naviserver-oracle, mail-relay, munin-node-openacs, munin-master).

  • The design principles of the containers are now explicitly documented, including filesystem layout, volume usage, and configuration strategy.

  • Added guidelines for local custom builds, in case modifications are required (the images are highly configurable, so rebuilding should only be necessary in rare cases).

  • Introduced canonical internal paths to simplify maintenance and reduce ambiguity.

  • Standardized volume handling to make integration of external resources more predictable.

  • Made it possible to use an OpenACS tree on NFS volumes (with the requirement of an external log directory).

  • Added the NaviServer letsencrypt to the openacs container for automated certificate renewal (a sample configuration is included but disabled in the examples).

All documentation has been migrated from Docker Hub to GitHub, which now serves as the single authoritative source:

https://github.com/gustafn/docker-ns

To reduce confusion, I plan to remove the following legacy GitHub repositories, as their content is now fully integrated:

  • docker-mail-relay
  • docker-munin-master
  • docker-munin-node-openacs

The examples in the repository have also been updated. This includes:

  • oacs-db-inclusive, a single-container setup providing OpenACS together with script directories, log files, content repository, and an integrated database.

  • openacs-org, a slightly simplified variant of the OpenACS.org deployment, where all binaries are provided by containers while all persistent data (log files, content repository, database) is stored externally.

The sample site demonstrates a production-style setup and includes:

  • multiple virtual servers
  • fully integrated mail delivery via Postfix
  • fully integrated monitoring via Munin (automatically configured)
  • fully integrated and automated certificate renewal

Feedback and testing reports are, as always, very welcome.

Best regards,
Gustaf

Collapse
Posted by Claudio Pasolini on

Well done, Gustaf!

This is not at all a small Christmas present, but a great contribution!
I never used Docker before and simply reading the various README I'm starting to understand how Docker could help us to develop and deploy our apps.

I tried the openacs.org example and encountered some small problems:

  • an indentation problems in the docker-compose.yml file (there was a space in the volumes: line)
  • a syntax problem in the environment, replaced
    <<:
    - *default-env
    - *db-env
    with <<: [*default-env, *db-env]
  • the health check didn't find the expected success.tcl file and I simply commented out the check
  • a problem connecting to the host db, but I don't remember the details

Now the container works and I'll test it further in the following days.

Collapse
Posted by Gustaf Neumann on

Hi Claudio,

The example openacs-org is probably not the best starter example, since it is already quite complex. The example is a down-stripped version of the setup running at openacs.org. It is not intended to work out of the box, since it depends on external resources (the OpenACS source tree, an external database, host-specific networking, etc.). When starting from this example, several adaptations are required for a given site: configuration files, environment variables, database host/port and permissions, and - importantly - making sure the OpenACS checkout is complete and reasonably recent.

If you want an example that works without external dependencies, the oacs-db-inclusive example is the better starting point. It includes the database and does not rely on host resources. BTW, it uses exactly the same YAML merge syntax*as the openacs-org example.

Having said this, there was indeed a stray space in the provided sample docker-compose.yml. YAML syntax is very strict about whitespace, so even a single extra space can break parsing. One can easily check the syntax, for example, with:

docker compose -f docker-compose.yml --env-file .env.example config >/dev/null

Portainer also validates the compose file and will flag such syntax issues immediately.

Regarding the other points:

  • YAML merge syntax (<<:) Both forms are valid YAML. If a parser complains, it is usually due to an inconsistency elsewhere (e.g., mixing map-style and list-style environment: entries). The merge syntax itself is fine and used consistently across the examples.

  • Health check and success.tcl /SYSTEM/success.tcl has been part of OpenACS for many years. If it is missing, this typically indicates an incomplete or overridden OpenACS checkout. Commenting out the health check hides the symptom; the real fix is to ensure the OpenACS tree is complete and correctly mounted.

  • Connecting to the host database Problems here are usually platform-specific (Linux vs macOS/Windows) and related to name resolution (host.docker.internal), database listen addresses, or permissions. Without the exact error message it’s hard to be precise, but this is a known and solvable class of issues.

Thanks again for testing and for the feedback - it’s very helpful, especially for improving documentation and expectations around the examples.

All the best in the new year!
-g

Collapse
Posted by Michael Aram on

This is really great. By asking ChatGPT how to install this stack locally on my Mac, I was able to run an OpenACS 5.10.1 instance locally "from zero to hello world" within a few minutes. Very nice. Also, as "install from repository" worked fine from the UI, this allows to try out packages in a vanilla sandbox very conveniently.

I have tested / clicked around in this instance a bit and I found the following issues (not all of them in scope of the containerization-effort, of course, but general issues):

  • There is a prominent search box on the start page, but using it results in a "Client Error - The requested file was not found". After adding the search package via the UI, the new error is: "FtsEngineDriver not available!"
  • The subsite mounted under /acs-admin/site-wide/ has another theme configured than the main site.
  • The page /acs-admin/monitor, which is linked on /acs-admin/, linked on the returns the error "'uptime' command not found on the system".
  • The page "/acs-admin/posture-overview" returns the error: "can't read "detailURL": no such variable"
  • The class graph is not rendered (image usually included when browsing to e.g. /xotcl/show-object?showmethods=1&showsource=0&object=::Generic::Form)
  • Bootstrap util-user-messages seem to have a small UI glitch with respect to the close cross.
  • The flush button for the caches shown under /acs-admin/cache/ doesn't succeed for most of the suffixes.
  • Running the complete test suite under /test/admin/ resulted in 466 executed test cases, 41258 passes 40 fails and 581 warnings. Some of the created test-users dont have the "testuser" prefix, btw.
  • Switching theme to openacsbootstrap5turquois puts the .LRN logo in the upper left corner.
  • Page /admin/nsstats?@page=log.smtpsent gives error "could not read "smtpsend.log": no such file or directory"
  • The local port under which I could access the instance changed upon every restart, which I didnt expect, but I am sure this can easily avoided by configuration.

Thanks again for this great contribution!

Collapse
Posted by Claudio Pasolini on
I tried the oacs-db-inclusive example and to avoid using ephemeral ports, I created an .env file with the ports httpport=8080 and https=8443 and everything worked well.

There was a strange behavior after installation: even browsing to localhost:8080 the browser automatically switches to localhost:8443.

I confirm the Michael's reports, with the eception of the page "/acs-admin/posture-overview" which in my case worked well.

Claudio

Collapse
Posted by Gustaf Neumann on

Thanks a lot to both Michael and Claudio for the extensive testing and feedback — this is very helpful.

Michael, you are most likely referring to the oacs-db-inclusive example. This setup is intended as a minimal but usable OpenACS sandbox, suitable for quick testing and experimentation.

Search box → “Client Error – file not found” / “FtsEngineDriver not available!” / missing Packages

In container environments, it is very common to keep images small and only install optional system packages on demand. Originally, the image contained only acs-core, but since this provides a very crude UI, I added a minimal xowiki-based configuration via install.xml.

You can see the configuration file:

  • from the image:

docker run --rm gustafn/openacs:latest cat /var/www/openacs/openacs-xowf-install.xml

  • from a running container:

docker exec oacs-db-inclusive-openacs-1 cat /var/www/openacs/install.xml

it is also possible to provide your own install.xml file.

On first startup, oacs-db-inclusive checks out OpenACS directly from CVS, defaulting to the oacs-5-10 branch. Other branches can be selected via the oacs_tag environment variable.

To summarize, this is an OpenACS usability issue, not a container issue. The standard templates always include a search box. The search package itself is installed by default. What is missing is typically the tsearch2-driver package, which is not installed automatically.

If tsearch2-driver is installed (e.g., via install from local) and search is mounted via the sitemap, search works as expected. There is nothing wrong with the container here, but the default UX for fresh installs could certainly be improved.


Different theme under /acs-admin/site-wide/

A different theme is intentional. The site-wide admin pages use a different theme to make it visually clear that this is not a normal subsite but an administrative area affecting the whole instance. A more beautiful theme would be nicer.


/acs-admin/monitor: 'uptime' command not found

The system package procps is not installed by default. This should ideally be handled more gracefully by OpenACS instead of erroring out.


/acs-admin/posture-overview: can't read "detailURL"

This page works for me without errors. Possibly a transient upstream issue or a configuration difference.


Class graph not rendered (/xotcl/show-object?...)

The graphviz package is not installed by default. Without it, both class graphs and call graphs in api-browser are silently omitted. No errors are shown.


Bootstrap util-user-messages UI glitch

I’m not sure how to reproduce this yet. Likely an OpenACS / theme issue.


Cache flush buttons under /acs-admin/cache/

This is an OpenACS issue. A practical change for OpenACS would be to use /xotcl/cache (when installed).


Regression test results (fails / warnings)

After a fresh install, the regression suite runs cleanly for me:

  • passes: 40 837
  • fails: 0
  • warnings: ~554

Once additional packages are installed, some test failures are unfortunately not unusual. There is certainly room for improvement here -- as always, contributions are welcome.


Theme openacsbootstrap5turquois shows .LRN logo

This is an OpenACS issue. The theme is not actually turquoise and appears to contain leftover dotLRN elements. It probably should not be offered at all.


/admin/nsstats?@page=log.smtpsent: missing smtpsend.log

This comes from the NaviServer nsstats package. The log file is created only after the first mail is sent; until then, the page should behave gracefully instead of erroring out. This should be addressed in NaviServer.


Local port changes on every restart

This is expected behavior when using ephemeral ports. It allows running multiple instances in parallel without port clashes.

If you want fixed ports, specify them explicitly — either via Portainer’s UI or via an .env file (as Claudio did with httpport=8080, https=8443).


Optional system packages

If you want the “missing” functionality out of the box, you can add:

system_pkgs=procps graphviz

to your environment. These packages will then be installed automatically when the image is built.

See also the configuration options documented in: https://github.com/gustafn/docker-ns/blob/main/openacs/README.md


Claudio’s observation (HTTP → HTTPS redirect)

Browsing to localhost:8080 redirects to localhost:8443

This is most likely intentional. Several parts of OpenACS will switch to HTTPS automatically for security reasons when HTTPS is available.


Summary

To summarize: none if these issues are actual container-specific in the reported observations. The containers behave as designed, in particular with respect to minimal base images, optional system packages, and port handling.

Most reported problems fall into the category of OpenACS issues, primarily around usability and robustness of a fresh/minimal installation (search UX, missing optional drivers, error handling when external tools are absent, theme inconsistencies, cache admin behavior, and some admin pages not degrading gracefully). These are areas where OpenACS itself could and should be improved. Some of the reported issues are due to missing docker background.

One additional issue is in NaviServer’s nsstats module, which currently errors out when expected log files (such as smtpsend.log) do not yet exist; this should also be handled more gracefully.

Addressing these points upstream would improve the out-of-the-box experience for fresh OpenACS installs, independent of whether they run in containers or on traditional systems.

Again, many thanks for the careful testing and detailed feedback — it’s very valuable for improving both documentation and defaults.

-g

Collapse
Posted by Gustaf Neumann on

i did some Improvements over the weekend:

  • nsstats is repaired to behave gracefully, when no nssmptd log file is available, and someone clicks on SMTP sent log. The fix is in the NaviSever repository on GitHub. If you recreate the container, you get immediately the updated version
  • The /acs-admin/monitor page of OpenACS is fixed in CVS head and oacs-5-10 to behave gracefully, when uptime is not installed.
  • The configuration of system_pkgs with graphviz and procps was added to the documentation of the oacs-db-inclusive container (README file)

I have also added the graphviz package to openacs.org, now we have there the graphs in api-doc again.

All the best -g

Collapse
Posted by Gustaf Neumann on

I've also added a mitigation for the cache management, as indicated, both in the HEAD and the oacs-5-10 branch. So, a fresh installation of the oacs-db-inclusive container (or an update-from-repo tomorrow, once the .apms for oacs-5-10 are rebuilt) will be able to flush the caches via /acs-admin/cache

Collapse
Posted by Brian Fenton on
This is great news indeed, Gustaf! Thanks as always for your sterling efforts.

Brian

Collapse
Posted by Brian Fenton on
Just to confirm that I got this working on Windows 11 running under WSL. I had to change the ipaddress to 0.0.0.0 and ports to 8080 and 8443 in docker-compose.yaml. Apart from that it worked flawlessly.

Here's the steps to get it running:
cd /web
git clone https://github.com/gustafn/docker-ns.git
cd docker-ns/examples/oacs-db-inclusive
code .
Edit docker-compose.yaml
I had to change the ipaddress to 0.0.0.0 and ports to 8080 and 8443
docker compose up -d

Runs on https://localhost:8443/

Thanks again Gustaf!
Brian

Collapse
Posted by Gustaf Neumann on
Hi Brian, Good news, thanks for letting us know!

Actually, you do not have to edit the docker-compoose file, but you can set your configuration variables. This eases later upgrades, since you do not have to remember, what you have originally changed.

Collapse
Posted by Gustaf Neumann on
Two more changes:
a) the bootstrap3 and bootstrap4 theses do not display search unless it is available (changes in the repository in the HEAD and oacs-5-10 branches)
b) i've updated the default install.xml for the openacs container to install tsearch and to mount search. This addresses the complaint about the error when entering something into the search field.
Collapse
Posted by Claudio Pasolini on
Starting from the oacs-db-inclusive image, I set up two containers (oacs-a and oacs-b) that communicate with a separate Postgres container. Portainer shows all instances as healthy, and the host ports are properly published.

My goal is to run multiple instances listening only on HTTP, letting Nginx handle HTTPS. To achieve this, I modified the YAML file by setting httpsport="" and removed all HTTPS-related sections from openacs-config.tcl.

The instances start normally, and I successfully completed the installation from the Welcome page. However, after restarting the browser (both Chrome and Firefox), it always redirects to https://127.0.0.1:8080. In contrast, accessing http://localhost:8085 with curl or lynx works fine.

In the logs, I see:
Notice: security::locations add connected location http://127.0.0.1:8085

immediately followed by:
Notice: security::locations add connected secure location https://127.0.0.1:8080

I'm not sure if this is a browser issue or an OpenACS problem.

Claudio

Collapse
Posted by Gustaf Neumann on

Hi Claudio,

a few clarifications that may help narrow this down:

  • To disable HTTPS handling inside the OpenACS container, it is not necessary (and not recommended) to remove HTTPS-related config sections. It is sufficient to unset/comment out oacs_httpsport. Removing HTTPS entirely means OpenACS loses its secure context, which can have side effects.

  • When running OpenACS behind a reverse proxy (e.g. Nginx handling HTTPS), OpenACS must be explicitly configured for this. In the current container setup this is done via ns/parameters/reverseproxymode which can be set in docker-compose.yml using oacs_reverseproxymode. Without this, OpenACS will have 'wrong' peer addresses, i.e. the proxy server itself.

  • It is also important to clarify whether oacs-a and oacs-b are meant to be independent instances or the same instance accessed twice. In the latter case, a proper cluster configuration is required; otherwise you will see inconsistencies (including location handling).

  • In a proxy-based setup, OpenACS ports normally should not be exposed at all—only the proxy ports should be published.

Regarding the redirect itself: browsers tend to cache scheme decisions (and sometimes HSTS-like behavior even on localhost/127.0.0.1), while tools like curl or lynx do not. Combined with OpenACS registering a “secure location” early at startup, this can easily explain why only browsers redirect to HTTPS.

all the best -g

Collapse
Posted by Claudio Pasolini on
Many thanks for the clarification, Gustaf!

Setting oacs_httpsport and oacs_reverseproxymode resolved the issue. Both instances are now working normally and are reachable via Nginx.

Claudio