Skip to main content

Complete Webapp Tutorial


This is a quick general tutorial to help you understand how you should architecture an app that has multiple components.

Let's say we want to make a webapp version of HOTDOG or NOT HOTDOG!

App Description

Assume we want to create a webapp that shows a list of photos with a line describing whether the image is a hotdog or not hotdog, something like this:

  • <IMAGE> Tags: Hotdog, Upload date: 2017-11-12
  • <ANOTHER IMAGE> Tags: NOT Hotdog, Upload date: 2017-07-08
  • <ANOTHER IMAGE> Tags: Hotdog, Upload date: 2017-07-07
  • ....

Anyone can upload images and our very smart Artificial Intelligence tags that image with HOTDOG or NOT-HOTDOG, then we save that image on the server and we also save upload date and tags in the database.

App Architecture

To make this app, let's assume we decided to have the following components:

  • NodeJS WebApp: (including static assets, frontend app, and API)
  • PHP Image Upload app - where we can make a POST request to save a photo on disk
  • MongoDB where we can store upload information (tags, upload date and etc)
  • PYTHON An Image Recognition service where we can make a POST request to know whether the image is a HOTDOG or NOT HOTDOG
+---------------------+
| |
| NodeJS Webapp |
| |
+---------------+------------+--------+-----------------+
| | |
| | |
| | |
| | |
| | |
+-------v-----------+ +----------v----------+ +-----------v---+
| | | | | |
| PHP File Uploader | | Python ImageDetector| | MongoDB |
| | | | | |
+-------------------+ +---------------------+ +---------------+

Persistence or Not

CapRover allows you to indicate whether your app/database/service has persistence data or not. Apps with persistence can have "persistent directories". These directories will be preserved if your app crashes and Captain starts a new instance of that app. All other directories will get wiped and reset to their default state if the application crashes and Captain starts a new instance of the app. In our example:

  • WebApp: DOES NOT have/need any persistence.
  • Image Upload App: Needs a persistent directory where images get saved on disk (for example, /uploaded_files)
  • MongoDB. Of course, this needs persistency (where we store information), we don't want to lose the database, just because our MongoDB crashed or our server got restarted.
  • PYTHON Image Recognition app. This one does not need to save any data on disk. It simply receives an image, does some image processing and let the client know whether the image was HOTDOG or NOT HOTDOG

Creating Services:

  • NodeJS Web app: after you write this app, you simply create a webapp and name it my-webapp on Captain, you DO NOT check the persistency checkbox and you deploy your app.
  • Image Upload app: similar to webapp described above, but we'll check the persistence checkbox when creating the app. Name this app image-uploader. After that, we go to app details page and add a persistent directory, the path of the directory is where your app stores images. This depends on your app, in our example, let's assume it is /uploaded_files
  • MongoDB: we'll use the one-click app installer to create an instance of MongoDB. We'll name this container my-mongodb. When the container (database) is created, you can go to the details page and you'll see that Captain automatically assigned some persistent directories to this container. This is where MongoDB saves its data.
  • Python Image Recognition app: Again, create a new app on Captain. We do not need to set persistence for this app as it does not save any information on the disk. Let's name this app image-processor.

Internal Access

Your web app needs to communicate with the MongoDB, image uploader, and image processor apps. Apps in the same CapRover cluster can use the target app name as the hostname. For example, connect to the app named my-mongodb from Node.js with:

mongoose.connect("mongodb://my-mongodb/mydatabase");

Of course, you can add username and password to the URI, see here for example.

The same rule applies to other services. For example, reach the image uploader app at http://imageuploader. Apps upgraded from CapRover releases before 1.15 can also use the legacy srv-captain--APP_NAME network alias.