Thursday, September 26, 2019

Dockerizing a Node.js web app

The goal of this example is to show you how to get a Node.js application into a Docker container. The guide is intended for development, and not for a production deployment. The guide also assumes you have a working Docker installation and a basic understanding of how a Node.js application is structured.
In the first part of this guide we will create a simple web application in Node.js, then we will build a Docker image for that application, and lastly we will instantiate a container from that image.
Docker allows you to package an application with its environment and all of its dependencies into a "box", called a container. Usually, a container consists of an application running in a stripped-to-basics version of a Linux operating system. An image is the blueprint for a container, a container is a running instance of an image.

Create the Node.js app

First, create a new directory where all the files would live. In this directory create a package.json file that describes your app and its dependencies:
{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "First Last <first.last@example.com>",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.1"
  }
}
With your new package.json file, run npm install. If you are using npm version 5 or later, this will generate a package-lock.json file which will be copied to your Docker image.
Then, create a server.js file that defines a web app using the Express.js framework:
'use strict';

const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello world\n');
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
In the next steps, we'll look at how you can run this app inside a Docker container using the official Docker image. First, you'll need to build a Docker image of your app.

Creating a Dockerfile

Create an empty file called Dockerfile:
touch Dockerfile
Open the Dockerfile in your favorite text editor
The first thing we need to do is define from what image we want to build from. Here we will use the latest LTS (long term support) version 10 of node available from the Docker Hub:
FROM node:10
Next we create a directory to hold the application code inside the image, this will be the working directory for your application:
# Create app directory
WORKDIR /usr/src/app
This image comes with Node.js and NPM already installed so the next thing we need to do is to install your app dependencies using the npm binary. Please note that if you are using npm version 4 or earlier a package-lock.json file will not be generated.
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
Note that, rather than copying the entire working directory, we are only copying the package.json file. This allows us to take advantage of cached Docker layers. bitJudo has a good explanation of this here. Furthermore, the npm ci command, specified in the comments, helps provide faster, reliable, reproducible builds for production environments. You can read more about this here.
To bundle your app's source code inside the Docker image, use the COPY instruction:
# Bundle app source
COPY . .
Your app binds to port 8080 so you'll use the EXPOSE instruction to have it mapped by the docker daemon:
EXPOSE 8080
Last but not least, define the command to run your app using CMD which defines your runtime. Here we will use node server.js to start your server:
CMD [ "node", "server.js" ]
Your Dockerfile should now look like this:
FROM node:10

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "node", "server.js" ]

.dockerignore file

Create a .dockerignore file in the same directory as your Dockerfile with following content:
node_modules
npm-debug.log
This will prevent your local modules and debug logs from being copied onto your Docker image and possibly overwriting modules installed within your image.

Building your image

Go to the directory that has your Dockerfile and run the following command to build the Docker image. The -t flag lets you tag your image so it's easier to find later using the docker images command:
docker build -t <your username>/node-web-app .
Your image will now be listed by Docker:
$ docker images

# Example
REPOSITORY                      TAG        ID              CREATED
node                            10         1934b0b038d1    5 days ago
<your username>/node-web-app    latest     d64d3505b0d2    1 minute ago

Run the image

Running your image with -d runs the container in detached mode, leaving the container running in the background. The -p flag redirects a public port to a private port inside the container. Run the image you previously built:
docker run -p 49160:8080 -d <your username>/node-web-app
Print the output of your app:
# Get container ID
$ docker ps

# Print app output
$ docker logs <container id>

# Example
Running on http://localhost:8080
If you need to go inside the container you can use the exec command:
# Enter the container
$ docker exec -it <container id> /bin/bash

Test

To test your app, get the port of your app that Docker mapped:
$ docker ps

# Example
ID            IMAGE                                COMMAND    ...   PORTS
ecce33b30ebf  <your username>/node-web-app:latest  npm start  ...   49160->8080
In the example above, Docker mapped the 8080 port inside of the container to the port 49160 on your machine.
Now you can call your app using curl (install if needed via: sudo apt-get install curl):
$ curl -i localhost:49160

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 12
ETag: W/"c-M6tWOb/Y57lesdjQuHeB1P/qTV0"
Date: Mon, 13 Nov 2017 20:53:59 GMT
Connection: keep-alive

Hello world
We hope this tutorial helped you get up and running a simple Node.js application on Docker.
You can find more information about Docker and Node.js on Docker in the following places:

Jet setup

Running Oracle JET in Oracle Cloud Free Tier

OOW'19 stands up from recent years OOW conferences with important announcement - Oracle Cloud Free Tier offering. This offering includes two free DB instances and two free compute VM instances. What else you could wish for the side and hobby projects? This is a strong move by Oracle and it should boost Oracle Cloud. Read more about it in Oracle Cloud Free Tier page.



