January 10, 2020
Creating a Development Environment/Workflow for solo or small team development using ColdFusion, MS SQL Server, and Docker Compose – Part 1
Comments
(6)
January 10, 2020
Creating a Development Environment/Workflow for solo or small team development using ColdFusion, MS SQL Server, and Docker Compose – Part 1
Master 31 posts
Followers: 17 people
(6)

I worked with a client who developed in a very frightening fashion by todays standards.  The company was founded 20 years ago, mainly had a single developer, and they developed against the production server.

That’s it.  No development environment.  No testing.  No safety net.  Their developer would make changes to local copies of files, visually scan the code to see if there was anything wrong with it, and push it to the production server.  They weren’t even running a copy of it on their local machine.  Someone else would refresh the page and look for errors.  If one popped up, a change was made and pushed immediately.  Part of the issue was the attitude of the company against development processes.  I described it as “reactive” development instead of “responsive” development.  The primary developer was so used to being able to be quick and agile in their ColdFusion development that applying any safety nets or process to his workflow was seen as a hindrance.  The company saw process as unnecessary overhead that slowed things down.

It made me want to scream into a bag.  And I vowed that one day, I was going to set up an environment to make development of this manner easier.  I would employ some basic processes in order to build in conservative development techniques without adding a lot of overhead.  There is a ton of ColdFusion work out there that doesn’t need a full development team with over-architected solutions and processes just to get things done.  However, even a solo developer can benefit from having a minimal amount of process in place to prevent coding disasters.

My obligatory preamble.  I’m not a Docker expert.  I did some research, and I took a couple of online courses, and I figured it out.  There may be better or different ways to accomplish what I’ve accomplished.

My Goal

With all of this in mind, and a focus on solo / small team development, here’s my goal:

  • I want to use a git repository for the code and store that code in the cloud.
  • I want to spin up a development environment quickly and easily on any computer with Docker installed.
  • It should create two containers: one for Adobe ColdFusion, and one for MS SQL Server.
  • The SQL Server should include a copy (even if it’s a subset) of the database used by the application.
  • The ColdFusion container should automatically apply server settings on startup, including datasources, caching, mail settings, etc.
  • The entire system should automatically push to a development beta website once the changes are merged into a branch called Development, and automatically push to production when Development is merged into Master.

This gives me a lot of flexibility… especially if the database is small enough for me to keep a copy in the repository.  When another developer comes on, he needs to pull the repository, spin up the environment and go.  Here’s how development in this environment should proceed, in my view:

  • Developer creates a branch of Development.
  • Coding and testing happens on their local computer.
  • Once satisfied, those changes get merged to development, which automatically get pushed to the beta site.
  • Other QA and UAT users test to make sure there’s no errors, and that the system works as expected.
  • Development gets merged to master, which gets automatically deployed.

This workflow is intended to be basic and minimum in order to satisfy the need to have a little bit of a safety net between the developer and the production server.  Away we go!

Software and Services

I’m going to use the official ColdFusion Docker images for my Docker containers.  I’m also going to use BitBucket for my git repository.

First things first, I need to make sure that I have the correct software in place to complete my tasks.  I use git and docker in this project, and I develop on a Mac, so these instructions will be Mac heavy.  The first thing I do is open up a terminal window (Applications > Utilities > Terminal on a Mac) and type “git” and press enter to make sure git is installed.  If it’s not, the OS will automatically prompt you to install it.

Once git is installed, I create a directory for my project.  In this case, I’ll call it “Project” and I’ll navigate into it from my terminal window, and initialize the git project using the following terminal commands:

mkdir Project
cd Project
git init

I see “Initialized empty Git repository in /Users/dbyers/Project/.git/” and I know that I’m good to go.

Next step is to install Docker.  I won’t go into details on how to install Docker here because there’s a ton of tutorials that cover it already.  Google it.  You’ll figure it out.

Once I’ve got git and Docker installed, I can start setting up my file structure.

My File Structure

Setting up my file structure is pretty simple.

Step 1 – Create Directories

The first thing I do is create two directories:

  • app
  • data

The app directory will contain all of the files that make up the website.  Consider it the root of the site itself.  The data directory contains all of the files I need to establish the database and ColdFusion settings.  The naming of these directories is important because the ColdFusion Docker container looks for the app directory to contain the website and the data directory to contain a ColdFusion archive of settings.  I’ll cover more of that in part 2 of this tutorial.

Step 2 – Create Files

Once the directories are created, I create three empty files; one in the root of the project folder, and two in the data directory.

  • /docker-compose.yml – This is the docker compose file that spin up the environment and define its services.
  • /data/entrypoint.sh – This will be a shell file that’ll be run after the SQL Server is spun up.  Its function is to check to see if the SQL Server is running before it tried to apply the database and controls whether or not the database has already been applied.
  • /data/setup.sql – This is standard SQL file that contains the instructions needed to restore or establish the database.

Step 3 – Populate the Files

