CommandBox/ColdBox on Google App Engine

I need to run another process (cloud_sql_proxy) inside the CommandBox Docker container for a connection to a Google MySQL Database.

As there is only one CMD in the Docker File and that is controlled by the commandbox docker build is it possible to run this second process?

You can override the CMD in a custom image that points to a shell script that first kicks off your process, and then kicks off the original RUN.sh or whatever it’s called.

Have you seen this though? I’m not familiar with the cloud sql proxy, but it appears they have a dedicated container for it. Perhaps it’s better if you spin it up on its own and then proxy through that container?

I’ve had this running for a few years now but it was from a base image where I added the components for Lucee, using supervisord. Cloud SQL is only a small program but it needs to run on the main image to provide port 3306 MySQL access.

The part I’m confused with is that using OrtusSolutions/CommandBox image I don’t have the same access as the container is already built.

Thanks for your help Brad…

I would question if what you say is true. I get that you have historically run it on the main image and you’re used to running it on the main image, but from my quick reading online yesterday I didn’t see an indication of that being a requirement. It would appear the proxy is designed to run in its own container and you simply point to that host:port and it proxies on.

Generally speaking as Docker goes-- one Docker container is supposed to have a single process. Any time you try to shoehorn more than one process, you’re sorting of working against the grain. Yes, I know people do it, but there’s usually a better way.

I don’t quite understand what you’re asking. Yes, ortussolutions/commandbox is an image that is already built, but the very nature of Docker is that anyone can take any image and build their own image on top of it.

Dockerfile

FROM ortussolutions/commandbox

# you customize stuff here...

This is basic Docker 101. In fact, I assume this is precisely what you did in the past when you wedged Lucee/Tomcat into the existing proxy containers. If you really want to make this work with a single image, I would start with the CommandBox image as the base and add the proxy program, not the other way around.

Agreed - I must be missing some understanding from Docker. I want to run the proxy process after commandbox starts as it provides the port for MySQL. Cloud SQL connector is only 15MB and can be run locally or inside a docker container.

It’s overkill to run a separate container.

This was my Dockerfile -

FROM lucee/lucee:5.3-nginx

COPY default.conf /etc/nginx/conf.d/
COPY supervisord.conf /etc/supervisor/conf.d/
COPY cfspreadsheet-lucee-5.lex /opt/lucee/server/lucee-server/deploy/
COPY ortuspdf-2.1.0.lex /opt/lucee/server/lucee-server/deploy/
COPY pdf-extension-1.0.0.68.lex /opt/lucee/server/lucee-server/deploy/
COPY lucee-server.xml /opt/lucee/server/lucee-server/context/

RUN mkdir -p /var/www
COPY index.cfm /var/www

RUN wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
RUN chmod +x cloud_sql_proxy

CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]

I then added code into the Lucee working directory in a subsequent Dockerfile build. I was adding code, not starting a process. This is where my understanding breaks down. There is only one CMD command in a docker image so the running image does not use the commandbox CMD command, rather the one I provide?

I understand if you don’t want to, but this is actually how Docker was designed to work!

Ahh, I see-- so you were adding the cloud sql proxy into the base Lucee image. Yep, that all makes sense.

I’m not sure what you mean by that. When you build an image, you’re adding to it. When you start a container, then you start a process. Which in your case was the supervisor process, which in turn, started the other processes.

Yes, this is correct. I’m a little confused by the line of questioning however since I asssume you created the docker file you posted above and have a working understanding of it. But now it sounds as though you’re asking how it works. I’m unclear if you’re asking how supervisor works or just how it would work in the CommandBox images. Because it it works in the CommandBox images the exact same way it would work in the Lucee images so far as I know.

Presumably, when you did this with the Lucee images, you placed the original command to start Lucee in the supervisord.conf file and you would do the same thing here, but using the default command the CommandBox images use.

Tagging @jclausen in case he has any further insight on this topic.

I was trying to avoid supervisord as it is a relatively heavy process. Yes, I understand the Dockerfile above but looking back on my code the second build phase did not have a CMD command, just clean up lines and a COPY command.