It was interesting to test how to deploy Oracle JET app to Oracle Always Free instance of compute VM. I will not go through the initial steps, related how to create VM instance and enable internet access (for the port 80). You can read all that in a nice write up from Dimitri Gielis post.

Assuming you already have created Oracle JET app and want to deploy it. One way would be to set up Node.js and Nginx on the compute VM and pull app source code from Git. I prefer another way - to go through Docker container, Nginx would act as HTTP server to redirect requests to Docker container port. But in this post for simplicity reasons, we are not going to look into Nginx setup - will focus only on JET deployment through Docker container.

1. Create an empty Node application (follow these steps):

express --view=pug 

2. Add dependencies, go into the Node app and run:

npm install

3. Copy Oracle JET content from web folder into Node app public folder (remove existing files)

4. Inside Node app, adjust app.js file, comment out these lines:

var usersRouter = require('./routes/users');

app.set('view engine', 'pug');

app.use('/users', usersRouter);

5. Keep only index.js file in router folder

6. Remove template files from views folder

7. Update index.js file to redirect to Oracle JET index.html

router.get('/', function(req, res, next) {
  //res.render('index', { title: 'Express' });
  res.sendFile('index.html', {root: './public/'});
});

8. Note down port 3000 info from bin/www, this is the port Node app will run in Docker container

9. Create Dockerfile inside Node app folder (follow these steps). Content:

FROM node:10

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000
CMD [ "node", "./bin/www" ]

10. Create .dockerignore file. Content:

node_modules
npm-debug.log

11. Build Docker image locally, by running below command inside Node app:

docker build -t username/imagename -f ./Dockerfile .

12. Push Docker container to Docker Hub. This way we will be able to pull container from Oracle compute VM in the cloud:

docker push username/imagename

---

Next steps are executed inside Oracle compute VM. You should connect through SSH to run below commands.

13. Install Docker (run sudo su):

yum install docker-engine

14. Enable Docker:

systemctl enable docker

15. Start Docker:

systemctl start docker

16. Check Docker status:

systemctl status docker.service

17. Check Docker version:

docker version

18. Login into Docker Hub, to be able to pull the container with Node app. If login doesn't work (access permission issue), run this command: sudo usermod -a -G docker $USER

docker login

19. Run container:

docker run -p 80:3000 -d --name appname username/imagename

Node app with Oracle JET content can be accessed by port 80 using public IP of your Oracle container VM: http://130.61.241.30/index.html

Oracle JET app runs on Oracle container VM free tier:

Oracle cloud for free setup

Best and Cheapest Oracle APEX hosting: Free Oracle Cloud

I really have to write about the Oracle Cloud Free Tier as it's the third time in my career I've been blown away by Oracle.

The first time was when I first saw and worked with the Oracle Database, the second time when I saw HTMLDB (now APEX) and today, again, with the announcement of the Free Autonomous Oracle Cloud.

The Free Oracle Tier is a hardcore smackdown on any other cloud offering which includes a virtual machine, database and development environment!



The Free Oracle Cloud was announced by Andy Mendelsohn at Oracle Open World 2019.
You get a free Oracle Autonomous Database, 2 Virtual Machines (Compute), Storage and other services:








There's nothing like this Oracle offering on the market. The best database in the world, running on amazing hardware and all of this for free. This is not just for APEX Developers, this is for anybody who wants a datastore or virtual machine in the cloud without wanting to manage things themselves.

Jon, from JMJ Cloud, wrote RIP Exadata Express, where do I run my RAD stack now?, the answer today for me is in the Free Oracle Autonomous Oracle Cloud. For many of my customers I also used the Exadata Express service before, as it was ideal to start developing new Oracle APEX apps. The Free Oracle Autonomous Database Cloud is a better version of what Exadata Express has ever been. I would always start my development in this new free Oracle Cloud offering as it allows you to scale up while you grow.

I really believe everybody should sign-up for this service. As with every new service, the beginning might have some hickups, but to me it's worth starting with this service straight away.

I signed up for the Free Oracle Cloud  in multiple regions, and love it so far.
So I thought to write a series of blog posts on how you can get started (links will be updated while articles are published):

1. Sign-up for Free Oracle Cloud
2. Setup Autonomous Transaction Cloud (ATP)
3. Connecting with SQL Developer (Desktop) to ATP
4. Connecting with SQL Developer Web to ATP
5. Setup APEX in ATP and create first APEX app
6. Create a VM Instance (Compute Cloud)
7. Setup a Webserver on the Compute Instance (VM)
8. Setup APEX Office Print (AOP) to export to PDF, Excel, Word, Powerpoint, HTML and Text
9. Setup an Object Store and make manual database backups
10. Running SQLcl and Datapump from the Compute Instance (VM) to ATP
11. Final steps: never let the service expire


Must Watch YouTube Videos for Databricks Platform Administrators

  While written word is clearly the medium of choice for this platform, sometimes a picture or a video can be worth 1,000 words. Below are  ...