About Me

My photo
Rohit is an investor, startup advisor and an Application Modernization Scale Specialist working at Google.

Wednesday, August 16, 2017

Pushing Docker images to Pivotal Cloud Foundry

Everyone thinks that Cloud Foundry does NOT support Docker images. Well here is your periodic reminder that CF and by extension PCF does support pushing of Docker images both from public and private docker registries.  Start with reading these links Using Docker in Cloud Foundry and Deploy an app with Docker.

Lets push a sample batch WebSphere Liberty Profile application to PCF. This batch application lives at https://github.com/WASdev/sample.batch.sleepybatchlet

SleepyBatchlet is a simple sample batchlet for use with feature batch-1.0 on WebSphere Liberty Profile. batch-1.0 is Liberty's implementation of the Batch Programming Model in Java EE 7, as specified by JSR 352. The batchlet itself is rather uninteresting. All it does is sleep in 1 second increments for a default time of 15 seconds. The sleep time is configurable via batch property sleep.time.seconds. The batchlet prints a message to System.out each second, so you can easily verify that it's running.

A WebSphere Liberty Profile image was built using the following repo: https://hub.docker.com/_/websphere-liberty/  with the following Dockerfile and server.xml configuration. Please note the majority of the Dockerfile comes FROM https://github.com/WASdev/ci.docker/blob/master/ga/developer/kernel/Dockerfile that EXPOSE 9080 9443

Note the following stanza in the server.xml 
<httpEndpoint id="defaultHttpEndpoint"



httpsPort="9443" />

The WebSphere Liberty Profile application is listening on ports 9080 and 9443. Cloud Foundry by default ONLY routes to one HTTP port. When launching an application on Diego, the Cloud Controller honors any user-specified overrides such as a custom start command or custom environment variables.To determine which processes to run, the Cloud Controller fetches and stores the metadata associated with the Docker image. The Cloud Controller Instructs Diego and the Gorouter to route traffic to the lowest-numbered port exposed in the Docker image. So in this case Diego, goRouter and CC collaborate to automatically route traffic to port 9080 and ignore port 9443. 

The Dockerfile built simply copies the built application into the config/dropins folder of the LibertyProfile and drops the server.xml into the config folder and configures Liberty to install the right features needed at runtime. Its useful to look at all the Docker caveats as you compose the Dockerfile. Note you can only copies from the current Docker context into the image and cannot COPY or ADD paths starting at /.

Commands to build and push the Docker image:

docker build -t jsr352app . 

First run the app locally using the following command:

 docker run -d -p 80:9080 -p 443:9443 --name jsr352 jsr352app    

and validate output with
 docker logs --tail=all -f jsr352 

Your local IP address can be found with the following command

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' jsr352


Push the built Docker image to a public Docker registry like DockerHub using the following instructions
docker push kelapure/jsr352app
The image can be found publicly at https://hub.docker.com/r/kelapure/jsr352app/

You can now push the app to CF and watch logs during the push
cf push batch-app --docker-image kelapure/jsr352app 

Some other options that are helpful when debugging failed docker image pushes are the -u and the -t option that disable health check and increase the staging app start timeout respectively.
-t 300 and -u none

cf logs batch-app

It will take a while (probably 5 mins. or so) for the app to start and the cf command line output will look like this 

0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
1 of 1 instances running

App started

App batch-app was started using this command `/opt/ibm/docker/docker-server run defaultServer`

Showing health and status for app batch-app in org pivot-rkelapure / space development as rkelapure@pivotal.io...

requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: batch-app.cfapps.pez.pivotal.io
last uploaded: Tue Aug 15 21:12:17 UTC 2017
stack: cflinuxfs2
buildpack: unknown

Multiple Application Ports

Please NOTE if you want to expose multiple ports in PCF you will need to use experimental APIs and follow these steps
  1. Push the WAS/Docker image
  2. Add the additional port via:
    cf curl "/v2/apps/<App GUID>" -X PUT -d '{"ports":[8080, 9060]}'
  3. Create a new, un-bound, route: cf create-route...
  4. Map the 2nd, new route to port 9060
    cf curl "/v2/route_mappings" -X POST -d '{ "app_guid": "<App GUID>", "route_guid": "<Route GUID>", "app_port": 9060}'
The Cloud Foundry community is actively working on adding support for multiple app port routing. You will find a WIP proposal on multiple custom app ports . Credit DereK Beauregard


  1. https://tecadmin.net/remove-docker-images-and-containers/
  2. https://github.com/WASdev/ci.docker.tutorials/tree/master/liberty

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.