When I said adding code, I meant just that - no process to start so it was a copy to a directory that was already there…

Thanks for tagging @jclausen - I watched both his videos in CFCasts. I think I am close to an understanding but there is something blocking my understanding.

Lol, well if you’re looking for alternatives that’s a different question. I don’t tend to run more than one process in my docker containers so I’m not sure what your options are. I assume at minimum you can override the CMD to be a shell script that simply starts the SQL proxy process and forks it async prior to delegating to the original command, but getting access to things such as the standard out logs would probably be difficult.

Correct, that’s because the CMD is specified by the parent image so you don’t need to specify it again. It’s already there.

It’s port 3306 that the original container needs to access and using the Dockerfile above this is possible using supervisord.

After talking to my sources it seems that Docker does not run any CMD command in any previous images used to build the final image.

So, as you rightly said earlier, my final Dockerfile has the CMD command which needs to run my script that starts Google SQL Proxy and then points to the run.sh in commandbox.

Maybe @jclausen could comment on this log access situation?

This port has nothing at all to do with whether you use supervisor. Let’s say you’re using docker compose and you start the proxy container up with a service name of sqlproxy and expose port 3306 on that container. You’d simply connect your CF datasources to sqlproxy:3306 as opposed to localhost:3306. All supervisor allows you to do is work around the Docker design limitation that a given container only runs one process by running a process that runs other processes.

Any time you build your own image FROM another image, you inherit the CMD of the original image unless you override it. So the CMD’s don’t stack up, they simply overwrite any previous CMD that was set. Also, when you specify a CMD in a docker file, you’re not running that command when you build the image-- you’re just setting the command for later reference for when a container actually starts from that image.

I’m not / can’t use Docker Compose with App Engine - I have a Dockerfile and app.yml to specify the system.

What led me to this confusion is that CommandBox is an image of an application to which you add your own code, whereas I’m adding a process to the image of an application.

I think I understand the way to go and will report back on my success or lack thereof!

It was just an example. I’m sure Google App Engine has their method of having related containers. I assume they are using K8s.

Right, but it’s not any different from the “official” Lucee images in that regard so whatever you did there works the same here.

Good luck!

Unless you have nodaemon=true in the supervisord.conf file you are copying in, you will want to run it in the forgeground to expose the output from all of your processes.

That would be:

CMD ["supervisord", "-c", "-n", "/etc/supervisor/supervisord.conf"]

Yes - I used the nodaemon=true in the supervisord.conf file.

The build I have for App Engine has been used for a few years now - long enough to get very rusty with Docker! The main issue is a slow launch in App Engine. I put this down to using App Engine Flexible but it could also be related to supervisord and other processes running from the initial image.

But also I have decided to move my legacy app (not written by me) from the original way of writing CF (ie no functions, loads of includes and no testing) into ColdBox so that I could enable other devs to work on it. App engine has served me well with the previous incarnation. This means that I need CommandBox to run on a container under App Engine. Your videos have proved helpful but I’m only partially through understanding them.

My idea is to build the image, use CMD to start my own script which will run Google SQL Proxy and then start run.sh in CommandBox - do you think this will work?

Dockerfile

FROM ortussolutions/commandbox:lucee5-3.6.2

COPY script.sh $BUILD_DIR/

COPY cloud_sql_proxy $BUILD_DIR/

COPY printmanager-1ca5da5741ed.json $BUILD_DIR/

CMD $BUILD_DIR/script.sh

script.sh

$BUILD_DIR/./cloud_sql_proxy -instances=printmanager:us-central1:printmanager=tcp:3307 -credential_file=$BUILD_DIR/./printmanager-1ca5da5741ed.json &

$BUILD_DIR/run.sh

This works fine - I’ve tested it as far as telneting to the db port and getting a response.

One thing that was weird though, was the /./ needed after the $BUILD_DIR - Could you throw some light on why?

Anyway thanks for your help - It was trivial in the end!

1 Like