CFWheels, meet Docker
You’re probably like I was also: curious about Docker and what it could do for you. If you’re familiar with CFWheels, this is a great way to jump in and see if it’s right for you.
Installing Docker and Docker Compose
To use such a setup, you need Docker and Docker Compose installed on your local machine. This depends on the operating system, but for our Macs, it involved using Homebrew to install
fig (that’s how it’s named in Homebrew because they won’t change the name for some unknown reason).
I found Josh Clayton’s instructions to be helpful when I was first starting out with Docker.
Our own boilerplate on GitHub
Major props to Adam for sharing his implementation online. But I forked it and tweaked things a little.
The main difference is changing the Ubuntu image that the
Dockerfile is based on to Phusion’s Baseimage-docker. I recommend reading up on Baseimage-docker after you get your feet wet.
I’ve also taken the liberty to put a blank CFWheels application in the
app folder and configured it to take advantage of Docker Compose’s
environment settings. (More on that in a minute.)
After you download the code, copy
docker-compose.yml, and run this command to build the Docker image:
It takes a few minutes to download and install Lucee, but don’t worry: this Lucee installation will be cached for your application unless you change the version number in the
Dockerfile. (Hence upgrading Lucee is as easy as changing the version number in your
Dockerfile and running
To run the application, run the
docker-compose up command and visit
http://192.168.59.103:3000 in your browser.
(Note: Port 3000 can be changed to whatever you want in
docker-compose.yml. Also note, if you can’t connect to your application, try running
boot2docker ip to make sure you should in fact be hitting the standard
192.168.59.103 IP address.)
Configuration via environment variables
I also set up a sample
docker-compose.yml file that does something a little different than most ColdFusion developers are used to:
environment hash. That sets up environment variables to be picked up by the operating system and passed on to Lucee. That’s where you would setup your data source according to Lucee’s documentation. (See
config/app.cfm for a peek at where these settings are being used.)
That’s right; my aim is to not use the Lucee Administrator for anything so that I can configure environment variables in
docker-compose.yml, add mappings and/or custom tag paths to
config/app.cfm, deploy code, and be done with it.
Here’s what configuring a data source looks like with this setup:
You could also add other keys for things that change depending on the environment you have configured, like 3rd party API credentials, SMTP servers, your Google Analytics Tracking Code, or whatever.
server.ENV variable setup in the above example
app.cfm, you should be able to write logic within your application based on the values instead of the CFWheels environment you’re in:
A note about databases
Many examples of Docker Compose suggest that you also configure a Docker container for your database. I have yet to ever get that to work properly on my machine. Sure, it works, but then when I need to rebuild my environment with
docker-compose build, it wipes out my database’s data.
I’ve tried every suggestion of mounting volumes or setting up volume containers via Docker Compose, but I’ve never been able to get it working properly.
That aside, in development, I suggest that you install the database directly on your development machine and setup the
DB_HOST environment variable to reference the LAN IP address of your development machine.
On my Mac, I can get my LAN IP by running this command:
On Windows, you can run
ipconfig and grab one of those IP addresses. (Can’t remember which one, and I have the lazy.)
Docker in production
Hosting Docker-based apps in production still seems to be in the “early adopter” phase. It’s probably possible to build your own Docker-running infrastructure. But for me, no thank you!
The easiest solution I’ve found so far has been Cloud 66, a PaaS provider that I’d halfway dare to call the “Heroku of Docker.” You point Cloud 66 at your Git repo, and on deploy, it pulls in your code and builds a Docker image on the fly based on your
Dockerfile. (Or you can tell it to use your own pre-built image if you want a faster deployment.)
After that, you have your CFWheels app running in production with the exact same OS, Lucee runtime, and code that you were running in development. Win!
I’ve found configuring Docker services on Cloud 66 to be very similar to the
docker-compose.yml file that I shared earlier in this post. They’ve done a nice job trying to keep things as consistent as possible. They’ve even chosen to host your database outside of Docker containers too, perhaps for the reasons I listed earlier.
Lastly, there is an interface for configuring your environment variables, or you can also configure those along with the services, just like with Docker Compose. There, you can set
production and not have to worry about accidentally deploying a
config/environment.cfm file that is set to
development. (I’ll admit to having done that once or twice.)
I’ve always been a fan of open source engines like Railo and Lucee because they make this sort of automation easier (and dare I say, possible) when compared to what Adobe ColdFusion licensing allows.
I’m sure I’ve left something out, so leave a comment or open an issue if you have questions or suggestions on how to improve this setup.