Example Dockerfile for a Liberty Network Deployment image

Use the Dockerfile example to create a Liberty Network Deployment image. The Docker image has a joinMember script that joins the member server in the Docker container to a collective controller. The Docker image also has a removeMember script that removes the member server in the Docker container from the collective.

Stabilized feature: Managing Docker containers using Liberty collectives is stabilized. For managing Docker containers, run our Liberty applications in IBM Cloud Pak for Applications for on-premises or bring-your-own infrastructure. For hosted environments, use Docker containers in IBM Cloud Kubernetes Service.


Dockerfile

The following Dockerfile example can create a Liberty Network Deployment image. The image that is available on Docker hub cannot access Liberty Network Deployment features such as scalingMember-1.0. Use this file to create a Liberty Network Deployment image. We can use the last line to copy an application for use onto the Docker image.

    # 
    # Dockerfile to create a Liberty Network Deployment image
    #
    # This Dockerfile assumes:
    # - The collective enabling scripts (joinMember, removeMember) will be placed in
    #   /opt/ibm/docker in the Docker container
    # - WebSphere Liberty will be installed at /opt/ibm/wlp
    # - The WebSphere Liberty server will be "defaultServer"
    #   (for example, /opt/ibm/wlp/usr/servers/defaultServer)
    # - The Docker container runs using --net=host so that no ports are explicitly
    #   exported in this file
    
    FROM websphere-liberty
    
    #
    # Auto-start the Liberty server with the container
    #
    ENTRYPOINT ["/opt/ibm/wlp/bin/server", "run", "defaultServer"]
    #
    #
    
    #
    # Add collective enabling scripts
    #
    ADD joinMember /opt/ibm/docker/
    RUN chmod +x /opt/ibm/docker/joinMember
    ADD removeMember /opt/ibm/docker/
    RUN chmod +x /opt/ibm/docker/removeMember
    
    #
    # Update the operating system 
    #
    RUN apt-get update
    
    #
    # Add the additional required features
    #
    RUN installUtility install --acceptLicense scalingMember-1.0 clusterMember-1.0 collectiveMember-1.0
    
    ADD server.xml /opt/ibm/wlp/usr/servers/defaultServer/
    
    #
    # Insert the application file name. This statement copies the application
    # onto the Docker image.
    # 
    ADD application_file /opt/ibm/wlp/usr/servers/defaultServer/dropins/


joinMember script

The Docker image joinMember script joins the member server in the Docker container to a collective controller:

    #!/bin/bash
    
    #
    # Script to join a Liberty Docker container to a collective controller.
    #
    # Required: <containerName> - positional parameter that is the name 
    #  of this Docker container
    #   --host - collective controller hostname
    #   --port - collective controller https port
    #   --user - collective controller admin user
    #   --password - collective controller admin user password
    #   --keystorePassword - to be used for the member keystore
    #   --dockerHost - hostname of the Docker host this container resides on
    #
    # Optional: --clusterName - cluster name for the member configuration.  
    #        If specified, it adds the cluster and scaling 
    #        member features also.
    #
    
    # Set initial values
    
    containerName=$1
    
    # Parse the command line
    
    failure="false"
    
    if [[ -z $1 ]]; then
        # No values received
        echo "Error: no parameters specified"
        failure="true"
    else
        TEMP=`getopt --long host:,port:,user:,password:,keystorePassword:,dockerHost:,clusterName:: -- "$@"`
        eval set -- "$TEMP"
        OPTIND=-1
        
        while true ; do
            case "$1" in
       --host) controllerHost=$2; shift 2;;
       --port) controllerPort=$2; shift 2;;
       --user) controllerUser=$2; shift 2;;
       --password) controllerPassword=$2; shift 2;;
       --keystorePassword) memberKeystorePassword=$2; shift 2;;
       --dockerHost) dockerHost=$2; shift 2;;
       --clusterName) clusterName=$2; shift 2;;
       *) break;;
            esac
        done
    
        # Validate the required parameters
        if [[ -z "$containerName" ]]; then
            echo "Error: no containerName specified, validation suspended"
            failure="true"
        fi
    
        # if a containerName is not specified, bash uses the 
        # 1st "--" parameter as the containerName
    
        if [[ $containerName == --* ]]; then
            echo "Error: no containerName specified, validation suspended"
            failure="true"
        fi
        
        # When the positional parameter containerName fails, 
        # suspend validation reporting
        
        if [[ $failure == false ]]; then
            if [[ -z "${controllerHost// }" ]]; then
        echo "Error: no host specified"
        failure="true"
            fi
            if [[ -z "${controllerPort// }" ]]; then
        echo "Error: no port specified"
        failure="true"
            fi
            if [[ -z "${controllerUser// }" ]]; then
        echo "Error: no user specified"
        failure="true"
            fi
            if [[ -z "${controllerPassword// }" ]]; then
        echo "Error: no password specified"
        failure="true"
            fi
            if [[ -z "${memberKeystorePassword// }" ]]; then
        echo "Error: no keystorePassword specified"
        failure="true"
            fi
            if [[ -z "${dockerHost// }" ]]; then
        echo "Error: no dockerHost specified"
        failure="true"
            fi
        fi
    fi
    
    if [[ $failure == false ]]; then
        # Create the env.properties file for the Liberty Docker member
    
        echo containerName=$containerName > /opt/ibm/docker/env.properties
        echo containerHost=$dockerHost >> /opt/ibm/docker/env.properties
    
    
        # Invoke the collective utility
    
        /opt/ibm/wlp/bin/collective join defaultServer --host=$controllerHost --port=$controllerPort --user=$controllerUser --password=$controllerPassword --hostName=$dockerHost --createConfigFile --keystorePassword=$memberKeystorePassword --autoAcceptCertificates --genDeployVariables
    
        # Save join return code    
        joinRC=$?
    
        # Build additional config dropin snippets
    
        if [[ $clusterName = *[!\ ]* ]]; then
            echo \<?xml version=\"1.0\" encoding=\"UTF-8\" ?\> > /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo \<server\> >> /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo $'\t'\<featureManager\> >> /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo $'\t'$'\t'\<feature\>clusterMember-1.0\</feature\> >>  /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo $'\t'$'\t'\<feature\>scalingMember-1.0\</feature\> >>  /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo $'\t'\</featureManager\> >> /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo \</server\> >> /opt/ibm/wlp/usr/servers/defaultServer/cfgfeatures.xml
            echo \<?xml version=\"1.0\" encoding=\"UTF-8\" ?\> > /opt/ibm/wlp/usr/servers/defaultServer/cluster-config.xml
            echo \<server\> >> /opt/ibm/wlp/usr/servers/defaultServer/cluster-config.xml
            echo $'\t'\<clusterMember name=\"$clusterName\" /\> >> /opt/ibm/wlp/usr/servers/defaultServer/cluster-config.xml
            echo \</server\> >> /opt/ibm/wlp/usr/servers/defaultServer/cluster-config.xml
        else
            echo "No clusterName provided, the container will not be configured as a cluster or scaling member."
        fi
    
    
        # Move config snippets to the proper location for consumption
    
        mkdir -p /opt/ibm/wlp/usr/servers/defaultServer/configDropins/overrides
        mv /opt/ibm/wlp/usr/servers/defaultServer/c*.xml /opt/ibm/wlp/usr/servers/defaultServer/configDropins/overrides
        if [ -f /opt/ibm/wlp/usr/servers/defaultServer/user-collective-include.xml ]
        then
            cp /opt/ibm/wlp/usr/servers/defaultServer/user-collective-include.xml /opt/ibm/wlp/usr/servers/defaultServer/configDropins/overrides
        fi
    else
        # At least one required parameter was missing, 
        # notify the user of the correct syntax
        printf "Usage:  joinMember <containerName> \n\t--host <controller host> \n\t--port <controller https port> \n\t--user <controller user> \n\t--password <controller password> \n\t--keystorePassword <member keystore password> \n\t--dockerHost <hostname of the Docker host> \n\t[--clusterName <cluster name for the member>]\n"
    fi
    
    exit $joinRC
    


