Docker Compose

This walkthrough will show you two methods of using CloudTruth to pass environment variables to a Docker container with Docker Compose. The first method uses an environment file and the second method uses the CloudTruth run command.

Prerequisites

Method 1: Docker Compose Environment File

You can also use CloudTruth Parameters with Docker Compose by using env_file and creating an Environment file with CloudTruth CLI cloudtruth parameter export docker.

Inside your Docker folder create an environment file with the CloudTruth CLI.

 cloudtruth --project MyFirstProject parameter export docker > dotenv

Create a Dockerfile with the following contents.

FROM alpine
CMD ["printenv"]

With the Dockerfile that you created above, create a new container image called cloudtruth

docker build -t cloudtruth .

Create a docker-compose.yml and copy the following snippet. The env_file specified will import all environment variables to use with Docker compose.

services:
  app:
    build: .
    image: cloudtruth
    container_name: ct-test
    env_file:
      - dotenv

Issuing the following command will build the Docker container and issue the printenv command which will display all of the parameters passed in the dotenv file that are now sourced and available to use within your Docker environment.

docker-compose up

You'll see an output to the terminal with your parameters, similar to the output below.

Creating ct-test ... done
Attaching to ct-test
ct-test | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ct-test | HOSTNAME=16569452923f
ct-test | FLASK_APP=flaskdemo.py
ct-test | FLASK_DEBUG=True
ct-test | FLASK_ENV=development
ct-test | FLASK_MESSAGE=Configuration Management for Default
ct-test | FLASK_RUN_HOST=0.0.0.0
ct-test | FLASK_RUN_PORT=3000
ct-test | HOME=/root
ct-test exited with code 0

Passing variables using the --env-flag file

Alternatively, the created dotenv file can be passed to Docker-Compose with the --env-file flag. This allows you to set specific variables for your app in docker-compose.yml.

services:
  app:
    build: .
    image: cloudtruth
    container_name: ct-test
    environment: 
      - FLASK_ENV    

Now you pass the --env-file where only the specified variables are displayed.

docker-compose --env-file dotenv up
Starting ct-test ... done
Attaching to ct-test
ct-test | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ct-test | HOSTNAME=ac37b482be46
ct-test | FLASK_ENV=development
ct-test | HOME=/root
ct-test exited with code 0 

Method 2: Docker Compose with CloudTruth Run

This method will use the cloudtruth CLI to add CloudTruth parameters to the environment docker-compose runs in, allowing you to inject the values into the services controlled by docker-compose.

Create a Dockerfile with the following contents.

FROM alpine
CMD ["printenv"]

The docker-compose.yml allows you to set specific variables for your app. For example, you can create variables/parameters for a Flask app, which are created in CloudTruth.

services:
  app:
    build: .
    image: cloudtruth
    container_name: ct-test
    environment: 
      - FLASK_ENV
      - FLASK_APP
      - FLASK_RUN_PORT 

Now execute docker-compose up with the cloudtruth run command which will pass your CloudTruth parameters to Docker compose and display the variables selected.

cloudtruth --project MyFirstProject run -- docker-compose up 
Starting ct-test ... done
Attaching to ct-test
ct-test | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ct-test | HOSTNAME=4ac024aae550
ct-test | FLASK_ENV=development
ct-test | FLASK_APP=flaskdemo.py
ct-test | FLASK_RUN_PORT=3000
ct-test | HOME=/root
ct-test exited with code 0

Method 3: Docker Compose with init container

This method will use the CloudTruth init (sidecar) container to render templates into a volume(s) shared with the target services in your docker-compose file.

Source code for the CloudTruth init container: https://github.com/cloudtruth/templates

This example injects a simple static HTML page into an nginx container. The static HTML page is stored as a template in CloudTruth.

Add a target to the template

The init container will scan the specified project and environment for all templates with a special comment on the first line that specifies the file to render the template to. It must be on the first line and it looks like this:

#~ target: /usr/share/nginx/html/index.html

For this example, CloudTruth created a template named `DEMO_PAGE` in project "MyFirstProject", but feel free to change the project name based on your use case. The template references the automatic parameter "cloudtruth.environment", which will insert the name of the environment the template was pulled from.

You'll notice that the template has the special comment as the first line: `#~ target: ...`. The init container will find this template and render it to "/usr/share/nginx/html/index.html".

Here is the template:

#~ target: /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
    <title>{{ cloudtruth.environment }}</title>
</head>
<body>
<p>This is the {{ cloudtruth.environment }} web page.</p>
</body>
</html>

Create docker-compose file

This example uses the public nginx container image, but you can replace this with your own container image.

Create a docker-compose.yml file or use one you already have. There are three important pieces to note, that make this whole solution work:

  1. Include the cloudtruth/templates image as a service in the docker-compose file. You will see that listed as the web_init service in the example file below.

  2. One or more named volumes shared between the target container (web) and the init container (web_init). In this case, we use the "static-content" named volume. Be sure to mount the named volumes to the same location in both the init container and the target container.

  3. Add the `depends_on` stanza to the container you want to inject the template into. The target container (web) should depend on the CloudTruth init container (web_init)

The full docker-compose.yml file for this example:

---
services:
  web_init:
    container_name: ctdemo-init
    environment:
      - CLOUDTRUTH_API_KEY=${CLOUDTRUTH_API_KEY}
      - CLOUDTRUTH_ENVIRONMENT=${CLOUDTRUTH_ENVIRONMENT:-production}
      - CLOUDTRUTH_PROJECT=${CLOUDTRUTH_PROJECT:-default}
    image: cloudtruth/templates
    volumes:
      - static-content:/usr/share/nginx/html
  web:
    container_name: ctdemo
    depends_on:
      web_init:
        condition: service_completed_successfully
    image: nginx:1.20-alpine
    ports:
      - "8585:80"
    volumes:
      - static-content:/usr/share/nginx/html

volumes:
  static-content:

Run docker-compose up

You will need to set a few environment variables for this exercise:

  • `CLOUDTRUTH_API_KEY` = your APi-Key

  • `CLOUDTRUTH_PROJECT` = the project you want to render templates from

  • `CLOUDTRUTH_ENVIRONMENT` = the environment you want to use values from to render into the template

Now run docker-compose:

docker-compose up

Verify the results

After a few seconds, the nginx container should be running with the web page hosted at http://localhost:8585

In this case, I ran with `CLOUDTRUTH_ENVIRONMENT=production` and can see that reflected in the web page:

Last updated

Copyright© 2023 CloudTruth