First Docker Compose File

The roadshow has just started, and you might have learned what Docker is, why you could / should use it, and then maybe a little of how to use it. You can spin up a Docker container pretty easily, with a command or two, but usually, we work with multiple servers. Configuring that might be confusing at first… you might wonder, if i spin up 3 containers, how do they know how to find each other, and other questions like this, are easily solved, with Compose files. That is what we're going to look at today.

If you want to see more of the Ortus Solutions Container / Docker Roadshow, check out our event page here

Wait a minute, i just learned about Docker files, and now I need to worry about Docker Compose files too? Yes, and I'll tell you why.

Each server / container you spin up has a series of information stored in their dockerfile… but your project, how each of those pieces work together is contained in the Docker Compose file.

Lets look at a couple of scenarios, and see how we could setup our Docker Compose file.

1 - Basic CFML Container

We could do this with a simple docker file, but this is just the beginner of our scenario, so we'll start with a docker compose file. Let's look at the file, and then break down how it works

 version: "3"

services:
  # CFML Engine
  cfml:
    image: ortussolutions/commandbox  
    # bind public port to 8080
    ports:
      - "8080:8080"
    volumes:
      - ./www:/app

Note: docker-compose.yml is a Yaml file, and therefore formatting is part of the code. The wrong level of indentation does make a difference.

  • Version 3 - This is the Docker Compose version we are using.
  • Services - this is a structure listing all the services we are managing with this compose files
  • CFML is the first service we are describing
    • Image - this is the docker image we are using as our base image for this service. Ortus's commandbox image is power packed, and is the perfect cfml image.
    • Ports - You need a way to get from your local machine to the docker container, so we're mapping port 8080 on our local to 8080 in the docker container. First port is the local port, second port is in the container. This gets important as you have more services you wish to connect with. Inside the container, Commandbox always runs on 8080… but you can map them to anything you want locally.
    • Volumes - this is where you map code on your machine, into the container. Here, we are mapping the www folder in this folder that contains the docker-compose.yml file into the app folder. As we change the code in the www folder, it updates in the container. Its a smooth workflow.

In this scenario, thats all we need. There are options through CommandBox with CFConfig for creating Lucee and Adobe ColdFusion settings for passwords, datasources etc, but we'll keep it as simple as we can for these examples.

Code? What does the www folder look like? Let's look at the whole directory structure

/
/www/
/www/index.cfm
docker-compose.yaml

Index.cfm has this code in this example

1-basicCFML - #now()#

We spin up this container from the command line with the following command from the root of our project

docker-compose up

When the command has completed, you will see a series of debug statements in the command line, and when you visit http://127.0.0.1:8080/ you will see this output

1-basicCFML - {ts '2017-09-05 01:40:53'}

In the command line, press ctrl-c to kill the docker-compose setup. You can start docker-compose in daemon mode just like a normal docker file startup, with -d. If you start in daemon mode, you can stop / restart with the docker ps commands. More about that in another blog post.

2 - CFML Container with MySQL Server

It is hard to imagine running a CFML Server without need of a database, so the next scenario, we'll show you how to set up a mysql container to go with the cfml container from the last scenario. Here is the new combined docker-compose.yml

version: "3"

services:
  # CFML Engine
  cfml:
    image: ortussolutions/commandbox  
    # bind public port to 8080
    ports:
      - "8080:8080"
    volumes:
      - ./www:/app

  # MySQL Server
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: "myp@ssword"

The first piece is the same, but we have a 2nd service described, mysql.

  • image - the image is the mysql image, distributed by mysql, available from Dockerhub.
  • environment - this is where you can pass in environmental variables to modify the containers behavior to suit your needs.
    • MYSQL_ROOT_PASSWORD - the password for mysql's root account. Important for security purposes not to be the default.

Code? What does the www folder look like? Let's look at the whole directory structure

/
/www/
/www/Application.cfc
/www/index.cfm
docker-compose.yaml

Application.cfc has this code in this example - essentially an empty Application.cfc with a datasource definition using the password set for mysql in the docker-compose.yml file.

component {
    this.datasources["dsmysql"] = {
          class: 'org.gjt.mm.mysql.Driver'
        , connectionString: 'jdbc:mysql://mysql:3306/mysql?useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=true'
        , username: 'root'
        , password: "encrypted:744d34f22944e1ca2e92bbf13f2617f7fc4c7daa255e440e9c52d856af118228"
    };  
}

Index.cfm has this code in this example


select * from user



We spin up this container from the command line with the following command from the root of our project

docker-compose up

When the command has completed, when you visit http://127.0.0.1:8080/ you will see a dump of the user table.

By default, docker-compose.yml automatically does some basic networking, so our example works using the name of the container mysql for the url. You have more networking options available with Docker-compose, but its nice that as simple as this file is, you have 2 containers up and running, communicating, with a few lines of code.

If you want to be able to connect to the mysql server from your local machine, you can add ports like we did with the CFML engine.

ports: 
      - "33306:3306"

Now if you want to connect, you can access on 33306, which routes to the docker containers' 3306 port.

The MySQL image allows for you to select a database, load data on the first load, so you seed your database, and much more.

In the command line, press ctrl-c to kill the docker-compose setup. You can start docker-compose in daemon mode just like a normal docker file startup, with -d. If you start in daemon mode, you can stop / restart with the docker ps commands. More about that in another blog post.

What's next?

Check out an upcoming blog post with the next scenarios, where we'll keep adding to our existing setup. In that blog post we will learn about the following:

  • Put Nginx in front of the CFML Server and MySQL

  • Create a new DB and preload some data into the MySQL server

Clone the repo and try it out

Clone the repo, and pick your flavor, and spin up your own dev environment today.

https://github.com/Ortus-Solutions/firstDockerCompose

There are a lot more options, tune into the roadshow blogs and webinars to learn more.