This walkthrough will cover every step needed to get your docker image built and deployed through FlexDeploy. In this example we will be deploying the image to a Kubernetes Cluster on Oracle Cloud Infrastructure via Helm.

If you don’t have your own docker application you can follow along using the Natours repository used in this example.

Contents

Prerequisites

Building and Pushing the Image

The first goal is to build our image. In the case of the Natours repository, we don’t need any additional compile steps. All we need to do is run docker build with the appropriate commands

Creating the Build Workflow

The build workflow is only going to need two steps: clone the source code and build the image. The buildProjectImage step is going to use the configuration directly in the project. As such, the default configuration is is fine for both steps, simply drag and drop.

<?xml version="1.0" encoding="UTF-8"?>
<ns0:WorkFlow xmlns:ns1="http://flexagon.com/flexdeploy/workflow/common" xmlns:ns0="http://flexagon.com/flexdeploy/workflow">
   <ns1:Name>BuildProjectImage</ns1:Name>
   <ns1:Description></ns1:Description>
   <ns0:Steps>
      <ns0:Step>
         <ns1:Name>cloneProjectSources</ns1:Name>
         <ns1:StepId>1</ns1:StepId>
         <ns0:InvokePlugin>
            <ns0:PluginName>FlexagonGITPlugin</ns0:PluginName>
            <ns0:PluginOperation>cloneProjectSources</ns0:PluginOperation>
            <ns0:consumesArtifacts>false</ns0:consumesArtifacts>
            <ns0:producesArtifacts>false</ns0:producesArtifacts>
            <ns0:EndpointSelection>
               <ns0:EndpointSelectionChoice>All</ns0:EndpointSelectionChoice>
            </ns0:EndpointSelection>
            <ns0:PluginInputs/>
            <ns0:UserInputs/>
            <ns0:PluginOutputs/>
            <ns0:UserOutputs/>
         </ns0:InvokePlugin>
      </ns0:Step>
      <ns0:Step>
         <ns1:Name>buildProjectImage</ns1:Name>
         <ns1:StepId>2</ns1:StepId>
         <ns0:InvokePlugin>
            <ns0:PluginName>FlexagonDockerPlugin</ns0:PluginName>
            <ns0:PluginOperation>buildProjectImage</ns0:PluginOperation>
            <ns0:consumesArtifacts>false</ns0:consumesArtifacts>
            <ns0:producesArtifacts>false</ns0:producesArtifacts>
            <ns0:EndpointSelection>
               <ns0:EndpointSelectionChoice>All</ns0:EndpointSelectionChoice>
            </ns0:EndpointSelection>
            <ns0:EndpointExecutionChoice>Any</ns0:EndpointExecutionChoice>
            <ns0:PluginInputs>
               <ns0:PluginInput>
                  <ns0:Name>FDDKR_INP_DOCKER_FILE</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDDKR_INP_IMAGE_NAME</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDDKR_INP_PUSH_IMAGE</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>Boolean</ns1:Type>
                  <ns0:Text>false</ns0:Text>
               </ns0:PluginInput>
            </ns0:PluginInputs>
            <ns0:UserInputs/>
            <ns0:PluginOutputs>
               <ns0:OutputValue>
                  <ns0:NameInCallee>FDDKR_OUT_IMAGE_ID</ns0:NameInCallee>
               </ns0:OutputValue>
            </ns0:PluginOutputs>
            <ns0:UserOutputs/>
         </ns0:InvokePlugin>
      </ns0:Step>
   </ns0:Steps>
</ns0:WorkFlow>

Creating a Registry Account

If we are going to be pushing our image anywhere, we will need a Registry Account in FlexDeploy. Navigate to Topology->Integrations->Containers and click the Plus button.

Be sure to select the Provider as DockerRegistry and populate the information as necessary. In the above account it is configured to push to the joelwenzel account on dockerhub.com

Creating Additional Build Topology

While still on the Topology screen, we can create the remaining items for the build process.

note

Done Offscreen

  • Create an endpoint where Docker is installed

    • If docker is installed on the FlexDeploy server, the localhost endpoint can be used.

  • Create a Docker instance

    • Add the Build Environment to the Instance

Done Offscreen

  • Create an endpoint where Docker is installed

    • If docker is installed on the FlexDeploy server, the localhost endpoint can be used.

  • Create a Docker instance

    • Add the Build Environment to the Instance

Ensure that the Docker Instance has the workflow created above added. This is how FlexDeploy knows what properties to show on certain screens.

Docker on Windows or Docker-Desktop

If you are using docker on windows, you will need to perform these additional steps.

note

