Howdy folks... can someone provide information on ...
# lucee
m
Howdy folks... can someone provide information on how to actually use LUCEE_ENABLE_WARMUP environment variable, with regards to "typical" workflow? I have a Lucee app/docker that is having issues when deployed to a relatively high traffic kubernetes environment, and the application is using ColdSpring/FW1. Our most recent deployment saw three containers start up, and one of them started spewing an error on every request, that certain classes were "not found" when referenced by EntityNew(), etc. even though the components were in the directories for the ORM/ColdSpring to find. The assumption here is that the server needs to be warmed up first, before it gets hammered with that traffic. So i started working on it this morning. When I build the image locally, i had env variable LUCEE_ENABLE_WARMUP set to true, but when I ran the image with that set, it starts up and then shuts down. When I set it back to false and ran the same image without (re)building it, it starts up and runs fine, but I don't notice any improvement in time-to-first-request/response, so I can't really tell if the setting is doing what it should. There's not much about this var in the documentation, so I'm just not sure how it should be used. TIA for any info!
after pondering further, I set the actual env variable for docker run to
false
, but added it as
true
directly to the Dockerfile and have observed the "warmup" notice during the build, with no shutdown happening during running of the container. But i'm not sure if it's doing what it should, as the first request still takes some time to get a response. If this is the workflow (build: warmup=true, run: warmup=false), then I guess I just need some sort of way to confirm that it's actually working.
p
Are you utilizing Commandbox to run Lucee for your app? Also are you using a headless environment to increase warm up time?
And does your docker image have a health check which should trigger the app firing up and fully having the coldspring objects made etc
m
We are not using CommandBox at this time (long story). Not sure what you mean by headless environment. the docker image itself does not have a health check, only the K8s deployment/environment (which on our last deployment, allowed the unhealthy node to end up in production anyway, which is a separate issue to be solved). I can try adding HEALTHCHECK to the Dockerfile if that's your suggestion of course
p
Well there are numerous approaches to dockerizing. I guess I would need to see some sample code to understand how yours is functioning. But typically we have health checks that require to pass before its announced as warmed up thus the app is up and functioning.
and sorry you are not in commandbox 😢
m
if i were to make the effort to implement commandbox, what does the solution to this issue look like in that context?
p
and headless means no CFAdmin UI
which is a lighter weight image
m
For now we're still using CFAdmin in production (properly secured) since this is an app that was converted from Adobe CF/IIS to Lucee/Docker/K8s and it's nice to be able to open the UI and poke around... but eventually we could not install the Admin extension (if that's the right way to go headless?) in the production docker image.
p
Well for production in my world, headless is the best and faster approach. As for your issue, again I would need to see your dockerfile to understand better; but DM if you want some more help
m
Thanks Patrick, I'll try to experiment more. Does commandbox solve this "out of the box" ?
p
Yea commandbox you can just have a flag in your file for $HEALTHCHECK_URI. Also for going headless too. Commandbox makes stuff superrrr simple, not to mention CFCONFIG helps to spin up everything you would need in CFAdmin so that you can easily go headless and dont need to look in the CFAdmin UI.
m
thanks... checking it out now to see how much effort it might be to convert our current version over to that. I'll probably have to resolve the immediate issue sooner, however.
b
@Marc Funaro All the Lucee warmup flag does is start Lucee and then stop it after • The lucee server and web contexts have been deployed on disk • All OSGI bundles are unpacked and in place • All core extensions are installed • Any extensions in the deploy folder are installed • Any extensions specified by env vars are installed
The main goal is just to have all that ready in the image AND to not be downloading anything when the container deploys
The old way used to be • put lex files in deploy folder • start server • sleep for ????? seconds • stop server with fingers crossed, hoping you didn't stop too early and fubar the server
The flag gives you a clean way to ensure everything is set up before it shuts down
m
so while that's obviously good to do, it sounds like the Dockerfile HEALTHCHECK would be the "rest" of the equation - hitting a URL that fires up the app before the container is considered healthy, so that the app itself can warm up as well.
b
It's also worth noting the warmup won't compile any of your class files or anything.
Yes, if you have an app that takes a long time to load on application start, then that's where the healthcheck URL comes in. It won't get traffic until it's ready to serve
šŸ‘šŸ» 1
m
is it definite that the container won't be fully accessible until the healthcheck (1) executes at least once, and (2) returns a 200 status, or might there be an additional config we need to consider, perhaps in the kubernetes configuration itself?
b
And a couple other notes • healtcheck isn't unique to the CommandBox images, it's a basic docker feature we make a little easier out of the box • The commandbox images block the CF admin URLs by default, but you can still re-enable them if you like. It's all configurable • The biggest benefit of the box images is probably the inclusion of CFConfig to handle all your admin config (no need to even log in!) • The next biggest benefit is the drop-in functionality like the FuisionReactor module, etc and the built in environment variable overides for EVERYTHING in server.json as well as all CFConfig settings.
For example, you can override a datasource password on the fly with a single env var and CFConfig/CommandBox. Lucee's images have nothing at all in that department.
is it definite that the container won't be fully accessible until the healthcheck (1) executes at least once, and (2) returns a 200 status,
Out of the box, the healthcheck command in our images is just a basic curl to
/
that needs to get a successful return. You can still configure that further if you like such as • the URL to his • the timeout before trying again
m
great. short term, i'll have to manually implement the HEALTHCHECK in our Dockerfile first, to try and get our pipeline deployments more stable. Longer term, I do think we should update to using commandbox.
b
So do I, but I'm biased šŸ˜†
m
and on top of all that, we also need the K8s configuration to recognize when a container is unhealthy (i assume it should just obey the HEALTHCHECK i specify, now that we'll have it), since it allowed an unhealthy container to continue running when we last deployed.
but imma leave that for our K8s expert to deal with 😃
b
I'm not sure how K8s works, but we use Docker Swarm and that's exactly how it happens
p
Brad the creator; I just love to promote it because it is a game change from all the manual processes!
😁 1
b
Here is the basic healthcheck config the commandbox images use just to give you an idea https://github.com/Ortus-Solutions/docker-commandbox/blob/5b8377e48945d690e7f7bef7d1095e989351c48c/builds/base/Dockerfile#L67-L70
m
so it allows the request to take 30 seconds to respond, and it would have to fail 15 times before it exits with error?
just looks a little weird to have a 30s timeout and a 20s interval
b
Some people have very large apps that take a a LONG time to come up šŸ™‚
Especially if they are on Adobe, lol
If the app is legit down and erroring out, it's going to go through 15 tries very fast because each one fails right away
m
gotcha.
b
Plus, you don't want your containers to all get killed off right away if your DB blips!
You want to have a bit of grace before you go killing the container
m
I understand that if curl times out, after all the retries it'll throw an error. But i assume that if curl returns anything other than a 200, it also throws an error?
b
You'd have to defer to the curl docs for that one. I don't know off the top of my head how
--fail
handles that
p
The container should fail to start; not sure about the exact code but I believe it needs 200; but yea look at curl docs
m
yep yep. thanks again, you've all been very helpful in filling my brain and confirming some things for me! 😃
šŸ‘ 1
p
So I guess you can write up your own "healthcheck" shell script to what determine what is healthy or not...
Copy code
HEALTHCHECK --interval=2s --timeout=5m --start-period=3s CMD bash healthcheck.sh
And the healthcheck.sh being :
Copy code
#!/bin/sh

code=$(curl -o /dev/null -s -w "%{http_code}\n" <http://localhost/ping>)
echo "response code: $code"

if [ "$code" == "200" ]
then
  echo "success"
  exit 0;
else
  echo "error"
  exit 1;
fi
m
i did a test earlier today, where the healthcheck URL i used was purposely pointing to a non-existing page, to force a 404. when i built the image and started the container, the container registered as unhealthy, so i'm wondering if curl already returns a 1 or 0 exit code
b
I'm pretty sure that's what the
--fail
flag does
it means curl returns a "failing" exit code if the HTTP request is considered failed.
p
Basically curl is saying anything other than 0 is a fail
m
22. HTTP page not retrieved. The requested URL was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if
-f, --fail
is used.
šŸ‘šŸ» 1
b
curl is saying anything other than 0 is a fail
That's not really a curl standard. Every shell across all operating systems treat exit codes like that
What curl is doing is mapping HTTP response codes to a pass/fail status
āœ… 1
p
Well, yea I was just saying how I think of it. Might not be the formal explanation heh.
b
Right, Marc's question was what requests curl would consider a pass or a fail. That doc, while long, manages to not actually answer that question šŸ˜† It just says
the operation went as planned.
I think it's safe to say a 200 status code is "as planned", but what about a 203 (Non-Authoritative)? A 302 or a 301? They're sort of vague about that
p
yea and in that case, write your own shell script and move along since you have a set of "Pass" codes in your own desire outside of what that curl is resulting.
b
Well, we don't know that. Perhaps curls set of pass codes matches our expectations. I was just saying at this point I don't know what their logic is
p
we actually had this convo issue a few years back heh when I had to abandon healthcheck for an environment if you recall Brad lol.
b
I don't recommend using a healthcheck for a development environment. Otherwise, your container won't be reachable when you have an error, lol
šŸ˜‚ 1
But then again, I don't recommend docker for development either šŸ™‚
Ok, looking at the man pages for
curl
, it seems that curl always returns a failing exit code if it thinks the request failed. All the
--fail
flag appears to do is tells it to fail silently and not go spitting out to the console.