Custom Image

Overview

This section shows how to create your own custom WorkflowGen image in order to customize WorkflowGen's files and DLLs.

Prerequisites

  • Windows 10 Pro with Docker Desktop for Windows installed and Windows Containers enabled OR

  • Windows Server 2019 with Docker Enterprise installed

Description

WorkflowGen's image provides a useful variant named advantys/workflowgen:7.18.3-win-ltsc2019-onbuild that can be used to easily customize any file contained in C:\inetpub\wwwroot or C:\Program Files\Advantys\WorkflowGen. All you need to do is create your own image with a Dockerfile that inherits from the onbuild variant and put the customized files in the Docker build context.

Simple example

Here's a simple example that replaces the web.config file, customizes the banner, and adds a custom library.

The .\inetpub\wwwroot and .\Program Files\Advantys\WorkflowGen paths must exist in order for the build to succeed. They don't have to have files in them, so they can be empty.

Step 1: Add your modified files at the root of the context

Here's the file tree of the context directory from which you'll build your custom WorkflowGen image:

context-dir\
inetpub\
wwwroot\
web.config
wfgen\
web.config
bin\
MyCustomLib.dll
ws\
bin\
MyCustomLib.dll
App_Themes\
Default\
portal\
banner\
banner.htm
Program Files\
Advantys\
WorkflowGen\
Services\
Bin\
MyCustomLib.dll

Step 2: Add a Dockerfile to the context directory

File tree:

context-dir\
Dockerfile
inetpub\
wwwroot\
web.config
wfgen\
web.config
bin\
MyCustomLib.dll
ws\
bin\
MyCustomLib.dll
App_Themes\
Default\
portal\
banner\
banner.htm
Program Files\
Advantys\
WorkflowGen\
Services\
Bin\
MyCustomLib.dll

Here's the content of the Dockerfile:

#escape=`
FROM advantys/workflowgen:7.18.3-win-ltsc2019-onbuild
# You can add any instructions in order to install other services or tools, etc.
# You also can add other files at any other location in the container.

Step 3: Build your custom WorkflowGen image

Set-Location C:\Path\To\context-dir
docker image build -t mycorporation/workflowgen:7.18.3-win-ltsc2019 .
# Optionally, you can push your custom image to your container registry
docker image push mycorporation/workflowgen:7.18.3-win-ltsc2019

Build with Docker Compose

With Docker Compose, you can specify the build parameters in a declarative format in order to integrate the Docker build process with the run. For example, you could have the following Compose file named docker-compose.yml in your context directory:

version: '3.7'
services:
workflowgen:
build:
context: .
dockerfile: .\Dockerfile
image: mycorporation/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
wfgdata:
licenses:
external: true
sqldata:

(This file is from the Getting started section.)

The important section is the build object in the workflowgen service object.

Then, to build and tag automatically, you could run the following command:

docker-compose build workflowgen

Docker Compose will then build and tag your image with the tag present in the image property. If you want to immediately update your Compose deployment on your local machine or immediately execute this deployment after the build, execute the following command, which will build your container in addition to running the services after the build:

docker-compose up --build

To push the image using Docker Compose, execute the following command:

docker-compose push workflowgen

You now have a customized WorkflowGen image. For more information on updating your container when a new WorkflowGen version is available, see the Update Management section.

Example with legacy custom WorkflowGen web application/procedure

Let's say in addition to DLLs and custom banners you have an ASP.NET 2.0 web application to add to the wfapps folder and configure in IIS. You would perform the same steps as before, but also add a custom Docker CMD script that will configure the application in IIS.

Multiple PowerShell scripts come with the WorkflowGen image and have different purposes:

  • docker-entrypoint.ps1: This is the main script that gets executed when you run a container. It handles the parsing of environment variables, configuration of authentication methods, etc.

  • monitor-services.ps1: This script handles the monitoring of processes (IIS and Windows services), as well as gathering the logs of the container and redirecting them to the standard output.

  • healthcheck.ps1: This handles the periodic check that indicates if WorkflowGen is working properly or not. This is defined in the WorkflowGen Dockerfile and is handled by the Docker engine.

  • *.psm1: Various developed PowerShell modules available in the image.

  • ServiceMonitor.exe: Binary executable provided by Microsoft. This is the main executable used by the monitoring script to check the state of a service. (You can find more information about ServiceMonitor on its GitHub page at microsoft/IIS.ServiceMonitor).

  • set-state.ps1: Sets the state of the container, such as bringing the website offline or online.

By creating your own WorkflowGen image in Docker, you can replace any script with your own that does something else completely, and it's a best practice to do so if the stock scripts don't do what you want. In the case of this example, the stock scripts don't take care of setting the added web application as in IIS; you need to develop your own script for this. Here's the one that you'll use in this example:

<#
.SYNOPSIS
Add the custom web application to IIS.
.NOTES
File name: custom-web-app-install.ps1
#>
#requires -Version 5.1
Import-Module IISAdministration
Import-Module C:\Const.psm1 -Variable Constants
Import-Module C:\Utils.psm1 -Fonction "Get-EnvVar"
$wfgenStartService = (Get-EnvVar "WFGEN_START_SERVICE" -DefaultValue "all").ToLower()
$isWebServices = $wfgenStartService -eq $Constants.SERVICE_ALL -or
$wfgenStartService -eq $Constants.SERVICE_WEB_APPS
if ($isWebServices -and (Get-WebApplication -Site "wfgenroot" -Name "wfgen/wfapps/<YOUR_WEB_SERVICE_NAME>").Count -le 0) {
Write-Host "CONFIG: Adding mywebapp to IIS ... " -NoNewLine
ConvertTo-WebApplication -PSPath "IIS:\Sites\wfgenroot\wfgen\WfApps\<YOUR_WEB_SERVICE_NAME>" | Out-Null
Write-Host "done" -ForegroundColor Green
}
if ($args.Count -gt 0) {
Invoke-Expression ($args -join " ")
} else {
. C:\monitor-services.ps1
}

Replace <YOUR_WEB_SERVICE_NAME> with the name of your web service that you added in the wfapps folder.

In this script, note the following:

  1. You're checking for the start service type and checking if you've already added the web service as a web application in IIS.

    Rationale This is because the entrypoint script is re-run between restarts of the container. Therefore, this script will also be re-run after a restart. When restarting a container, the IIS configuration stays and the ConvertTo-WebApplication command will cause the start procedure to fail when trying to add an already-added web application. Consequently, you have to check that you haven't already added the application.

    Also, you're checking if the container is running in web applications mode. When it isn't, you don't need to add your web service in IIS because there will be only Windows services that will run.

  2. You're checking for arguments and executing them if there are some. If not, you start to monitor the container's services.

    Rationale

    This is a general good practice in a Docker container. For example, if you're debugging the container and only want to prompt a PowerShell command line after the start sequence, you would pass powershell as an argument to the run command like so:

    docker container run -it `
    # ...
    mycorporation/workflowgen:7.18.3-win-ltsc2019 C:\custom-web-app-install.ps1 powershell

    The powershell argument will be executed by the Invoke-Expression command and a new PowerShell command prompt will be displayed. If no arguments are passed, the default behavior is to start monitoring the services. Since the image already has a script for that, you only need to execute it.

Your Dockerfile will then be as follows:

#escape=`
FROM advantys/workflowgen:7.18.3-win-ltsc2019-onbuild
SHELL ["powershell", "-Command"]
COPY .\custom-web-app-install.ps1 C:\
CMD C:\custom-web-app-install.ps1

After that, you'll perform the same build and push steps as the previous example.