loopbackio / loopback-next

LoopBack makes it easy to build modern API applications that require complex integrations.
https://loopback.io
Other
4.96k stars 1.07k forks source link

[Spike] Deploy a basic LB4 application to IBM Cloud Kubernetes #1606

Closed hacksparrow closed 5 years ago

hacksparrow commented 6 years ago

Time box this spike for a week

Description

Find out what's needed to deploy LB4 applications to IBM Cloud Kubernetes and write a short document describing the steps.

Updated per discussion with @raymondfeng @bajtos @jjtang1:

This spike/task is only limited to document the steps on how to deploy to k8s, and not about implementing any changes that would enhance the user experience (This will be the longer term goal).

~Take our existing Todo application as the project to deploy, but make the following changes:~

~- Use Cloudant (free Lite plan) to persist our Todo items. To do so, we need to temporarily modify db datasource to use cloudant connector and add this connector to project dependencies.~ ~- When deploying to IBM Cloud Kubernetes, the application must be configured to use a cloud-based Cloudant instance.~ ~- When developing and testing locally, the app should use local docker-based Cloudant Developer Edition.~ ~- There may be other settings we need to tweak when deploying to cloud, for example the port number where to listen.~ ~Besides the deployment guide, this spike should also identify the biggest pain points - things we need to improve to make the deployment experience smoother.~

Acceptance criteria

dhmlau commented 6 years ago

Per the team meeting's discussion, we'll visit it after GA.

dhmlau commented 6 years ago

As a reference: Saw some documentation on deploying to IBM Cloud using kubernetes, not sure how much it will be different/similar in our case: https://www.ibm.com/cloud/garage/tutorials/microservices-app-on-kubernetes/ https://console.bluemix.net/docs/containers/cs_tutorials_apps.html#cs_apps_tutorial

hacksparrow commented 6 years ago

We'll have lots of useful info from those, that's for sure. There might be LB4 specific requirements, which we don't know about yet. Good find!

emonddr commented 5 years ago

Pain Points

emonddr commented 5 years ago

Articles about dockerizing a web app in docker

( No mention of setting host IP to 0.0.0.0 )

https://semaphoreci.com/community/tutorials/dockerizing-a-node-js-web-application https://we-are.bookmyshow.com/understanding-expose-in-dockerfile-266938b6a33d

Articles about dockerizing a web app in docker

( Do mention setting host IP to 0.0.0.0 )

https://nodejs.org/en/docs/guides/nodejs-docker-webapp/ https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker

emonddr commented 5 years ago

Perhaps there should be a page in the documentation explaining how an lb4 application can be configured to work in a Docker container, and explain : 1) which file need to be changed ( index.js), 2) what to place in the Dockerfile, and 3) How to build the docker image, and run the application in the docker container.

dhmlau commented 5 years ago

I also had a talk with @raymondfeng about the direction of this cloud native experience:

@emonddr, what do you think we can do to minimize the manual steps you need to go through in "step 1"?

emonddr commented 5 years ago

@raymondfeng , @bajtos . With regards to the step of having to set the host IP to 0.0.0.0 in index.js, I was hoping one of you could shed some light about why this step is necessary to get a loopback 4 application (web server) working in Docker. I am not an expert on the product yet, and I am not an expert on Docker. As I mentioned above , while discussing the main pain point, I found different articles on getting web server applications working in Docker, and some never mention having to set host IP to 0.0.0.0 in application code/config, and some do ( some were articles on Node.js applications).

raymondfeng commented 5 years ago

@emonddr I don't think listening on 0.0.0.0 is specific for LB4. It probably applies to all Node.js apps. My understanding is Docker container has multiple network interfaces and 0.0.0.0 means all of them. One way to verify is to log into your docker container and run ifconfig. Please note one of such interfaces are bridged into the host OS.

emonddr commented 5 years ago

I spoke to @b-admike after his "ToDo List" application demo, to have him try to get his application to work in a docker container to see if he encounters into the same problem as I did. He ended up having to change his index.js file (setting host to 0.0.0.0) in order to get his lb4 application running in docker and accessible from outside the container.

He suggested that perhaps loopback CLI should generate an index.js file that has:

 const config = {
    rest: {
      port: +process.env.PORT || 3000,
      host: process.env.HOST || '0.0.0.0',
      openApiSpec: {
        // useful when used with OASGraph to locate your application
        setServersFromRequest: true,
      },
    },
  };

