Lucee, Docker, Portainer and configs


Hi all. Can anyone give some direction on how to have Docker build config files for Lucee? When we try using Portainer, we get 500 errors - possibly due to file permissions of the lucre-server.xml file that Docker creates? Any help would be appreciated! Thank you.


@stobener Did you look at ?


Hi Bob,

Have you checked out ?
They suggest to use the commandbox docker image, which should absolutely work.

Kind regards,

Paul Klinkenberg


I absolutlely love Commandbox’s Docker images. That, combined with a server.json file and using the commandbox-cfconfig forgebox extension make it very awesome.

A good place to start is to make sure you have a server.json created with commandbox:

Then you should use box install commandbox-cfconfig and then work with that to create your server configuration:

Then you can use their own docker container:

what this looks like is as follows:

  1. install commandbox
  2. in the command-line do box init
  3. edit the box.json file as you want
  4. Start it locally (to create a server.json) by doing box start cfengine=Lucee@5 which will give you the latest version
  5. you need to install the commandbox-cfconfig plugin so do box install commandbox-cfconfig
  6. Setup your server using the admin, (or follow how cfconfig does it) and you can see your settings with box cfconfig show
  7. you can save those settings to a file by doing box cfconfig export .cfconfig.json
  8. you can stop the local server now we are going now create our docker container. box stop
  9. Crate a Dockerfile in your root with:
FROM ortussolutions/commandbox
COPY . /app
  1. Now you can build your image with docker build -t my-lucee-app . (notice the last . dot there!)
  2. now you can run it! docker run -p 9999:8888 my-lucee-app

and profit! :smiley:

We use this for development (by mapping app volumnes using -v) as well as testing (by running testbox) and soon to deploy to kubernetes stacks.



@21Solutions Yes that’s actually where we started with our Docker journey! Thank you for getting back to me on this.

@frinky and @markdrew Thank you for getting back to me as well. We’ll check out CommandBox today!


Maybe @justincarter and/or @modius can help. I believe that they are the ones who created that project.


To clarify, there are two docker images being discussed in this thread. The official Lucee image is maintained by the Daemon crew (Geoff/Justin). The CommandBox-based image is maintained by Ortus Solutions (Luis, myself, Jon Clausen)


Have you written a custom Dockerfile and you’re having issues? Can you include the Dockerfile and any container output or log files or screenshots that show the error you’re getting? That would make it much easier to help :slight_smile:

Generally to override the lucee-server.xml you just put one “COPY” statement in your Dockerfile. I’ve not seen any issues related to config file permissions in the couple of years that I’ve been using Lucee with Docker, it could be more likely that the config itself is bad, but even then Lucee might be able to handle it. Post as much info about your config changes as you can, just remember to remove anything that might contain passwords/hashes.


Hi Brad. Thank you for the response. We’re working with the CommandBox image. We’re trying to understand how to generate the server.json config file (or find it in the container if it already exists). Our goal is to do what you did in your video from Container Roadshow (excellent by the way). We’ll be tackling this next week.


Hi Justin. Thank you for your response. The copy commands work fine on local Docker environments with the config files. Maybe the permissions problem is with our Azure host that might have different security restrictions set up. More work for us on this next week.


@stobener Feel free to jump on the CFML slack team if you need some realtime help with this. You create the server.json file yourself, and by default it’s in the web root. (The webroot is in /app which you will copy your code to in a warmed production image, but can be mapped as a volume in local dev) You can find the full documentation on this file in the CommandBox docs:
I also just blogged about it last night:

There are no required fields in a server.json, you can just set whatever specifics you’d like. I’d also like to point out that there is no copying of XML files anywhere in the CommandBox-based image. CFConfig handles all of your CF engine config (like datasources, etc) and it’s seamless. In fact, you can literally switch a CommandBox-based Docker image from Adobe CF to Lucee by swapping out the app.cfengine property in your server.json and all the config like datasources will just import right into the new engine since nothing is tied to engine-specific XML files.


How do you build the image, do you deploy everything to the server and manually run “docker build” there?

I’d highly recommend using a build/registry service like Docker Hub or to build your images. It will help avoid a number of issues that you might encounter locally or on your own servers (such as the permission issue that you have), automate your builds based on pushes to a git repository, and it’ll assist with tagging versions of your images so that it’s easy to roll back quickly in the event of some bad code change, and Quay even does security scans on your images.


Hi All,

I am Bob’s Co-Worker. We really appreciate all of the help on this issue.

We are attempting to deploy Docker containers to a test, QA, and production environments. These environments are running Docker Swam and backed by a private registry.

We currently build a Docker image based on the official Lucee 5.2 docker images,

