Is there an easy way to insert a datasource to lucee-server.xml from the command line (say, when Docker is building a docker image ) ?
I want to insert a global datasource shared by all the contexts on the server.
I’ve tried using sed to replace in the XML blob I see being added when I use the server web interface to do this, but Lucee always seems to say
2017-04-28 15:44:37.254 config file /opt/lucee/server/lucee-server/context/lucee-server.xml was not valid and has been replaced
2017-04-28 15:44:37.256 write file:/opt/lucee/server/lucee-server/context/lucee-server.xml
We usually set datasources in the application.cfc via the this.datasources array, and populate the settings with environment variables. This way your build isn’t tied to a particular environment, you can easily pass in different settings no matter where you want to run your container.
Sometimes it can be very useful to use the web GUI to update all the permanent settings you want for your Lucee installation. This automatically updates the underlying XML config files and all you need is to capture those changes and push them in at build time.
We store our project configuration in a subfolder structure beneath the location of the Dockerfile:
These can be committed to version control and copied via the Dockerfile at build time:
# Lucee server configs
COPY config/lucee/lucee-web.xml.cfm /opt/lucee/web/lucee-web.xml.cfm
COPY config/lucee/lucee-server.xml /opt/lucee/server/lucee-server/context/lucee-server.xml
You can map these configuration files into your container using VOLUMES during development so you can easily capture any changes you might make to the admin; for example, a docker-compose.yml file might include:
Note, it’s not ideal if you need these values to change at container runtime You need to use ENV variables for this. Fortunately, Lucee allows you to set many configuration flags directly or programmatically via the Application.cfc.
But, con-wise, if that shared data source ever changes, you need up update all the projects. We also have per-project datasources, and setting them up via Application.cfc is definitely where I want to get to.
If the data source parameters are all dynamically populated from EVs as in Geoff’s example, (or even just those that are liable to change) then surely you only have to change the environment variables, not the project code.
That’s right, you just update the environment variables in your orchestration tool/platform of choice, no need to change any code/files and no need to do a new Docker image build of your app
To take it a step further, sensitive data is better managed using a secrets store of some kind (Swarm has built-in support for Secrets, or you can use other solutions like Vault, etc). There’s a little bit of extra complexity to deal with here, and the landscape is evolving pretty quickly, but that’s the direction things are heading.
And tell all the team the new environment variables etc. And if we added a new param that had to passed to the (shared) DSN, update all the projects (again).
For now it’s easiest to bake the DSN (and the secrets) into the image I think. Trying to be as simple as possible to start with and not change the existing project code to match our current deployment tool!.
If team members are each using a locally installed dev server then you’d have to tell them about changes anyway so they can update their local admin settings. The only difference is where those details are stored: in the Lucee server settings versus in the host server’s EVs.
In theory there’s a custom attribute which allows you to put additional the params together as a struct. You could store that value as an EV so it could be changed without altering app code. In practice it seems to be a bit buggy.
One potential “con” though is that EV changes do require a Lucee/JVM restart to be picked up.
However I’m definitely leaning towards EVs as the best and simplest place for these types of variables.
If you’re only approaching it from a local dev perspective then you could bake them in, but once you consider deploying to other environments like stage and production you’ll quickly be wanting to use settings that come from the environment / orchestration tool.
A single build of a Docker image can be deployed to stage and then to production without any changes, because all your configuration comes from the environment rather than code/files inside your image
For example, for local dev you can store your particular environment variables in a docker-compose.yml file, or in env files that are picked up by your compose file. For stage and production, you might be using Mesos/Marathon in which case the environment variables come from the application definition (think of it as a .json file), or if you were using Docker Cloud it might come from a stack file (basically a compose file with a few extra options). The point is that your code / build / Docker image doesn’t need to change, you can deploy it anywhere and let the settings come from the environment.
My current (getting started) plan is just to move to Docker for day-to-day development. So I’m building a simple reusable Docker image that non-Docker-knowledgeable people can pull, run and be up and running as easily as with a remote Lucee and a network share (+ a one time change to their hosts file per-project).
Our (eventual) production (and dev, stage etc) containers won’t be based on this image, so it makes more sense to use the environment variables there I think.
The password can be encrypted or not, it’s up to you. if it’s encrypted, it always starts with the text “encrypted:” I have a utility on ForgeBox called the Lucee password util that will do this, or just create the datasource in your admin, go back and edit, and scroll to the bottom of the page where the encrypted version will be output on the page for you to copy.