Blog

CommandBox Docker Image 3.6.0 Released

Jon Clausen March 28, 2017

Spread the word

Jon Clausen

March 28, 2017

Spread the word


Share your thoughts

This morning, we released the official Docker CommandBox image v3.6.0, which adds support for customizing your server using environment variables in your build, including support for the conventions used by the cfconfig CommandBox module. While the module is still in alpha, it is already proving to be a powerful way to provision and configure CFML servers at runtime.

Why use Docker?

If you're not up to speed with what Docker is and how it can benefit you, throughout the dev-ops lifecycle of your application, have a look at this summary article on the benefits or dig in to the official documentation. As we get further in to the weeds with configuration, we'll assume you're up to speed on the basics.

Running a CFML Docker Container using the CommandBox image

Once you're up to speed with running Docker on your local machine, starting up a CFML server using the CommandBox image is as simple as:

docker pull ortussolutions/commandbox
docker run -p 8080:8080 -v "/path/to/your/app:/app" ortussolutions/commandbox

This will serve a CFML application on port 8080 (which is the default $PORT variable of the image) of the active Docker engine. If you have a server.json file in the root of your directory, all of those config settings will be transferred over, with the exception of three, which will be overridden by the environment variables and used to expose the image: web.http.port, web.ssl.port (if applicable), and host. The variables $PORT and $SSL_PORT may be specified when running the container, and will be used in place of the defaults. This allows you to prevent conflicts with other containers (e.g. Tomcat) which may use the default port. Note the -v directive in the docker run command which mounts your application in to the /app directory of the container - which is the convention path CommandBox uses to serve your application.

The implementation problem of the above command is that it doesn't allow us to really deploy a configured CFML server. Through the 3.5.0 docker image, the only way to do that was to specify a custom app.serverHomeDirectory in your server.json file and then commit only your configuration files. Example .gitignore for an ACF2016 server confiugured with an app.serverHomeDirectory of /app/.engine (placed inside your .engine directory):

*
!.gitignore

!/WEB-INF/cfusion/lib/neo-*.xml
!/WEB-INF/cfusion/lib/*.properties
!*/