instead of :

 const config = {
    rest: {
      port: +process.env.PORT || 3000,
      host: process.env.HOST || 'localhost',
      openApiSpec: {
        // useful when used with OASGraph to locate your application
        setServersFromRequest: true,
      },
    },
  };

This would allow : the application to receive incoming connections from any network interface besides the localhost (loopback) interface (network interface agnostic), and the application to work as-is ( standalone or inside a docker container) without any modifications to the host ip address.

This would eliminate one step in deploying an lb4 app to kubernetes on IBM Cloud.

emonddr commented 5 years ago

Having the CLI generate a .dockerignore file would eliminate another step.

The contents of .dockerignore would be 👍

node_modules
npm-debug.log

Having the CLI generate the Dockerfile file would eliminate another step.

The contents of Dockerfile would be:

FROM node:10.14-alpine

EXPOSE 3000

COPY package.json package.json
RUN npm install

COPY . .

RUN npm run build

CMD ["npm", "start" ]

The port we expose in the Dockerfile would need to be aligned with the value in the index.js file. The node docker image value , for example: node:10.14-alpine , would have to be a valid/recent docker image for node. The CLI would prompt for these values or offer valid values as default.

Having the CLI create a build_docker_image.sh , run_app_in_docker.sh, stop_app_in_docker.sh, show_logs_of_app_in_docker.sh, list_docker_apps.sh, list_docker_images.sh, delete_docker_image.sh (Not sure exactly how much "Docker" hand-holding we should do for the user with script files vs documenting docker commands in the how-to document itself.

dhmlau commented 5 years ago

@emonddr , could you please summarize the next steps? We'd need to agree on the follow-up task(s) in order to claim this spike done. :) Thanks.

emonddr commented 5 years ago

Next Steps

  1. The existing lb4 app CLI command should generate an index.js where '0.0.0.0' is used instead of 'localhost' for the host IP value
  2. A new lb4 docker CLI command should generate a .dockerignore file
  3. A new lb4 docker CLI command should generate a Dockerfile file
  4. A new lb4 docker CLI command should generate script files to : build the docker image, start the app in Docker, stop the app in Docker.
dhmlau commented 5 years ago

@strongloop/loopback-maintainers ^^ If we agree on the above next steps, @emonddr can create a task for that and call this spike done. Thanks.

bajtos commented 5 years ago

The next steps look good to me. I have few comments to consider.

The existing lb4 app CLI command should generate an index.js where '0.0.0.0' is used instead of 'localhost' for the host IP value

IIRC, we used to use 0.0.0.0 as the default IP address to listen on. I believe that when no hostname is specified, LB4 will listen on all interfaces by default.

Here is the reason why we limited the HTTP server to localhost in the scaffolded applications: When an LB4 application starts, it prints the URL where it is listening on. I vaguely remember there were issues with an URL like http://0.0.0.0:3000/ or http://[::1]:3000, certain browsers or operating systems were not able to load it. See also #1623.

We should refresh our understanding of this area to make sure the changes preserve overal user experience.

Other related discussions: #1900 #1637

  1. A new lb4 docker CLI command should generate a .dockerignore file
    1. A new lb4 docker CLI command should generate a Dockerfile file
    2. A new lb4 docker CLI command should generate script files to : build the docker image, start the app in Docker, stop the app in Docker.

Perhaps lb4 dockerize may better convey the meaning of the action?

Nice to have: lb4 app can ask the user whether they want to dockerize their application as part of the initial scaffolding.

$ lb4 app my-project --dockerize
dhmlau commented 5 years ago

+1 on $ lb4 app my-project --dockerize. Perhaps (eventually) we want to offer options to dockerize right at the scaffolding phase and any point in time during the LB app development?

emonddr commented 5 years ago

@bajtos , @raymondfeng I read those links provided above and they are very involved. I think perhaps before we even consider a design spike for kubernetes on the IBM Cloud, there should be a design spike to test if all conceivable server configurations would run inside a simple Docker container. Are there any existing test cases for this?

emonddr commented 5 years ago

Closing this spike now that I have created two next step tasks : #2350 and #2351.