I start with the docker-compose.yml file.  This file will be what spins up and runs the entire environment.  I open the docker-compose.yml file and I paste in the following:

version: "3.7"
services:
  sql:
    image: mcr.microsoft.com/mssql/server:2019-latest
    container_name: sql
    hostname: sql
    networks:
      - network
    ports:
      - "1433:1433"
    volumes:
      - "mssqldata:/var/opt/mssql"
      - "./data:/data"
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=SQLS3rv3r
      - MSSQL_AGENT_ENABLED=true
      - MSSQL_PID=Express
    entrypoint:
      - /bin/bash
      - /data/entrypoint.sh
    command: [ "/opt/mssql/bin/sqlservr" ]
  coldfusion:
    image: eaps-docker-coldfusion.bintray.io/cf/coldfusion:latest
    container_name: coldfusion
    hostname: coldfusion
    networks:
      - network
    ports:
      - "80:8500"
    volumes:
      - "./app:/app"
      - "./data:/data"
    environment:
      acceptEULA: "YES"
      password: "C0ldFusi0n"
      enableSecureProfile: "false"
    healthcheck:
      test: curl -f http://localhost/
      interval: 1m
      timeout: 3s
    depends_on:
      - sql
volumes:
  mssqldata:
networks:
  network:

This establishes two containers; one for MS SQL Server running the latest version of SQL Server 2019, and binds it to port 1433 on your computer.  Next, it uses the official Adobe ColdFusion Docker Images to spin up a CF2018 container running the internal web server and binding it to port 80.  Both containers map the data directory from my project into /data on the container.  Finally, the ColdFusion container is set to depend on the SQL container.

Next, I open the entrypoint.sh file and paste the following, which I admittedly ripped off from somewhere on the web… and I can’t remember where.

#!/bin/bash
set -e
if [ "$1" = '/opt/mssql/bin/sqlservr' ]; then
  # If this is the container's first run, initialize the application database
  if [ ! -f /tmp/app-initialized ]; then
    # Initialize the application database asynchronously in a background process. This allows the SQL Server process to be the main process in the container, which allows graceful shutdown and other goodies, and allows us to only start the SQL Server process once, as opposed to starting, stopping, then starting it again.
    function initialize_app_database() {
    # Wait a bit for SQL Server to start. SQL Server's process doesn't provide a clever way to check if it's up or not, and it needs to be up before we can import the application database
    sleep 15s
    #run the setup script to create the DB and the schema in the DB
    /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P SQLS3rv3r -d master -i /data/setup.sql
    # Note that the container has been initialized so future starts won't wipe changes to the data
    touch /tmp/app-initialized
  }
  initialize_app_database &
  fi
fi
exec "$@"

This file runs after the SQL Server container spins up and waits for SQL Server to be installed and ready to respond before instructing it to run the /data/setup.sql file.   It’s whole purpose in life is to watch for the SQL Server to be ready before trying to create the database.

Finally, my setup.sql file.  For the moment, it doesn’t do anything other than create the database.

USE [master]
GO
CREATE DATABASE [Project]
GO

Starting it Up

Once these steps have been followed, my project is ready to be spun up!  Making sure that Docker is running, I navigate to the Project directory in my terminal window and type:

docker-compose up

…and press enter.  That’s when this madness happens.  (Please note, this video is already super boring, so I sped it up quite a bit… the actual download and initialization took about 3 and a half minutes.)

Magical, right?  Let’s check and see if everything is okay.  Open a browser and go to http://127.0.0.1, and I see the following:

There’s one criteria off the list… now for the second.  Do we have a database?  I load up Azure Data Studio and check.  This is what I see:

So we’re good!  The first step in creating a development environment using ColdFusion, MS SQL Server, and Docker Compose is done!  In Part 2, we will establish database connections and some changes to the ColdFusion Server settings.  We will create the database tables and make them persist through Docker builds.

Enjoy!

6 Comments
2020-05-19 21:26:12
2020-05-19 21:26:12

Great timing as I’m trying to stand up ACF Docker containers myself as I can’t get the Add-on services working with Commandbox Docker.

One question – when I start the vanilla ACF Docker image (I’m using 2016) it starts the migration wizard?   Why?  It’s a container.  I can’t figure out how to bypass that.

Like
2020-05-18 02:53:37
2020-05-18 02:53:37

David has posted his part 2. Great to see the things you’re sharing here, David.

Like
(1)
>
Charlie Arehart
's comment
2020-05-18 03:48:12
2020-05-18 03:48:12
>
Charlie Arehart
's comment

Thanks, Charlie!

Like
2020-05-02 09:27:39
2020-05-02 09:27:39

Great!!! Waiting the next part

Like
2020-03-05 02:25:41
2020-03-05 02:25:41

Outstanding post.

Like
(1)
>
Grae Desmond
's comment
2020-03-13 14:59:42
2020-03-13 14:59:42
>
Grae Desmond
's comment

Thanks!  It’s been a fun project.

Like
Add Comment