We are fully able to customize this image. We currently add custom certificates and custom jar files in addition to the application code.

Part of the image customization is a lucee-server.xml file that contains the data source connection parameters.

The image contains the test version of the lucee-server.xml. This works great and we are able to connect to launch our applications as expected.

As a best practice, we are reusing the container in QA but replacing the lucee-sever.xml with a QA version of the file. This replacement of the file is the problem. We insert the QA configuration using the docker configs functionality found in Docker Swarm. Docker swarm inserts the file as read-only, the file permissions are not configurable.

When we launch this container Lucee errors out with the following:
2017-12-18 17:16:46.57 lucee.runtime.exp.NativeException: /opt/lucee/server/lucee-server/context/lucee-server.xml (Read-only file system)

Our question is why does this file need to be read-write? Can we configure lucee to accept this file as read-only?



Hi Armando, I’m not sure what’s going on with your file system, but I’ll point out here that the CommandBox based image doesn’t involve any copying of XML files at all! That alone comes with it’s own hassles They are potentially specific to the version of Lucee you’re on now, they are a complete overwrite which means you can’t just override a single setting such as swapping out an admin password on one environment without needing to generate a whole new XML file. CFConfig which is part of CommandBox images gives you laser precision on what you want to manage with a human-readable JSON file that is imported into the existing configuration and only overwrites the properties you want changed. CFConfig also supports environment variable replacements meaning you don’t even need a separate configuration file for environments if all you want to do is swap out some connection parameters. Just set up the env vars on your containers to be specific for the environment and let CFConfig do the rest. With CFConfig you can even override settings like the admin password with a single env var named by convention and it just gets sucked in. You’ll never need to touch the XML files again :slight_smile:

-e cfconfig_adminPassword='$3cr3t'


Can you explain how the file is getting replaced? Are you using a “volume” or a “mount” to map the file from the host file system into the container? I’m just trying to work out if it’s a build time issue, or a run time issue.

As per the official docs the default for volumes and mounts is generally read-write, so it would only be read only if you were specifying the “readonly” flag;

If you’re doing it some other way perhaps you could detail it here?

When we build a Docker image we always ensure that any config files that get copied during the build process are identical across all environments, and we use environment variables to vary the configuration by writing some application code to set things up using the application scope (DSNs, cache servers, etc). If you can avoid changing files between environments that would be ideal, because then you truly have one build (one Docker Image) that you can progress through dev -> test -> uat -> production, and you don’t need separate builds for each :slight_smile:

As I mentioned before we also recommend doing your builds using a service that has a private registry, like, so that if you had anything that your local build server was doing incorrectly during build time you could avoid that by using an external service. It’s nice to have builds triggered automatically from your commits, the builds generally happen very fast, and you also don’t need to maintain your own build server or do builds on stage/production servers and use up vital resources. If it’s a build time issue that you have then this might be a good test, or if it’s a run time issue then I guess we’ll need to know a bit more about your process for building and spinning up the container.




Bob is trying to use CommandBox. One of the issues we are having with command box is that it does not seem to install Lucee in the default location.

Can we add CFConfig to an official lucee docker image?




We are not using volumes or mounts we are using Docker Configs:

Docker configs are similar to Docker Secrets.

You also mentioned:

“When we build a Docker image we always ensure that any config files that get copied during the build process are identical across all environments, and we use environment variables to vary the configuration by writing some application code to set things up using the application scope (DSNs, cache servers, etc).”

I think this may be our best way forward. Do you have a tutorial or example for setting up an application scope?



@Armando Let’s break of this discussion to another thread, or the CFML slack where I can figure out what it is you need. The CommandBox image won’t have the same paths you’re expecting, but that shouldn’t be an issue at all. We have it all documented where the files go and you can customize it as well if you need. Firstly, it doesn’t have a standard “Lucee install” at all :slight_smile: You could add your own CFConfig bits to the Lucee image, but that sounds like a lot more work. Jump on CFML Slack and chat with me so I can figure out what your needs are faster. Jon Clausen, the architect of the CommandBox images is also there to help.


I guess that means Docker Configs must mount the files as read-only, but I can’t find any supporting documentation to verify that, and I don’t have a Swarm running at the moment to test. I agree it would be nice if Lucee could avoid writing to the file during startup, but I can see that in other certain scenarios it could cause additional problems (e.g. during an upgrade where the file is read only for some other reason, it would be difficult to debug. Logging might be a workaround, but it might be designed to fail startup for some other reason too).

For customising something like a datasource you could put that in your application code rather than the lucee-server.xml using an approach like this:

Instead of hard coding the values your datasource configuration, you can use Docker Secrets or read them from environment variables using the server.system.environment scope;

Hope that helps :slight_smile: