For LINUX platformsFor Windows platforms

Deploying Docker containers using deployment REST APIs

You can deploy Liberty or Node.js servers in Docker containers as members of a collective by using the DeployService REST APIs.

Before you begin

Stabilized feature: Managing Docker containers by using Liberty collectives is stabilized. For managing Docker containers, run your 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.

Determine the target hosts onto which you want to install a Docker image. Install Docker on the target hosts. Each target host needs RXA or SSH. See Setting up RXA for Liberty collective operations.

If you will use Node.js in a Docker container, download a Node.js 4.x version from the Docker Hub registry.

Multimedia Watch: The Managing an On-Premise, Polyglot Environment with WebSphere® Liberty Collectives video.

Procedure

  1. Create a Docker image.
    1. Use a Dockerfile to create a Liberty image.

      You can change the following Dockerfile examples for your environment. Provided with each example are a joinMember script that joins the member server in the Docker container to a collective controller and a removeMember script that removes the member server in the Docker container from the collective.

    2. If you are using a Dockerfile for a Liberty Network Deployment image, configure the server.xml file to use with the Dockerfile; for example:
      <server description="Default Server">
         <featureManager>
            <feature>webProfile-6.0</feature>
         </featureManager>
      
         <httpEndpoint id="defaultHttpEndpoint"
                       httpPort="${memberHttpPort}"
                       httpsPort="${memberHttpsPort}" />
      
      </server>
    3. Ensure that the collective controller server.xml file has statements that define the controller user name and password and deployment variables.
      • Example server.xml for a Liberty Network Deployment image:
           <collectiveController user="admin" password="adminpwd" />
        ... 
           <deployVariable name="memberHttpPort" value="9090" increment="1"/> 
           <deployVariable name="memberHttpsPort" value="9453" increment="1"/>
      • Example server.xml for a Node.js member image:
           <collectiveController user="admin" password="adminpwd" />
        ... 
           <deployVariable name="wlpn.appPort" value="9090" increment="1"/> 
           <deployVariable name="wlpn.adminPort" value="9453" increment="1"/>

      The deployment variables must set values that enable each member to have a unique port number on the target hosts. See DeployVariable (deployVariable).

    4. Run the Docker build command to create the image.
      1. Copy the Dockerfile and the joinMember and removeMember scripts to a computer with Docker installed. If you are using a Docker file for a Liberty Network Deployment image, also copy the server.xml file named in the Dockerfile to the computer. Put the files in the same directory.
      2. Open a command window at the directory that holds the files.
      3. Run the Docker command to create the image:
        docker build -t image_name .
      4. Verify the image creation. The following command returns the image name when creation is successful.
        docker images
    5. Optional: Post the Docker image on a Docker registry with a docker push command. See Docker Registry for more information.
  2. Register the target Docker host with the collective controller.
    Registering a host enables the collective controller to pull the Docker image from the registry to that host, as well as access files, commands, and other resources on the host. Run the registerHost command on the controller machine to register the target host. See the following example:
    wlp/bin/collective registerHost targetHost --host=controllerHost --port=controllerHTTPSPort --user=controllerAdmin --password=controllerAdminPassword --rpcUser=osUser --rpcUserPassword=osUserPassword  --autoAcceptCertificates

    Look at the server.xml file of the controller to find the values for the --host, --port, --user, and --password parameters. To not use an SSH private key file, such as for target hosts on Linux® or Windows operating systems, include an operating system login user and password by setting --rpcUser and --rpcUserPassword parameters. The user specified by --rpcUser must have operating system rights to the target deployment location.

    If a host is already registered, you can use the updateHost command to reset registration information. For more information, see Registering host computers with a Liberty collective.

  3. If the Docker image to deploy is stored in a registry instead of locally available on the Docker host where you will deploy, you can configure the collective controller to access the registry. See Configuring a Docker registry for use by a collective controller.
  4. Review the available deployment rules.
    1. Invoke a REST API that returns the available deployment rules.
      Use a tool that can invoke REST APIs to get the available deployment rules.
      GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/rule

      The invocation returns the deployment rules in JSON structure; for example:

      {"rules":
      [
       {"id":"Liberty Docker Rule","description":"Deploy rule for Liberty Docker containers.","type":"docker","deployCommands":"repository=${dockerRepository};
       registry=${dockerRegistry}; if [ ! $registry ]; then if [ ! $repository];
       then echo 'The dockerRegistry and dockerRepository are not configured in the collective controller, the Docker image to be deployed is assumed available on the target host' ;
       docker run -d -e LICENSE=accept -e CONTAINER_NAME=${containerName} -e CONTAINER_HOST=${wlp.deploy.host} --net=host --name=${containerName} ${imageName} ;
       else echo 'No dockerRegistry configured in the collective controller, Docker image deployments are disabled'; failure='true' ; fi;
       else user=${dockerUser}; password=${dockerUserPassword}; email=${dockerUserEmail};
       if [ ! $repository]; then echo 'No dockerRepository configured in the collective controller, Docker image deployments are disabled'; failure='true' ; fi;
       if [ ! $user]; then echo 'No dockerUser configured in the collective controller, Docker image deployments are disabled'; failure='true' ; fi;
       if [ ! $password]; then echo 'No dockerUserPassword configured in the collective controller, Docker image deployments are disabled'; failure='true'; fi;
       if [ ! $email]; then echo 'No dockerUserEmail configured in the collective controller, Docker image deployments are disabled'; failure='true'; fi;
       if [ ! $failure]; then echo 'Login to the Docker registry at ' $registry ' for repository named ${dockerRepository} as user ' $user ' and pull the image ${imageName} to be started' ;
       docker logout;
       docker login --username=$user --password=$password --email=$email $registry ; docker pull ${dockerRepository}:${imageName} ;
       docker run -d -e LICENSE=accept -e CONTAINER_NAME=${containerName} -e CONTAINER_HOST=${wlp.deploy.host} --net=host --name=${containerName} ${dockerRepository}:${imageName} ; fi; fi;
       if [ ! $failure]; then echo 'Configure the running container ${containerName}' ;
       docker exec -t ${containerName} bash /opt/ibm/docker/joinMember ${containerName} --clusterName=${clusterName}
         --dockerHost=${wlp.deploy.host} --host=${wlp.admin.host} --port=${wlp.admin.port}
         --user=${wlp.admin.user} --password=${wlp.admin.password} --keystorePassword=${keystorePassword};
       else false; fi","undeployCommands":"docker start ${containerName}; 
       docker exec -t ${containerName} bash /opt/ibm/docker/removeMember ${containerName}
         --host=${wlp.admin.host} --port=${wlp.admin.port} --user=${wlp.admin.user} --password=${wlp.admin.password}
         --dockerHost=${wlp.deploy.host} && ( docker stop ${containerName};
       docker rm
        ${containerName} )","startCommands":"docker start
        ${containerName}","stopCommands":"docker stop
        ${containerName}","restartCommands":"","inputVariables":[
         {"name":"keystorePassword","type":"password","description":"Password for keystores of the deployed server","displayName":"Keystore Password"},
         {"name":"clusterName","type":"String","description":"Name of Liberty Docker container cluster.","defaultValue":"${imageName}_cluster","displayName":"Cluster Name"},
         {"name":"containerName","type":"String","description":"Name of Liberty Docker container.","defaultValue":"${imageName}_container","displayName":"Container Name"},
         {"name":"imageName","type":"dockerImage","description":"Name of Liberty Docker image.","displayName":"Image Name"}],
        "name":"Docker Container","default":true,"runtimeTypes":[{"displayName":"Node.js"},{"displayName":"Liberty"}],"packageType":"Docker Container"
       }
      ]}
    2. If necessary, create your own deployment rules by adding DeployRules to your controller configuration. See Deploy Rule (deployRule).
  5. Deploy the Docker image.
    Use a tool that can invoke REST APIs to deploy the Docker image. The deployment rule contains variables that can specify input values for the invocation, such as the Docker image to use and the container name to create. The return body contains a token that you can use to request status and results.
    Note: Use the same Liberty Docker Rule for both Liberty Docker images and Node.js Docker images.
    POST https://controller_host:controller_port/ibm/api/collective/v1/deployment/deploy
    
    {
       "rule": "Liberty Docker Rule", 
       "hosts": [ "myHostName" ],
       "variables": [
          { "name":"imageName", "value":"myImageName" },
          { "name":"containerName", "value":"myContainerName" },
          { "name":"clusterName", "value":"myClusterName" },
          { "name":"keystorePassword", "value":"thePassword" }
       ]
    }
    

    For example, the return token might be {"id":3}, which you can use to get status and results.