In the above .gitignore, we are only persisting the .properties and neo-*.xml files used to configure the Coldfusion 2016 server. When the CFML engine WAR is exploded on the startup of your engine, those config files will persist and your server is pre-configured. You can still do this, however CFConfig offers a way to accomplish the same thing without any configuration files in place through the use of environment variables. A quick tour of the available environment variables:

  • $PORT - The port which your server should start on. The default is 8080.
  • $SSL_PORT - If applicable, the ssl port used by your server The default is 8443.
  • $CFENGINE - Using the server.json syntax, allows you to specify the CFML engine for your container (i.e. - adobe@2016 or lucee@5 )
  • $cfconfig_[engine setting] - Any environment variable provided which includes the cfconfig_ prefix will be determined to be a cfconfig setting and the value after the prefix is presumed to be the setting name. The command cfconfig set ${Setting: settingName not found}=${Setting: value not found} will be run to populate your setting in to the $SERVER_HOME_DIRECTORY You can checkout an example config file here.
  • $CFCONFIG - If you need advanced configuration - datasources, caches, timeout settings, etc - a cfconfig-compatible JSON file may be provided with this environment variable. The file will be loaded and applied to your server. For Lucee servers, if an adminPassword key exists, it will be applied as the Server and Web context passwords.
  • $SERVER_HOME_DIRECTORY - When provided, a custom path to your server home directory will be assigned. By default, this path is set as /root/serverHome ( Note: You may also provide this variable in your app's customized server.json file )

If you already have a pre-configured CFML server you'd like to use, simply install cfconfig and save your existing setting with the following commmand:

box cfconfig export myConfig.json /path/to/my/existing/server/install adobe@2016

View the docs for more config, transfer, import and export information.

Once you have your cfconfig file set, a simple docker run command would be:

docker run -p 8080:8080 -e "CFCONFIG=/app/myConfig.json" -v "/path/to/your/app:/app" ortussolutions/commandbox

The -e "CFCONFIG=/app/myConfig.json" argument tells docker to set an environment variable of CFCONFIG to /app/myConfig.json. If that file exists when the Docker container is started, the configuration will be automatically applied. (Note: For additional security, you can mount your config in to a non-app path and simply change the environment variable above.)

Compose It

In reality, deploying a CFML server usually requires additional connection dependencies. If you need to deploy those dependencies along with your application, the easiest way to do so is using Docker Compose. It also provides a much more human-readable configuration, in comparison to script one-liners.

Let's say we want to deploy a self-contained stack that includes your CFML server, MySQL server, and reverse proxy your web traffic via NGINX. A single compose file in the root of your app, which connects the three of these containers might look like:

version: '2.1'

services:
  # NGINX Container
  web:
    image: nginx
    ports: 
      - "80:80"
      - "443:443"
    # Mount our shared webroot volume
    volumes:
      - .:/usr/share/nginx/html
      - ./build/docker/nginx/nginx.conf:/etc/nginx/nginx.conf
  
  #Application Server
  app:
    image: ortussolutions/commandbox 
    environment:
      PORT: 8080
      SSL_PORT: 8443
      CFCONFIG: /app/cfConfig.json
    volumes:
      - .:/app

  #MySQL
  mysql:
    image: mysql:latest  
    environment:
      MYSQL_ROOT_PASSWORD: "MyS3cur3P455!"
    volumes:
      - ./build/docker/mysql/initdb:/docker-entrypoint-initdb.d
      - /my/host/datadir:/var/lib/mysql
    ports:
      - "3306:3306"

There are a few things going on in this file, of note:

  1. We've mounted our NGINX configuration as well as the application in to the convention routes for configuration and the HTML root. You can skip the HTML root mounting, if you wish, as CommandBox will also serve your static files. We would need to provide the appropriate proxy settings from nginx to the host app:8080 in order for NGINX to deliver our CFML, however
  2. We've provided our CFCONFIG environment variable to our app container, which will be used to automatically configure the CFML server.
  3. We've mounted an initdb directory in to the MySQL container's /docker-entrypoint-initdb.d directory. The MySQL image will pick up any scripts in this directory, when it inits and run those scripts automatically
  4. We've mounted /my/host/datadir in to /var/lib/mysql in the MySQL container to allow our data files to persist between builds of the container.

Now, to start this "stack", from the root of our project, we can simply type:

docker-compose up --build

Your terminal will be filled with the results of the individual containers starting up, which may help you to debug configuration issues within the stack.

To bring up the stack quietly, use docker-compose up -d, which will daemonize it.

Docker is increasingly becoming a powerful tool for orchestrating, scheduling, and deploying applications. It can also provide a powerful framework for common development environments for teams. If you're new to Docker, feel free to take the image for a spin. Once you pass the initial learning curve, we think you'll be excited about this powerful new tool in your toolbox!

Add Your Comment

(1)

Mar 29, 2017 15:34:41 UTC

by Jim

Good to see the ColdFusion community exploring tools like Docker and containers! I know what I'll be doing this weekend :)

Recent Entries

The hidden costs of outdated ColdFusion Apps (And how to fix them)

The hidden costs of outdated ColdFusion Apps (And how to fix them)

Is Your ColdFusion System Quietly Costing You More Than You Think?

Many organizations continue to rely on ColdFusion systems that haven’t been updated in years. While these systems may still be running, they often come with hidden operational, financial, and security costs that can compound over time.

In this article, we’ll explore the true cost of maintaining legacy ColdFusion applications—and how teams can start reducing that burden through ...

Cristobal Escobar
Cristobal Escobar
March 26, 2025
ContentBox v6.1 Released

ContentBox v6.1 Released

In this release, we're thrilled to unveil a series of significant enhancements and upgrades to ContentBox designed to elevate your experience and considerably improve system performance. Our team has focused on integrating the latest CommandBox migrations and ColdBox Core, which ensures that the core system continues to operate with maximum efficiency and stability. This upgrade is part of our ongoing commitment to maintaining a cutting-edge platform that meets the evolving needs of our users.

Luis Majano
Luis Majano
March 19, 2025