Deploy Docker containers using deployment REST APIs
Overview
We can deploy Liberty or Node.js servers in Docker containers as members of a collective using the DeployService REST APIs.
- For on-premises or bring-your-own infrastructure, run Liberty applications in IBM Cloud Pak for Applications.
- For hosted environments, use Docker containers in IBM Cloud Kubernetes Service.
Stabilized feature: Managing Docker containers using Liberty collectives is stabilized.
Configure RXA or SSH on each target host that willl have a Docker image.
To use Node.js download from the Docker Hub registry.
Watch: The Manage an On-Premise, Polyglot Environment with WebSphere Liberty Collectives video.
Deploy Docker containers
- Create a Docker image.
- Create a Dockerfile.
We can change the following Dockerfile examples for the 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.
- Example Dockerfile for a Liberty Network Deployment image
- Example Dockerfile for a Node.js member image
- For a Liberty Network Deployment image, configure server.xml to use the Dockerfile...
<server description="Default Server"> <featureManager> <feature>webProfile-6.0</feature> </featureManager> <httpEndpoint id="defaultHttpEndpoint" httpPort="${memberHttpPort}" httpsPort="${memberHttpsPort}" /> </server>
- Ensure the collective controller server.xml file has statements defining the controller user name and password and deployment variables.
- Liberty Network Deployment example:
<collectiveController user="admin" password="adminpwd" /> ... <deployVariable name="memberHttpPort" value="9090" increment="1"/> <deployVariable name="memberHttpsPort" value="9453" increment="1"/>
- Liberty Network Deployment example:
- Node.js member example:
<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.
- Create the image.
- Copy the Dockerfile and the joinMember and removeMember scripts to a computer with Docker installed. If we 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.
- Open a command window at the directory that holds the files.
- Create the Docker image:
- docker build -t image_name .
- Verify the image creation. The following command returns the image name when creation is successful.
- docker images
- Optional: Post the Docker image on a Docker registry with a docker push command.
- Create a Dockerfile.
- 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.
wlp/bin/collective registerHost targetHost \ --host=controllerHost \ --port=controllerHTTPSPort \ --user=controllerAdmin \ --password=controllerAdminPassword \ --rpcUser=osUser \ --rpcUserPassword=osUserPassword \ --autoAcceptCertificatesLook at server.xml 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, we can use the updateHost command to reset registration information.
- If the Docker image to deploy is stored in a registry instead of locally available on the Docker host where we will deploy, configure the collective controller to access the registry.
- Review the available deployment rules.
-
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" ]} - If necessary, create our own deployment rules by adding DeployRules to the controller configuration.
-
Invoke a REST API that returns the available deployment rules.
- 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 used 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 we 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. We do not need to specify a deploy rule. The rule used for deployment was stored at deploy time. We 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 https://controller_host:controller_port/ibm/api/collective/v1/deployment/undeploy
To get status and results, follow steps similar to deployments.
Related reference