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