CommandBox
Container
ColdFusion (CFML) CLI
Image details
Configuration
TypeContainerlinuxortussolutions/commandbox:latest8080/tcp8443/tcpTemplate by portainer
Standalone Install
Select an install method, to see config/commands for deploying CommandBox
Install on Portainer
Import all app templates into your Portainer instance, for easy 1-click deploys
- Ensure both Docker and Portainer are installed, and up-to-date
- Log into your Portainer web UI
- Under Settings → App Templates, paste the below URL
- Head to Home → App Templates, and the list of apps will show up
- Select CommandBox, fill in any config options, and hit Deploy
Template Import URL
https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json
Show Me
More install options in our documentation.
Tags
Note: For references to the specific versions of CommandBox used within image versions, please see the Changelog.:latest(Dockerfile) - Latest stable version:3.9.0- Tagged version of the image - not to be confused with the version of CommandBox within the image:snapshot- Development/BE version:[tag]-snapshot- Development/BE version of a tagged variations (e.g. -:adobe2021-snapshot):jdk8- Base image using OpenJDK8:jre11- Base image using OpenJDK11 JRE:jdk11- Base image using OpenJDK11 full JDK:jre17- Base image using OpenJDK17 JRE:jdk17- Base image using OpenJDK17 full JDK:alpine(Dockerfile) - Alpine Linux version of the image - slight decrease in overall size and optimizations for containerized runtimes:ubi9(Dockerfile) - RHEL Universal Base Image version of the image:[engine][version]- Containers with warmed-up engines - saves having to download the server WAR during container start::lucee5(Dockerfile),:lucee-light(Dockerfile),:adobe2018(Dockerfile),:adobe2021(Dockerfile),:adobe2023(Dockerfile):[engine][version]-alpine- Alpine linux versions of the image with warmed-up engines:
:lucee5-alpine(Dockerfile), :lucee-light-alpine(Dockerfile), :adobe2018-alpine(Dockerfile), :adobe2021-alpine(Dockerfile):[engine][version]-ubi9- RHEL ubi9 versions of the image with warmed-up engines:
:lucee5-ubi9(Dockerfile), :lucee-light-ubi9(Dockerfile), :adobe2018-ubi9(Dockerfile), :adobe2021-ubi9(Dockerfile)Note: The
:latest tag currently uses OpenJDK11, as do all other pre-built engine images. If you required JDK 8 or JDK 17 support in your app or engine, use the :jdk8 or :jdk17 tags, respectively. Description
CommandBox allows you to configure your entire CFML engine environment at runtime using file or environment-based conventions. For more information on how to leverage CommandBox in developing and deploying your applications, see the official documentation.In addition the CommandBox modules of
dotenv and cfconfig are included in these pre-built images, which allow you to leverage additional runtime environmental and server configuration options.Current CFML engines supported are:
- Lucee: 5+
- Adobe ColdFusion 2018+
You may also specify a custom WAR for deployment, using the
server.json configuration.Usage
This section assumes you are using the Official Docker ImageBy default, the directory
/app in the container is mapped as the Commandbox home. To deploy a new application, first pull the image:docker pull ortussolutions/commandboxThen, from the root of your project, start with
docker run -p 8080:8080 -p 8443:8443 -v "/path/to/your/app:/app" ortussolutions/commandbox By default the process ports of the container are
8080 (insecure) and 8443 (secure - if enabled in your server.json) so, once the container comes online, you may access your application via browser using the applicable port (which we explicitly exposed for external access in the run command above). You may also specify different port arguments in your run command to assign what is to be used in the container and exposed. This prevents conflicts with other instances in the Docker machine using those ports:docker run -p 80:80 -p 443:443 -e "PORT=80" -e "SSL_PORT=443" -v "/path/to/your/app:/app" ortussolutions/commandboxSupported Architectures and Operating Systems
All Debian-based images currently supportlinux/amd64, linux/arm64 and linux/arm/v7 architecture. Alpine builds are currently only supported on linux/amd64Environment Variables
The CommandBox Docker image supports the use of environmental variables for the configuration of your servers. Specifically, the image includes thecfconfig CommandBox module, which allows you to provide custom settings for your engine, including the admin password.Port Variables
$PORT- The port which your server should start on. The default is8080.$SSL_PORT- If applicable, the ssl port used by your server The default is8443.
Load Balancer Configuration
In order to use the multi-site features of CommandBox v6 and above, if your multi-site setup is domain-aware, you will need to set the environment variableBOX_SERVER_WEB_useProxyForwardedIP=true. Note, though, that doing so will open your container up to threat vectors by providing visitors with the ability to circumvent:- Internal-only host matching
- IP restrictions on admin blocking
as well as potentially allowing the spoofing of client certs and/or SSL redirects/validation. Because of this, if you choose to enable this setting, you should take care to ensure that your containers are only publicly accessible via the load balancer and exposed container ports on the Docker host are not publicly available. Once this setting is enabled, however, headers such as
X-Forwarded-Host sent by the upstream load balancer will be honored when service multi-site traffic.HTTP/2 Support
As of Commandboxv5.3.0, all CommandBox servers have HTTP/2 enabled by default. For browser support of this protocol, you will need to enable SSL and provide a certificate.Server Configuration Variables
The following environment variables may be provided to modify your runtime server configuration. Please note that environment variables are case sensitive and, while some lower/upper case aliases are accounted for, you should use consistent casing in order for these variables to take effect.BOX_SERVER_APP_SERVERHOMEDIRECTORY- When provided, a custom path to your server home directory will be assigned. By default, this path is set as${LIB_DIR}/serverHome, which resolves to/usr/local/lib/serverHomein most builds. The Alpine-based builds will default to/usr/lib/serverHome. ( Note: You may also provide this variable in your app's customizedserver.jsonfile )APP_DIR- Application directory (web root). By default, this is/app. If you are deploying an application with mappings outside of the root, you would want to provide this environment variable to point to the webroot ( e.g./app/wwwroot)USER- When provided the server process will run under the provided user account nameUSER_ID- Numeric. When provided in conjunction with aUSERenvironment variable, the UID of the user will be assigned this number. This can be useful for ensuring permissions of mounted volumes and filescfconfig_[engine setting]- Any environment variable provided which includes thecfconfig_prefix will be determined to be acfconfigsetting and the value after the prefix is presumed to be the setting name.BOX_SERVER_CFCONFIGFILE- Acfconfig-compatible JSON file may be provided with this environment variable. The file will be loaded and applied to your server. If anadminPasswordkey exists, it will be applied as the Server and Web context passwords for Lucee engines. You may instead add a.cfconfig.jsonfile to the root of theAPP_DIRand it will be picked up automatically.BOX_SERVER_APP_CFENGINE- Using theserver.jsonsyntax, allows you to specify the CFML engine for your container ( e.g.lucee@5). Defaults to the CommandBox default ( currently[email protected])BOX_SERVER_RUNWAR_CONSOLE_APPENDERLAYOUT- When setting this toJSONTemplateLayout, the log output of the container will be inndjson. For more information on this setting, please see the CommandBox documentation on customizing log layoutsFINALIZE_STARTUP- When provided a final startup script will be generated, which will be considered authoritative the next time the container/image starts. The caveat to this, however, is that the finalized startup script will bypass the evaluation checks for all of the other environment variables in this list as those values will be explicitly exported in the startup file.BOX_SERVER_PROFILE- When set, this will be applied as the runtime CommandBox server profile. By default, CommandBox will set this value to theproductionmode, since the container server binds to all interfaces on0.0.0.0. If you wish a lower level of security, you will need to provide this variable or set it in yourserver.jsonfile.BOX_SERVER_WEB_REWRITES_ENABLE- A boolean value, specifying whether URL rewrites will be enabled/disabled on the server. Rewrite configurations provided within the app'sserver.jsonfile will supersede this argument.CFPM_INSTALLandCFPM_UNINSTALL- Supported for Adobe Coldfusion 2021 engines. When provided as a delimited list of Coldfusion Package Manager packages, these will be installed ( or uninstalled, respectively ), prior to the server start. A warmed-up server is required to use these variables.BOX_INSTALL/box_install- When set to true, thebox installcommand will be run before the server is started to ensure any dependencies configured in yourbox.jsonfile are installed
Docker Runtime Variables
$HEALTHCHECK_URI- Specifies the URI endpoint for container health checks. By default, this defaults tohttp://127.0.0.1:${PORT}/at 20 second intervals, a timeout of 30 seconds, with 15 retries before the container is marked as failed. Note: Since the interval, timeout, and retry settings cannot be set dynamically, if you need to adjust these, you will need to build from a Dockerfile which provides a newHEALTHCHECKcommand
Deprecated Environment Variables
The following variables are still supported, however they are deprecated and support will be removed in the next major release version of the image:SERVER_HOME_DIRECTORY- UseBOX_SERVER_APP_SERVERHOMEDIRECTORYinsteadCFCONFIGandcfconfigfile- UseBOX_SERVER_CFCONFIGFILEinsteadCFENGINE- UseBOX_SERVER_APP_CFENGINEinsteadHEADLESS=true- UseBOX_SERVER_PROFILE=productioninsteadSERVER_PROFILE- UseBOX_SERVER_PROFILEinsteadURL_REWRITES/url_rewrites- UseBOX_SERVER_WEB_REWRITES_ENABLEinstead
Docker Secrets
Docker secrets can use two storage mechanisms:- Secret values stored as files on the host (non-swarm mode).
docker secret-managed key/value pairs (swarm mode).
Secret expansion can be accomplished by one of two mechanisms ( or both ):
<<SECRET:*>> Prefix
To use secrets as variables in this image, a placeholder is specified (e.g., <<SECRET:test_docker_secret>>) as the variable's value. At run-time, the environment variable's value is replaced with the secret.Example with a secret using host file storage:
version: '3.1'
services:
sut:
environment:
- IMAGE_TESTING_IN_PROGRESS=true
#- ENV_SECRETS_DEBUG # uncomment to debug the placeholder replacements
# this is a placeholder that will be replaced at runtime with the secret value
- TEST_DOCKER_SECRET=<<SECRET:test_docker_secret>>
...
secrets:
test_docker_secret:
# this is the file containing the secret value
file: ./build/tests/secrets/test_docker_secret_FILE Suffix conventions
When any environment variable is suffixed with _FILE, the right-hand assignment will be loaded and expanded as the environment variable prior to the suffix. The most common use-case for this is in sourcing Docker secrets, however it may also be used to source runtime-mounted files as variables.For example the variable
REINIT_PASSWORD_FILE=/run/secrets/reinit_password would source the contents of the right-hand file path in as the REINIT_PASSWORD environment variable.Best Practices and Customization
Customizing Images
To create your own, customized Docker image, use our Dockerfile repository as a reference to begin your customizations. You can extend any of the base images and add your own additional functionality or modules. For example, to install the Ortus Couchbase extension for Lucee:FROM ortussolutions/commandbox:lucee5
ARG REDIS_EMAIL
ARG REDIS_LICENSE_KEY
ARG REDIS_ACTIVATION_CODE
# Install the Ortus Redis cache extension from Forgebox
RUN box install 5C558CC6-1E67-4776-96A60F9726D580F1
# Scope in our args for extension activation
REDIS_EXTENSION_EMAIL=$REDIS_EMAIL
REDIS_EXTENSION_LICENSE_KEY=$REDIS_LICENSE_KEY
REDIS_EXTENSION_ACTIVATION_CODE=$REDIS_ACTIVATION_CODE
REDIS_EXTENSION_SERVER_TYPE=Production
# WARM UP THE SERVER WITH THE NEW EXTENSION
RUN ${BUILD_DIR}/util/warmup-server.shWe recommend using the pre-tagged images as your base, rather than starting from scratch.
Optimizing Startup Times
Because, with the exception of the CommandBox default engine of Lucee 5, the CFML server engines are downloaded and installed at container runtime. This can result in significant startup time increases ( even with Lucee 5 already downloaded in the base image, there is a time penalty for a "cold start" ). It is recommended that builds for production use employ an engine-specific variation for the build, which ensures the server is downloaded, in place, and warmed up on container start.For a basic example, the following will suffice:
FROM ortussolutions/commandbox:lucee5
# Copy application files to root
COPY ./ ${APP_DIR}/In many cases, you will have tier-specific builds, with custom configuration options. The following employs a
build directory, which includes additional configuration files for tier-based deployments:FROM ortussolutions/commandbox:lucee5
ARG CI_ENVIRONMENT_NAME
# Copy application files to root
COPY ./ ${APP_DIR}/
# Copy tier-only files over
COPY ./build/env/${CI_ENVIRONMENT_NAME}/tier/ ${APP_DIR}/
# Install our box.json dependencies
RUN cd ${APP_DIR} && box install
# Warm up and validate our server
RUN ${APP_DIR}/build/env/setup-env.sh
# Remove our build directory from our deployable image
RUN rm -rf ${APP_DIR}/build
# Set our healthcheck to a non-framework route - in this case we only need to know that CFML pages are being served
ENV HEALTHCHECK_URI "http://127.0.0.1:${PORT}/config/Routes.cfm"In the above case, the
setup-env.sh file might perform an additional server warmup and validation, where in the former case, the server was previously warmed up when the image was built.Once your customized
Dockerfile has has been built, you can run the generated image directly, or publish it to a private registry Multi-Stage Builds
As of v3.0.0 of the image you can create multi-stage builds which include only a shell script to start the server, the RunWar servlet container, and the application/engine. This build is finalized, however, so the startup script will bypass all environmental and server evaluation in favor of the variables provided in the generated shell script. This means that you will need to provide all secrets and variables needed by your server and CFConfig files during the initial build phase, as the.env and .cfconfig.json files will not be in play during the server startup.A finalized image reduces container startup times by up to 80% and reduces the final image size by up to 50%. Multi-stage builds are ideal for creating production images. The environment variable
FINALIZE_STARTUP, when provided, will only generate the startup script. The script written is considered authoritative and will be used on the next container start.To leverage this with a multi-stage build:
FROM ortussolutions/commandbox:lucee5 as workbench
# Generate the startup script only
ENV FINALIZE_STARTUP true
RUN $BUILD_DIR/run.sh
# Eclipse Temurin Focal image is the smallest OpenJDK image on that the same kernel used in the base image.
# For most apps, this should work to run your applications
FROM eclipse-temurin:11-jre-jammy as app
# COPY our generated files
COPY --from=workbench /app /app
COPY --from=workbench /usr/local/lib/serverHome /usr/local/lib/serverHome
RUN mkdir -p /usr/local/lib/CommandBox/lib
COPY --from=workbench /usr/local/lib/CommandBox/lib/runwar-4.0.5.jar /usr/local/lib/CommandBox/lib/runwar-4.0.5.jar
COPY --from=workbench /usr/local/bin/startup-final.sh /usr/local/bin/run.sh
# Restore working directory environment
ENV APP_DIR /app
WORKDIR $APP_DIR
# Restore the healthcheck, since that doesn't transfer from the first stage
ENV HEALTHCHECK_URI "http://127.0.0.1:${PORT}/"
HEALTHCHECK --interval=20s --timeout=30s --retries=15 CMD curl --fail ${HEALTHCHECK_URI} || exit 1
CMD /usr/local/bin/run.shSingle-Stage With Script Finalization
You may also create this finalized startup script in a single-stage build:FROM ortussolutions/commandbox:lucee5
# Generate the finalized startup script and exit
RUN export FINALIZE_STARTUP=true;$BUILD_DIR/run.sh;unset FINALIZE_STARTUPThis created image will contain the authoritative script with its runtime benefits and caveats ( see above ). Unlike the multi-stage build above, however , secret expansion will take place prior to image start, with the caveat that any environment variables in existence when the finalized script was generated will overwrite the runtime-provided variables or secrets.
About CommandBox
CommandBox is a standalone, native, modular CFML development and deployment tool for Windows, Mac, and Linux which provides a CLI for server orchestration, developer productivity, tool interaction, package management, application scaffolding, and some sweet ASCII art. It is open for extensibility for any ColdFusion (CFML) project and is written in CFML, allowing developers to easily write their own modules. It tightly integrates with the CFML open source hub ForgeBox, so developers can share modules world-wide.Learn more about CommandBox
Issues
Please submit issues to our repository: https://github.com/Ortus-Solutions/docker-commandbox/issuesLICENSE
Apache License, Version 2.0.Serve CommandBox on your own domain behind Caddy, Nginx or Traefik. Fill in your domain and copy the result. It's a starting point, some apps need their own base URL or extra headers set too.
Proxying commandbox.example.com to http://commandbox:8080
Add this to your Caddyfile
commandbox.example.com {
reverse_proxy http://commandbox:8080
}Check the logs first
Nine times out of ten the logs tell you exactly what went wrong.
- In Portainer, go to Containers, click the container, then Logs. Or run
docker logs <container> - Exit codes help too:
137means killed, usually out of memory.126or127means the command inside the image is broken.
Published on a random port
This template exposes 8080/tcp without setting a host port,
so Docker picks a random free one on every deploy.
- Find it in the Ports column of Portainer's container list, or with
docker port <container>
Image won't pull
Test the pull directly on the host: docker pull ortussolutions/commandbox:latest
- "manifest unknown" means the tag no longer exists. This template uses
latest, so try pinning a specific version instead. - "toomanyrequests" is the Docker Hub rate limit. Log in with
docker loginto raise it. - "no space left on device" means a full disk. Reclaim space with
docker system prune
"exec format error"
This means the image was built for a different CPU architecture than your server.
- This image supports:
amd64, arm64 - Check yours with
uname -m: x86_64 is amd64, aarch64 is arm64. Raspberry Pi and other ARM boards are the usual culprits.
Data disappears when the container is recreated
This template doesn't define any volumes, so everything the app saves lives inside the container and is lost on update or recreate.
- Add a volume mapping for the app's data folder before storing anything you care about.
Raise an issue
Found something which isn't working as it should? Here's how to report it.
- Bug within the app: Open an issue within the app's repo
- Template not working: Open an issue on portainer/templates
- This website not working: Open an issue on lissy93/portainer-templates
A single container
CommandBox runs as one container, the simplest kind of app here. Just the one image to pull and nothing else wired up alongside it.
The app image
An image is the app packed up ready to go, everything CommandBox needs bundled into one download. This template pulls ortussolutions/commandbox:latest, which Docker fetches once (about 411 MB) and then starts your own copy from.
Where the image comes from
Docker pulls its images from registries, public libraries of ready-built apps. CommandBox's comes from Docker Hub, published by ortussolutions.
Version tags
The bit after the colon in the image name is the version tag. Here it's latest, which always points at the newest build, so a redeploy can bump you to a newer release without you asking. Newest right now is 3.22.0. Pin a specific tag if you would rather stay on one version.
Which machines it runs on
Every image is built for particular CPU types. This one ships for amd64, arm64, so it runs on both regular x86 servers and ARM boards like a Raspberry Pi.
Ports
A port is the door the app answers on. Here the app exposes a port but leaves the host side blank, so Docker picks a free one for you. It opens:
8080, published on a random host port8443, published on a random host port
No stored data
This template doesn't mount any storage, so whatever CommandBox writes stays inside the container and is wiped if it's recreated or updated. That's fine for something stateless, but add a volume before trusting it with anything you want to keep.
Environment variables
Environment variables are the settings you hand over when you deploy, things like a password or a timezone. CommandBox takes 1 of them, all with defaults you can leave alone or tweak:
CFENGINE, defaults to[email protected]
Networking
Nothing custom is set, so CommandBox sits on Docker's default bridge network: its own private space that reaches the outside world only through the ports it publishes.
Platform
The platform is linux, the kind of system the container is built to run on. Docker and Portainer handle this on a normal Linux server.
Portainer app templates
Zooming out, this whole page comes from a Portainer app template: a short recipe telling Portainer how to set CommandBox up. Add the template list to Portainer once, then deploying CommandBox is a click rather than a wall of config.