Done Offscreen

  • Add the Docker Endpoint to your Docker-Build EnvInst in Topology Overview

  • Create the SCM Instance for the Git repository

Done Offscreen

  • Add the Docker Endpoint to your Docker-Build EnvInst in Topology Overview

  • Create the SCM Instance for the Git repository

Setting up the Project

Lastly, create a new Project in FlexDeploy. Give it a name that closely resembles your Git repository name and select Container as the Classification.

note

Done Offscreen

  • Update the Project Configuration tab to include the Build Workflow, Build Instance and SCM Configuration.

Done Offscreen

  • Update the Project Configuration tab to include the Build Workflow, Build Instance and SCM Configuration.

After creating the Project, click on the Container Configuration tab. It is here where we specify the image tag information and build behavior.

Add the following configuration:

Naturally your image name and account could be different compared to what’s shown above. With this configuration, FlexDeploy will build an image with an incrementing Project Version every time we run a build. In addition to tagging the image with the ProjectVersion it will tag with latest and push the image to the Docker Hub registry that was set up earlier.

We will come back to image scanning, but for now lets finally build the image.

Run a build

Click the Build button on the Project Activity screen and if everything goes well we should have a new version of the natours image.

Notice that both version 1.0.1 and the latest tag were both pushed to the registry.

Deploying the Containerized App

A reminder that before deployment, you should have kubectl and helm installed on the local FlexDeploy server and have a valid context configured. Similar to the build process, we will first configure the project.

Creating the Deploy Workflow

The only step our deploy workflow needs to do is run Helm, which we will do through the deploy operation on the FlexDeployHelmPlugin. The only input specified is the K8s Context which should be the kubectl context as it shows when running

kubectl config current-context
<?xml version="1.0" encoding="UTF-8"?>
<ns0:WorkFlow xmlns:ns1="http://flexagon.com/flexdeploy/workflow/common" xmlns:ns0="http://flexagon.com/flexdeploy/workflow">
   <ns1:Name>DeployHelm</ns1:Name>
   <ns1:Description></ns1:Description>
   <ns0:Steps>
      <ns0:Step>
         <ns1:Name>deploy</ns1:Name>
         <ns1:StepId>1</ns1:StepId>
         <ns0:InvokePlugin>
            <ns0:PluginName>FlexagonHelmPlugin</ns0:PluginName>
            <ns0:PluginOperation>deploy</ns0:PluginOperation>
            <ns0:consumesArtifacts>true</ns0:consumesArtifacts>
            <ns0:producesArtifacts>false</ns0:producesArtifacts>
            <ns0:EndpointSelection>
               <ns0:EndpointSelectionChoice>All</ns0:EndpointSelectionChoice>
            </ns0:EndpointSelection>
            <ns0:EndpointExecutionChoice>Any</ns0:EndpointExecutionChoice>
            <ns0:PluginInputs>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_CHART_NAME</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_K8S_CONTEXT</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
                  <ns0:Text>oci-demo-cluster</ns0:Text>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_RELEASE_NAME</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_VALUES_FILE</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_REPO_NAME</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_CONFIG_FILE</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_BUILD_DEPENDENCIES</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>Boolean</ns1:Type>
                  <ns0:Text>false</ns0:Text>
               </ns0:PluginInput>
               <ns0:PluginInput>
                  <ns0:Name>FDHLM_INP_OPTIONS</ns0:Name>
                  <ns0:ValueType>Text</ns0:ValueType>
                  <ns0:Encrypted>false</ns0:Encrypted>
                  <ns1:Type>String</ns1:Type>
               </ns0:PluginInput>
            </ns0:PluginInputs>
            <ns0:UserInputs/>
            <ns0:PluginOutputs/>
            <ns0:UserOutputs/>
         </ns0:InvokePlugin>
      </ns0:Step>
   </ns0:Steps>
</ns0:WorkFlow>

Creating the Deploy Topology

More of the same as what we did on the Build side of things.

note

Done Offscreen

  • Create a Helm Instance

  • Associate the DeployHelm workflow

  • Set the Localhost endpoint on the Development Environment for the Helm Instance.

Done Offscreen

  • Create a Helm Instance

  • Associate the DeployHelm workflow

  • Set the Localhost endpoint on the Development Environment for the Helm Instance.

Finalizing the Project

note

Done Offscreen

  • Associate the Deploy Workflow and Deploy Instance on the Project Configuration tab.

Done Offscreen

  • Associate the Deploy Workflow and Deploy Instance on the Project Configuration tab.

Almost there, the final piece of the puzzle is to update the Helm configuration on the project.