Set up Google Cloud Platform + MEAN stack in 5mins

I believe in Google products, so it’s thus quite naturally that I use Google Cloud Platform to host my websites, apps, etc. GCP proposes a lot of pre-configured images for all your needs: blog, os, database, crm, or developer tools and infra like:

  • Jenkins
  • GitLab
  • Trac
  • NodeJS
  • MEAN
  • MySQL
  • Ruby
  • Cassandra

Images are delivered with all the tools you need to work efficiently! For example, the MEAN stack came with MongoDB, NodeJS, Express, Git, etc.

Well 🙂

But, a little configuration is needed to make your app listening on your custom port (3000 for example)

Steps

  1. Launch your server SSH console from Google Cloud Platform (Bitnami)
  2. Clone the project under /home/user/apps/
  3. Open up port 3000 in your Google Compute Network Firewall : Your VMs > Edit > Network > Click on default network_google_clud_mean_settingup
  4. Launch your own project on port 3000 (using your favorite grunt/node server command) and test if http://SERVER_IP:3000 works ? If it’s OK, go to step 5
  5. Edit the file opt/bitnami/apache2/conf/bitnami/bitnami.conf and replace the content with the configuration below (it’s only a proxy pass to route your server to the 3000 port)

Virtual Host Configuration

    <IfVersion < 2.3 >
      NameVirtualHost *:80
      NameVirtualHost *:443
    </IfVersion>

    <VirtualHost _default_:80>
    #  DocumentRoot "/opt/bitnami/apache2/htdocs"
    #  <Directory "/opt/bitnami/apache2/htdocs">
    #    Options FollowSymLinks MultiViews
    #    AddLanguage en en
    #    LanguagePriority en
    #    ForceLanguagePriority Prefer Fallback

    #    AllowOverride All
    #    <IfVersion < 2.3 >
    #      Order allow,deny                          
    #      Allow from all
    #    </IfVersion>
    #    <IfVersion >= 2.3 >
    #      Require all granted
    #    </IfVersion>
    #  </Directory>

    # Error Documents
      ErrorDocument 503 /503.html

    # Bitnami applications installed with a prefix URL (default)
    #  Include "/opt/bitnami/apache2/conf/bitnami/bitnami-apps-prefix.conf"

    # Redirect to port 3000 (proxy pass)
      ServerAdmin youremail@gmail.com
      ServerName yourservername.fr
      ProxyPass / http://localhost:3000/
      ProxyPassReverse / http://localhost:3000/
      ProxyPreserveHost On

    </VirtualHost>

    # Default SSL Virtual Host configuration.

    <IfModule !ssl_module>
      LoadModule ssl_module modules/mod_ssl.so
    </IfModule>

    Listen 443
    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder on
    SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !EDH !RC4"
    SSLPassPhraseDialog  builtin
    SSLSessionCache "shmcb:/opt/bitnami/apache2/logs/ssl_scache(512000)"
    SSLSessionCacheTimeout  300

    <VirtualHost _default_:443>
      DocumentRoot "/opt/bitnami/apache2/htdocs"
      SSLEngine on
    SSLCertificateFile "/opt/bitnami/apache2/conf/server.crt"
    SSLCertificateKeyFile "/opt/bitnami/apache2/conf/server.key"

      <Directory "/opt/bitnami/apache2/htdocs">
        Options FollowSymLinks MultiViews
        AddLanguage en en
        LanguagePriority en
        ForceLanguagePriority Prefer Fallback
        AllowOverride All
        <IfVersion < 2.3 >
          Order allow,deny                          
          Allow from all
        </IfVersion>
        <IfVersion >= 2.3 >
          Require all granted
        </IfVersion>
      </Directory>
      # Error Documents
      ErrorDocument 503 /503.html

      # Bitnami applications installed with a prefix URL (default)
      Include "/opt/bitnami/apache2/conf/bitnami/bitnami-apps-prefix.conf"
    </VirtualHost>
    # Bitnami applications that uses virtual host configuration
    Include "/opt/bitnami/apache2/conf/bitnami/bitnami-apps-vhosts.conf"
    # Status
    ExtendedStatus on
    <VirtualHost _default_:80>
    ServerName local-stackdriver-agent.stackdriver.com
    <Location /server-status>
      SetHandler server-status
      Order deny,allow
      Deny from all
      Allow from 127.0.0.1
    </Location>
    </VirtualHost>
  1. Restart apache with this command sudo /opt/bitnami/ctlscript.sh restart apache
  2. Now check your server IP in your favorite browser (chrome probably?), and your project should run there.

L’équivalent du SELECT (SQL) sur une base de données MongoDB (NoSQL)

La particularité des bases de données “non structurées” ou “orientée documents” comme MongoDB, c’est quelles sont très performantes pour de gros volumes de données (en particulier depuis l’arrivée de tous ces objets connectés).

Pour faire un petit tour d’horizon des bases de données NoSQL actuellement sur le marché (> 225 fin décembre 2015), rendez-vous sur le site http://nosql-database.org/ qui dispose d’une liste à peu près complète des produits du marché.

Je vais montrer l’équivalent (ou plutôt les deux équivalents) de mongoDB par rapport au SELECT qui est une des requêtes de base du SQL.

SQL

Structure d’un SGBD SQL

SGBD > Database > Table >Entrées (lignes)

Capture d’écran 2015-12-20 à 13.08.24

Exemple de Select

Pour rappel, la requête basique pour sélectionner le nom, prénom et l’age des utilisateurs ayant comme ville Paris en SQL :

[sql]
SELECT nom, prenom, age
FROM users
WHERE ville="Paris"
[/sql]

MONGODB

Structure d’un SGBD NoSQL

SGBD > Database > Collections > Documents

Capture d’écran 2015-12-20 à 13.09.46

db.collection.find(query, projection)

Le premier paramètre de la fonction find() est un objet au format JSON qui va permettre de filtrer les résultats (un peu comme le where en SQL). Le second paramètre permet de retourner seulement certains champs, il est donc similaire aux valeurs qui suivent le mot clé SELECT en SQL. On peut également ajouter des conditions comme supérieur à, inférieur ou égal à, etc…

  • $gt = supérieur à
  • $lt = inférieur à
  • $gte = supérieur ou égal à
  • $lte = inférieur ou égal à

Quelques exemples :

[javascript]
// All
var res = db.users.find( );

// Paris as city
var res = db.users.find( { ville: "Paris" } );

// Older than…
var res = db.users.find( { ville: "Paris", age: { $gte:20 } } );

// Don’t return all dataset, only the name
var res = db.users.find( { ville: "Paris" }, { name: true } );

// Same as findOne()
var res = db.users.find( { nom: "Bronner", prenom: "Joey" }).limit(1);
[/javascript]

db.collection.findOne(query, projection)

La requête findOne() est différente puisqu’une fois exécutée, elle va retourner les données et fermer le curseur. Au contraire de la requête find() (même en utilisant la syntaxe find().limit(1)) qui retourne un curseur. Il faut également savoir que sans argument, findOne() retourne un document quelconque de la collection. Ce type de requête sans argument peut donc être utilisé pour constater la structure des documents.

[javascript]
// All
var res = db.users.findOne( { nom: "Bronner", prenom: "Joey" });
[/javascript]

Il n’y a pas grand chose à ajouter, c’est simple comme bonjour. Ah si j’oubliais, si vous êtes en train de faire ou refaire votre CV et que vous n’avez pas de compétences avancées en SQL, mettez que vous êtes expert en NoSQL 🙂

nosql-expert