removeMember script

The Docker image removeMember script removes the member server in the Docker container from the collective:

    #!/bin/bash
    
    # Script to remove a Liberty Docker container from a collective controller.
    #
    # Required: <containerName> - positional parameter that is the
    #  name of this Docker container
    #   --host - collective controller hostname
    #   --port - collective controller https port
    #   --user - collective controller admin user
    #   --password - collective controller admin user password
    #   --dockerHost - hostname of the Docker host this container resides on
    #
    #
    
    # Set initial values
    
    containerName=$1
    
    # Parse the command line
    
    failure="false"
    
    if [[ -z $1 ]]; then
        # No values received
        echo "Error: no parameters specified"
        failure="true"
    else
        TEMP=`getopt --long host:,port:,user:,password:,dockerHost:: -- "$@"`
        eval set -- "$TEMP"
        OPTIND=-1
    
        while true ; do
            case "$1" in
       --host) controllerHost=$2; shift 2;;
       --port) controllerPort=$2; shift 2;;
       --user) controllerUser=$2; shift 2;;
       --password) controllerPassword=$2; shift 2;;
       --dockerHost) dockerHost=$2; shift 2;;
       *) break;;
            esac
        done
    
        # Validate the required parameters
        if [[ -z "$containerName" ]]; then
            echo "Error: no containerName specified, validation suspended"
            failure="true"
        fi
    
        # if a containerName is not specified, bash uses the
        # 1st "--" parameter as the containerName
    
        if [[ $containerName == --* ]]; then
            echo "Error: no containerName specified, validation suspended"
            failure="true"
        fi
    
        # When the positional parameter containerName fails, 
        # suspend validation reporting
    
        if [[ $failure == false ]]; then
            if [[ -z "${controllerHost// }" ]]; then
        echo "Error: no host specified"
        failure="true"
            fi
            if [[ -z "${controllerPort// }" ]]; then
        echo "Error: no port specified"
        failure="true"
            fi
            if [[ -z "${controllerUser// }" ]]; then
        echo "Error: no user specified"
        failure="true"
            fi
            if [[ -z "${controllerPassword// }" ]]; then
        echo "Error: no password specified"
        failure="true"
            fi
            if [[ -z "${dockerHost// }" ]]; then
        echo "Error: no dockerHost specified"
        failure="true"
            fi
        fi
    fi
    
        # Invoke the collective utility
    if [[ $failure == false ]]; then
    
        /opt/ibm/wlp/bin/collective remove defaultServer --host=$controllerHost --port=$controllerPort --user=$controllerUser --password=$controllerPassword  --hostName=$dockerHost --autoAcceptCertificates
    
    else
        # At least one required parameter was missing, 
        # notify the user of the correct syntax
        printf "Usage:  removeMember <containerName> \n\t--host=<controller host> \n\t--port=<controller https port> \n\t--user=<controller user> \n\t--password=<controller password> \n\t--dockerHost=<docker host> \n"
    fi