Generic Docker container image for running and dynamically reloading an Oracle JET application from a Git repository

0

This article introduces a Docker Container Image that runs an Oracle JET application from a Git repository and is capable of dynamic reload of that application when the repository contents get updated. The container image sources are on GitHub in repository https://github.com/lucasjellema/docker-oracle-jet-run-live-reload. It has been pushed to Docker Hub as lucasjellema/ojet-run-live-reload:0.1.

The next figure illustrates the contents and working of the container:

image

 

The container contains the Oracle JET 5.2 runtime and CLI for building the JET application as well the Node runtime for serving the JET application and nodemon for restart the that Node runtime application server when any sources are changed. The container is run with a GIT repository URL as minimal input; this repository should contain the Oracle JET application (compatible with JET 5 and developed using the Oracle JET CLI). The application is git cloned from the repository. Subsequently, the JET application is built and copied to the Node application that will serve it. Then this Node application is started – serving the JET application at port 3000.

A reload can be requested on port 4500, endpoint /reload. Such a request will force a git pull – refreshing the application sources from the repository. The application is rebuilt and the Node reloader application is refreshed to serve the new version of the JET application.

The next figure illustrates these steps:

image

I have selected a JET application repository in GitHub at random and ran it with a single command line statement:

docker run --name jet-app -p 3006:3000 -p 4515:4500 -e GITHUB_URL=https://github.com/vijayveluchamy/ojet-exp-manager -e APPLICATION_ROOT_DIRECTORY= -d lucasjellema/ojet-run-live-reload:0.1

In just a few seconds, the application is available and can be accessed in my browser:

image

Details on the Generic JET Runner and Reloader

In this section I will show the main constituents of the container image. Note that this container is based on the generic Node application runner that was introduced in an earlier article: https://technology.amis.nl/2018/09/22/generic-docker-container-image-for-running-and-live-reloading-a-node-application-based-on-a-github-repo/ .

The container is based on the node:10 image (perhaps a bit heavy handed?). The Oracle JET CLI is installed into it, as is the nodemon utility. The reloader application is added to the container (a simple Node application that received the reload request and or the GitHub WebHook and invokes the gitRefresh script). Scripts are added to run upon startup (startUpScript.sh) and upon reload (gitRefresh.sh).

Dockerfile:

FROM node:10
#copy the Node Reload server - exposed at port 4500
COPY reloader /tmp/reloader
COPY jet-on-node /tmp/jet-on-node
RUN cd /tmp/reloader && npm install
RUN cd /tmp/jet-on-node && npm install
EXPOSE 4500
RUN npm install -g nodemon
RUN npm install -g @oracle/ojet-cli
COPY startUpScript.sh /tmp
COPY gitRefresh.sh /tmp
CMD ["chmod", "+x",  "/tmp/startUpScript.sh"]
RUN /bin/bash -c 'chmod +x /tmp/gitRefresh.sh'
ENTRYPOINT ["sh", "/tmp/startUpScript.sh"]

The startUpScript that is executed whenever the container is started up – that takes care of the initial cloning of the JET application from the Git(Hub) URL to directory /tmp/app, followed by building the application (ojet build), copying it to the public directory under the /tmp/jet-on-node directory and the serving of that application using nodemon is shown below. The startup script runs the live reloader application in the background – using (echo “start reload”;npm start)&. That final ampersand (&) takes care of running the command in the background. This npm start command runs the server.js file in /tmp/reloader. This server listens at port 4500 for reload requests.

#!/bin/sh
CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER"
TARGET_DIR=${APPLICATION_ROOT_DIRECTORY-''}
if [ ! -e $CONTAINER_ALREADY_STARTED ]; then
    touch $CONTAINER_ALREADY_STARTED
    echo "-- First container startup --"
    # this branch is only executed when the container is first started
    cd /tmp
    # prepare the actual JET app from GitHub
    mkdir app
    git clone $GITHUB_URL app
    echo "GIT repo with Oracle JET application was cloned to /tmp/app/${TARGET_DIR}"
    cd /tmp/app/$TARGET_DIR
    #install dependencies for the JET application app
    npm install
    #build the deployable JET application from the sources
    ojet build
    #copy built JET application to /tmp/jet-on-node/public
    cp -a ./web/. /tmp/jet-on-node/public
    #start  both the reload app (in the background) and (using nodemon) the actual Node app
    cd /tmp/reloader
    echo "starting reload app and nodemon"
    (echo "start reload";npm start; echo "reload app finished") &
    cd /tmp/jet-on-node;
    echo "starting nodemon for JET app copied to /tmp/jet-on-node/public";
    nodemon --delay 2.5 --watch public
else
    echo "-- Not first container startup --"
    cd /tmp/reloader
    (echo "start reload";npm start; echo "reload app finished") &
    cd /tmp/jet-on-node;
    echo "starting nodemon for JET app copied to /tmp/jet-on-node/public";
    nodemon --delay 2.5 --watch public
fi

The gitRefresh script is executed when a reload request is processed. It performs a git pull to refresh the application sources. Next it rebuilds the JET application using the ojet cli. It copies the build product to the /tmp/jet-node/public directory from where the Node application serves the static sources of the JET application.

#!/bin/sh
cd /tmp/app
git pull
#install dependencies for the Node app
npm install
#rebuild JET application
ojet build
#copy built JET application to /tmp/jet-on-node/public
cp -a ./web/. /tmp/jet-on-node/public

You can build the Docker container image using

docker build -t "ojet-run-live-reload:0.1" .

Once the image is built it can be tagged and pushed – for me using:

docker tag ojet-run-live-reload:0.1 lucasjellema/ojet-run-live-reload:0.1

docker push lucasjellema/ojet-run-live-reload:0.1

I can now leverage the image using:

docker run --name jet-app -p 3020:3000 -p 4510:4500 -e GITHUB_URL=https://github.com/lucasjellema/webshop-portal-soaring-through-the-cloud-native-sequel -e APPLICATION_ROOT_DIRECTORY= -d lucasjellema/ojet-run-live-reload:0.1

which makes the Soaring through the Cloud Webshop Portal available – in this case on Oracle Container Cloud:

image

Just for kicks I tried to another random JET application from GitHub:

docker run --name jet-app -p 3008:3000 -p 4515:4500  -e GITHUB_URL=https://github.com/gregja/ojetdiscovery -e APPLICATION_ROOT_DIRECTORY= -d lucasjellema/ojet-run-live-reload:0.1

And that worked nicely too.

 

Resources

My earlier article Oracle JET Web Applications – Automating Build, Package and Deploy (to Application Container Cloud) using a Docker Container on creating a Docker container that can be used to build an Oracle JET application, package it and deploy it to Oracle Application Container Cloud – https://technology.amis.nl/2018/02/26/oracle-jet-web-applications-automating-build-package-and-deploy-to-application-container-cloud-using-a-docker-container/

My article on a generic Docker container that can run and reload any Node application: https://technology.amis.nl/2018/09/22/generic-docker-container-image-for-running-and-live-reloading-a-node-application-based-on-a-github-repo/

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director and Oracle Developer Champion. Solution architect and developer on diverse areas including SQL, JavaScript, Kubernetes & Docker, Machine Learning, Java, SOA and microservices, events in various shapes and forms and many other things. Author of the Oracle Press book Oracle SOA Suite 12c Handbook. Frequent presenter on user groups and community events and conferences such as JavaOne, Oracle Code, CodeOne, NLJUG JFall and Oracle OpenWorld.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.