What to do next

Request and review the deployment status and results.

  • Get a list of tokens for requested deployment operations.
    GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/deploy
    
  • Get a short status of the deployment operations. Use the token from step 4 for {token}. Thus, for a {"id":3} return token from step 4, use 3 for {token}.
    GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/{token}/status 
    
    During deployment, the API returns IN_PROGRESS:
    {"status":{"target_host":"IN_PROGRESS"}}
    After deployment, the API returns FINISHED:
    {"status":{"target_host":"FINISHED"}}
  • Get the complete results of a deployment operation. Use the token from step 4 for {token}. Thus, for a {"id":3} return token from step 4, use 3 for {token}.
    GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/{token}/results
    After deployment completes, the results contain information about the operation. The following example shows results for FINISHED:
    {"results":[{"host_name":"target_host","status":"FINISHED","result":0}]}
Undeploy a Docker container. You do not need to specify a deploy rule. The rule used for deployment was stored at deploy time. You can use the rule for undeployment. The userDir variable must be Docker.
  • Undeploy a container.
    
    POST https://controller_host:controller_port/ibm/api/collective/v1/deployment/undeploy
    {     
       "host": "myHostName",
       "userDir":"Docker",     
       "serverName":"myContainerName"
    }
  • Get a list of tokens for undeployment operations.
    GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/undeploy
    To get status and results, follow steps similar to deployments.