SYSTEM
user to perform a quick test of our backend app. In a real world use case, we of course do not want to do this. So we will designate some new environment variables to specify a new application user and password.HXE_MASTER_PASSWORD=HXEHana1
HANA_APP_UID=APPUSER
HANA_APP_PWD=SomeSecretPassword
HANA_SERVER=hxehost:39017
HANA_APP_BACKEND=/backend
docker-compose.yaml
file under /hanadev
and update the contents as follows:version: '2'
services:
hello-world-app:
build:
context: .
dockerfile: ./hello-world-app/Dockerfile
ports:
- "3333:9999"
environment:
- HANA_UID=${HANA_APP_UID}
- HANA_PWD=${HANA_APP_PWD}
- HANA_SERVERNODE=${HANA_SERVER}
sqlpad:
image: sqlpad/sqlpad
volumes:
- sqlpad:/var/lib/sqlpad
ports:
- "8899:3000"
hxehost:
image: store/saplabs/hanaexpress:2.00.036.00.20190223.1
hostname: hxe
volumes:
- hana-express:/hana/mounts
command: --agree-to-sap-license --master-password ${HXE_MASTER_PASSWORD}
volumes:
hana-express:
sqlpad:
hello-world-app
environment variable mapping of HANA_UID
and HANA_PWD
to point to our new HANA_APP_UID
and HANA_APP_PWD
variables in our .env
files.hanadev
directory in a terminal window.docker-compose up
http://[cloud 9 external IP]:8899
and log in with the user you created. Refer to Part 1 if you need a reminder on how to log in.CREATE USER APPUSER PASSWORD SomeSecretPassword NO FORCE_FIRST_PASSWORD_CHANGE;
Control + C
in the terminal window that you typed docker-compose up
.docker-compose-up -d
and wait about 60 seconds for HANA Express to start up.curl -X POST http://localhost:3333/api/overview | grep user
. You should get a one line back of the JSON output similar to below: % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1202 100 1202 0 0 52260 0 --:--:-- --:--:-- --:--:-- 52260
"user": "APPUSER"
npm i -g @vue/cli
. This will install Vue and the Vue CLI.vue ui -p 8080
from the hanadev/hello-world-app
directory (important.) Once you see the status in your terminal below, proceed to the next step.ec2-user:~/environment/hanadev (Part3) $ vue ui -p 8080
Starting GUI...
Ready on http://localhost:8080
frontend
. Click Next.hanadev/hello-world-app/frontend
folder. After a few moments, you should arrive at a screen saying “Welcome to your new project!”.vue-cli-plugin-vuetify
. Click on the matching search result and click on Install vie-cli-plugin-vuetify.
App running at:
Local: http://localhost:8081/
Network: http://172.16.0.99:8081/
Note that the development build is not optimized.
To create a production build, run npm run build.
80xx
(whichever one is mentioned in the output) in our Cloud 9 EC2 instance in order to access this application easier. Refer to steps in Part 1 if you do not know how to do this. I’d recommend opening up ports 8080
through 8085
as sometimes we may be running more than one app at once and it will save you a trip to the EC2 Dashboard later on.80xx
port, navigate to http://[your cloud 9 external ip]:80xx
.Welcome to Your Vue.js App
congratulations! We are ready to start coding./hanadev/hello-world-app/frontend
folder. This is where all your frontend code has now been generated. Modify/Create the following files./hello-world-app/frontend/.env.production
:This file will be used for our final productin build. The VUE_APP_HANA_APP_BACKEND
variable tells the frontend app where to issue backend requests to. For production, we’ll handle this with Nginx a bit later on.VUE_APP_HANA_APP_BACKEND=/backend
/hello-world-app/frontend/.env.development.local
NOTE: Be sure to add your Cloud 9 External IP address in the placeholder below. For development, we’ll want to hit our running Docker stack running in Cloud 9.VUE_APP_HANA_APP_BACKEND=http://[your cloud 9 external ip]:3333
/hello-world-app/frontend/src/main.js
import Vue from 'vue'
import './plugins/vuetify'
import App from './App.vue'
import router from './router'
if(!process.env.VUE_APP_HANA_APP_BACKEND){
alert("VUE_APP_HANA_APP_BACKEND environment variable not set. Please set your environment and restart this frontend server.")
}else{
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
}
/hello-world-app/frontend/src/router.js
import Vue from 'vue'
import Router from 'vue-router'
import Overview from './views/Overview.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Overview',
component: Overview
}
]
})
/hello-world-app/frontend/src/App.vue
<template>
<v-app dark>
<AppNav :systemInformation="results.backend_information"/>
<v-content transition="slide-x-transition">
<router-view />
</v-content>
</v-app>
</template>
<script>
import AppNav from '@/AppNav';
import axios from 'axios';
export default {
name: 'App',
components: {
AppNav
},
data () {
return {
results: {
backend_information : {
user : 'dummy'
}
}
};
},
methods : {
getData (){
axios.post(process.env.VUE_APP_HANA_APP_BACKEND + '/api/overview/',{ }).then(res=>{
if(res.data){
this.results = res.data;
this.systemInformation = res.data.backend_information;
// console.log(this.results);
}else{
alert(JSON.stringify(res));
this.results = {};
}
}, err=> {
alert(JSON.stringify(err.response.data));
}).catch(err=>{
alert(`An error occured communicating with the backend.
${err}`);
})
},
},
mounted(){
this.getData();
}
};
</script>
/hello-world-app/frontend/src/AppNav.vue
<template>
<v-toolbar app color="blue darken-4" dark>
<v-toolbar-title>{{appTitle}}</v-toolbar-title>
<template v-for="(item,index) in items">
<v-btn v-if="typeof item.link === 'undefined'" :key=index flat :to="'/' + item.title">{{item.title}}</v-btn>
<v-btn v-else :key=index flat :to="'/' + item.link">{{item.title}}</v-btn>
</template>
<v-spacer />
<v-chip color="primary" label outline text-color="white">{{systemInformation.user}}@{{systemInformation.server}}:{{systemInformation.port}}</v-chip>
</v-toolbar>
</template>
<script>
export default {
name: 'AppNav',
props : {
systemInformation : Object
},
data(){
return{
appTitle: 'HANA Sandbox',
drawer: false,
items: [
{ title: 'Overview',link: '' }
]
};
}
};
</script>
<style scoped>
</style>
About.vue
, Home.vue
etc.) under /hello-world-app/frontend/src/views
/hello-world-app/frontend/src/views/Overview.vue
<template>
<div>
<v-list two-line>
<template v-for="(item,index) in results.M_SYSTEM_OVERVIEW">
<v-list-tile :key="index">
<v-list-tile-content>
<v-list-tile-title v-html="item.KEY"></v-list-tile-title>
<v-list-tile-sub-title v-html="item.VAL"></v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</template>
</v-list>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Overview',
data: () => ({
results: []
}),
components: {},
methods: {
getData(){
axios.post(process.env.VUE_APP_HANA_APP_BACKEND + '/api/overview/',{ }).then(res=>{
if(res.data){
this.results = res.data;
}else{
this.results = {};
}
}, err=> {
alert(JSON.stringify(err.response.data));
}).catch(err=>{
alert(`An error occured communicating with the backend.
${err}`);
})
}
},
mounted(){
this.getData();
}
}
</script>
Overview.vue
file, we are making use of the axios
npm module, so we will want to install this. To do so, open a terminal window in Cloud 9 and cd to your frontend
folder. Type npm i axios
to install it.vue-cli
UI, you can now terminate it by pressing Control + C
. We will now demonstrate how to run the same serve task via command line from the terminal.3333
. This is our backend port that we’ll need our browser to hit in order to get back data from our HANA Container running in our Stack while running in Developer mode. For “production” use cases, we will not need this port.cd /hanadev
docker-compose up -d
cd /hanadev/hello-world-app/frontend`
npm run serve
http://[your cloud 9 external ip]:80xx
where 80xx
is the port mentioned above.Control + C
.docker-compose.yaml
file before we call it a day. We’ll need to update a few files to incorporate the frontend app.Dockerfile
located under /hanadev
Update it with the following:# Docker Image containing SAP HANA npm package
FROM node:8-slim
LABEL Maintainer="Your Name <your.name@example.com>"
# Install nginx to handle backend and frontend apps
RUN apt-get update && apt-get install -y nginx
# Add SAP HANA Client NPM package from SAP's npm repository
RUN npm config set @sap:registry https://npm.sap.com && npm i -g @sap/hana-client
# Set the global NPM path Environment variable
ENV NODE_PATH /usr/local/lib/node_modules
# Configure nginx and startup
COPY ./hello-world-app/server.conf /etc/nginx/conf.d/default.conf
# Copy backend Node JS modu
COPY /hello-world-app/backend /app/backend
# Copy production build of Vue frontend app
COPY /hello-world-app/frontend/dist /app/frontend
# Copy startup.sh script
COPY ./hello-world-app/startup.sh /app/startup.sh
WORKDIR /app
CMD ./startup.sh
dist
folder will be copied over to our Docker images’s /app/frontend
folder. The production dist
folder is an optimized and minified version of our frontend Vue app.startup.sh
script since we’ll be launching more than one process for the CMD
line.startup.sh
in /hanadev/hello-world-app
#!/bin/sh
echo "Starting Servers..."
mkdir -p /run/nginx
rm /etc/nginx/sites-enabled/default
echo "Starting nginx..."
nginx
cd /app/backend
echo "Starting backend..."
npm run prod
startup.sh
from a terminal window cd /hanadev/hello-world-app
chmod +x startup.sh
server.conf
in /hanadev/hello-world-app
server {
listen 80 default_server;
# document root #
root /app/frontend/;
# Route requsts to /backend/ to Backend npm module
location /backend/ {
proxy_pass http://localhost:9999/;
}
}
```
dist
folder.
cd /hanadev/hello-world-app/frontend
npm run build
> frontend@0.1.0 build /home/ec2-user/environment/hanadev/hello-world-app/frontend
> vue-cli-service build
⠏ Building for production...
WARNING Compiled with 2 warnings 19:16:17
warning
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
app (303 KiB)
css/chunk-vendors.bc527eeb.css
js/chunk-vendors.2793d0c4.js
js/app.02b450ce.js
warning
webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
File Size Gzipped
dist/js/chunk-vendors.2793d0c4.js 180.43 KiB 60.10 KiB
dist/js/app.02b450ce.js 4.87 KiB 2.03 KiB
dist/css/chunk-vendors.bc527eeb.css 118.13 KiB 15.45 KiB
Images and other types of assets omitted.
DONE Build complete. The dist directory is ready to be deployed.
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
docker-compose.yaml
file under /hanadev
:version: '2'
services:
hello-world-app:
build:
context: .
dockerfile: ./hello-world-app/Dockerfile
ports:
# - "3333:9999" No longer needed we are using Nginx
# Reroute Nginx listening on Port 80 over to 8080 which we've already exposed in EC2
- "8080:80"
environment:
- HANA_UID=${HANA_APP_UID}
- HANA_PWD=${HANA_APP_PWD}
- HANA_SERVERNODE=${HANA_SERVER}
sqlpad:
image: sqlpad/sqlpad
volumes:
- sqlpad:/var/lib/sqlpad
ports:
- "8899:3000"
hxehost:
image: store/saplabs/hanaexpress:2.00.036.00.20190223.1
hostname: hxe
volumes:
- hana-express:/hana/mounts
command: --agree-to-sap-license --master-password ${HXE_MASTER_PASSWORD}
volumes:
hana-express:
sqlpad:
3333
) from being accessible, since our Nginx app inside of our Docker container will be reverse-proxying calls to the npm task running there. For development use cases, you may wish to leave this in place for when developing live and not hosting inside a container, or better yet, simply have a separate docker compose stack for when you are developing, and maybe this one that represents “production”.80
over to Port 8080
since we’ve already exposed 8080
in our EC2 Dashboard, and that will save us a trip and another exposed port.cd /hanadev
docker-compose build
...
Step 7/11 : COPY /hello-world-app/backend /app/backend
---> c5c3508dc2a2
Step 8/11 : COPY /hello-world-app/frontend/dist /app/frontend
---> 6ee34d81d8d5
Step 9/11 : COPY ./hello-world-app/startup.sh /app/startup.sh
---> 60f38e70da77
Step 10/11 : WORKDIR /app
---> Running in e54ee8b3c9c6
Removing intermediate container e54ee8b3c9c6
---> df3d269e1dff
Step 11/11 : CMD ./startup.sh
---> Running in 594e5016ca51
Removing intermediate container 594e5016ca51
---> 4abedcaed348
Successfully built 4abedcaed348
Successfully tagged hanadev_hello-world-app:latest
/hanadev
, type:docker-compose up
http://[your cloud 9 ide external ip]:8080
If you see the HANA Sandbox page with your HANA Express system overview, congratulations! You’ve successfully containerized your frontend and backend app!You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
9 | |
8 | |
6 | |
5 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 |