Ce tutoriel va mettre en lumière la "dockerisation", terme barbare pour démontrer en quelques lignes de commande, comment créer une application NuxtJS et la transformer en containeurs, facilement déployable sur n'importe quelle plate-forme.

Ainsi depuis un MacBook sur le terminal, nous allons commencer par installer NuxtJS et créer notre application.

Pré-requis :

  • Un MacBook
  • NPM
  • NodeJS
  • NuxtJS
  • Docker
  • NPX

Installation

On débute en installant NuxtJS depuis NPM, le gestionnaire de paquet NodeJS

npm install nuxt

Assurez-vous que npx est installé (npx est livré par défaut depuis npm 5.2.0)  

npx create-nuxt-app <mon-projet> 

Ou avec Yarn:  

yarn create nuxt-app <mon-projet>

Cette commande appliquée à votre terminal va générer cette réponse :

npx : 402 installé(s) en 14.984s
> Generating Nuxt.js project in /Users/admin/my-project
? Project name my-project
? Project description My badass Nuxt.js project
? Use a custom server framework koa
? Use a custom UI framework bulma
? Choose rendering mode Universal
? Use axios module no
? Use eslint no
? Use prettier no
? Author name Gsagnard26
? Choose a package manager npm
Dépôt Git vide initialisé dans /Users/admin/my-project/.git/

Sauf, que ce sont vos réponses qui figureront évidemment dans le rendu final, Npx va vous demander lors de la création de l'app NuxtJS :

  • le nom du projet,
  • quel framework utiliserez-vous (express, Koa etc...)
  • quel css ?
  • quels modules ?

Et une fois le travail achevé :

> nodemon@1.18.9 postinstall /Users/admin/my-project/node_modules/nodemon
> node bin/postinstall || exit 0


> nuxt@2.3.4 postinstall /Users/admin/my-project/node_modules/nuxt
> opencollective || exit 0


                                     :=.
                                    -=+=:   :-
                                  .-=+++=: :++=.
                                 .-+++++++=++++=.
                                .=+++++++****++++.
                               :=+++++++******++*+:
                              :=+++++++********++*+:
                             :=+++++++**********++*+-
                            -=+++++++*************+*+-.
                          .-=======+**************++++=.
                          .........::::::::::::::::::::.

                         Thanks for installing nuxtjs 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.

                            Number of contributors: 30
                              Number of backers: 138
                            Annual budget: 31 273 $US
                            Current balance: 7 639 $US

           👉  Donate: https://opencollective.com/nuxtjs/donate

npm notice created a lockfile as package-lock.json. You should commit this file.
added 1055 packages from 511 contributors and audited 13841 packages in 21.044s
found 0 vulnerabilities


  To get started:

    cd my-project
    npm run dev

  To build & start for production:

    cd my-project
    npm run build
    npm start

On suit donc les consignes données en se plaçant à la racine du projet :

cd my-project

Et on teste l'app en local avec npm :

npm run dev

On obtient alors le résultat suivant sur notre navigateur :

==> Docker

Nous allons à présent ajouter un fichier Dockerfile à notre projet afin de pouvoir construire et utiliser une image Docker de notre app. Pour cela appliquer le code suivant :

FROM node:8.9.1

RUN mkdir -p /app
COPY . /app
WORKDIR /app

COPY package.json /app
COPY package-lock.json /app
RUN npm install

ENV NODE_ENV=production

COPY . /app
RUN npm run build

ENV HOST 0.0.0.0
EXPOSE 3000
CMD ["npm", "start"]

Une fois le fichier Dockerfile crée à la racine du projet :

MBP-de-admin:my-project admin$ ls
Dockerfile		components		node_modules		package.json		server
README.md		layouts			nuxt.config.js		pages			static
assets			middleware		package-lock.json	plugins			store

...Vous allez utiliser la commande "docker build" pour construire l'image de notre app, puis vous pourrez allez vous servir un petit café pendant que celle-ci se "builde"

MBP-de-admin:my-project admin$ sudo docker build -t my-project .
Sending build context to Docker daemon  95.21MB
Step 1/13 : FROM node:8.9.1
 ---> 1934b0b038d1
Step 2/13 : RUN mkdir -p /app
 ---> Using cache
 ---> aceb16501d62
Step 3/13 : COPY . /app
 ---> e599de31f8c9
Step 4/13 : WORKDIR /app
 ---> Running in 06cddfc41bcb
Removing intermediate container 06cddfc41bcb
 ---> 7e7e1b2232f4
Step 5/13 : COPY package.json /app
 ---> 627c68a2e4d1
Step 6/13 : COPY package-lock.json /app
 ---> 3f2765c1cdbd
Step 7/13 : RUN npm install
 ---> Running in 177902d219d1
up to date in 5.115s
Removing intermediate container 177902d219d1
 ---> 6ed0c823a2a7
Step 8/13 : ENV NODE_ENV=production
 ---> Running in 3699b59577c7
Removing intermediate container 3699b59577c7
 ---> e62deb388942
Step 9/13 : COPY . /app
 ---> 2cdf89610e11
Step 10/13 : RUN npm run build
 ---> Running in 10d4a8e4de6f

> my-project@1.0.0 build /app
> nuxt build

ℹ Production build                                                    12:08:33
✔ Builder initialized                                                 12:08:33
✔ Nuxt files generated                                                12:08:33
ℹ Compiling Client                                         webpackbar 12:08:34
✔ Client: Compiled successfully in 9.95s                   webpackbar 12:08:44
ℹ Compiling Server                                         webpackbar 12:08:44
✔ Server: Compiled successfully in 3.04s                   webpackbar 12:08:47

Hash: 39fa940b4a2cf998d7dd
Version: webpack 4.28.1
Time: 9953ms
Built at: 2018-12-22 12:08:44
                  Asset       Size  Chunks             Chunk Names
07bd3334f3b8b4c23ecf.js    168 KiB       4  [emitted]  vendors.app
28fb0aed8cd0ef31d61e.js   2.15 KiB       3  [emitted]  runtime
4e06b4603355206a38d9.js   3.59 KiB       2  [emitted]  pages/index
               LICENSES  426 bytes          [emitted]
c683cb34292359509c4a.js    140 KiB       1  [emitted]  commons.app
cb22fc48ffa2767c62b4.js   27.7 KiB       0  [emitted]  app
 + 3 hidden assets
Entrypoint app = 28fb0aed8cd0ef31d61e.js c683cb34292359509c4a.js 07bd3334f3b8b4c23ecf.js cb22fc48ffa2767c62b4.js

Hash: 3c26c37a604cc30a0ab6
Version: webpack 4.28.1
Time: 3038ms
Built at: 2018-12-22 12:08:47
             Asset     Size  Chunks             Chunk Names
server-bundle.json  580 KiB          [emitted]
Entrypoint app = server-bundle.js
Removing intermediate container 10d4a8e4de6f
 ---> 453c697300cf
Step 11/13 : ENV HOST 0.0.0.0
 ---> Running in 0acced1bf59a
Removing intermediate container 0acced1bf59a
 ---> caed31bca7ba
Step 12/13 : EXPOSE 3000
 ---> Running in 53a2875bbab1
Removing intermediate container 53a2875bbab1
 ---> 9d2bc132fb6e
Step 13/13 : CMD ["npm", "start"]
 ---> Running in 38e8bf48cb94
Removing intermediate container 38e8bf48cb94
 ---> 0b4ba257bb94
Successfully built 0b4ba257bb94
Successfully tagged my-project:latest

Ok, nous avons désormais une application NuxtJS fonctionnelle localement, en partie Dockerisée (build), reste à la tester localement via Docker avant d'envisager la création d'un repository Github et/ou un dépôt sur le Docker Hub. On utilise donc la commande docker run pour tester l'image localement :

MBP-de-admin:my-project admin$ sudo docker run -it -p 3000:3000 my-project:latest
Password:

> my-project@1.0.0 start /app
> cross-env NODE_ENV=production node server/index.js


 READY  Server listening on http://0.0.0.0:3000                                                                                    12:15:54

Ce qui nous donne sur l'adresse http://localhost:3000

Super notre image est fonctionnelle ! Attaquons désormais à la création de notre repository avec .git

Git --> Github repo

On commence par créer un repository vide sur Github via l'interface web de votre compte comme ceci :

Une fois ceci fait, vous allez vous placer à la racine de votre projet et appliquer la liste de commandes suivantes :

MBP-de-admin:my-project admin$ git init
Dépôt Git existant réinitialisé dans /Users/admin/my-project/.git/
MBP-de-admin:my-project admin$ echo "node_modules" > .gitignore
MBP-de-admin:my-project admin$ git add .
MBP-de-admin:my-project admin$ git commit -m "Initial commit"
[master (commit racine) de97b24] Initial commit
 37 files changed, 11441 insertions(+)
 create mode 100644 .editorconfig
 create mode 100644 .gitignore
 create mode 100644 .nuxt/App.js
 create mode 100644 .nuxt/client.js
 create mode 100644 .nuxt/components/no-ssr.js
 create mode 100644 .nuxt/components/nuxt-child.js
 create mode 100644 .nuxt/components/nuxt-error.vue
 create mode 100644 .nuxt/components/nuxt-link.js
 create mode 100644 .nuxt/components/nuxt-loading.vue
 create mode 100644 .nuxt/components/nuxt.js
 create mode 100644 .nuxt/empty.js
 create mode 100644 .nuxt/index.js
 create mode 100644 .nuxt/loading.html
 create mode 100644 .nuxt/middleware.js
 create mode 100644 .nuxt/router.js
 create mode 100644 .nuxt/server.js
 create mode 100644 .nuxt/utils.js
 create mode 100644 .nuxt/views/app.template.html
 create mode 100644 .nuxt/views/error.html
 create mode 100644 Dockerfile
 create mode 100644 README.md
 create mode 100644 assets/README.md
 create mode 100644 components/Logo.vue
 create mode 100644 components/README.md
 create mode 100644 layouts/README.md
 create mode 100644 layouts/default.vue
 create mode 100644 middleware/README.md
 create mode 100644 nuxt.config.js
 create mode 100644 package-lock.json
 create mode 100644 package.json
 create mode 100644 pages/README.md
 create mode 100644 pages/index.vue
 create mode 100644 plugins/README.md
 create mode 100644 server/index.js
 create mode 100644 static/README.md
 create mode 100644 static/favicon.ico
 create mode 100644 store/README.md

Après quoi il va falloir peupler le dossier git :

MBP-de-admin:my-project admin$ git remote add origin https://github.com/gabrielsagnard/nuxtapp-docker.git
MBP-de-admin:my-project admin$ git push -u origin master
Énumération des objets: 51, fait.
Décompte des objets: 100% (51/51), fait.
Compression par delta en utilisant jusqu'à 8 fils d'exécution
Compression des objets: 100% (45/45), fait.
Écriture des objets: 100% (51/51), 111.19 KiB | 7.41 MiB/s, fait.
Total 51 (delta 3), réutilisés 0 (delta 0)
remote: Resolving deltas: 100% (3/3), done.
To https://github.com/gabrielsagnard/nuxtapp-docker.git
 * [new branch]      master -> master
La branche 'master' est paramétrée pour suivre la branche distante 'master' depuis 'origin'.

Et vous devriez désormais trouver votre repository rempli :

Test de l'application en production sur un VPS

Déploiement

Nous allons désormais déployer notre application en externe sur un VPS accessible sur le web. Pour cela nous allons avoir besoin d'un fichier docker-compose.yml afin de rendre le déploiement optimal et fonctionnel, en voici un exemple :

version: "3"

services:
  nuxt:
    build: ./app/
    container_name: nuxt
    restart: always
    ports:
      - "3000:3000"
    command:
      "npm run start"

  nginx:
    image: nginx:1.15
    container_name: ngx
    ports:
      - "80:80"
    volumes:
      - ./nginx:/etc/nginx/conf.d
    depends_on:
      - nuxt

Une fois ceci fait nous allons lancer le déploiement sur notre VPS, on s'y connecte depuis ssh sur notre machine de développement et on lance la commande suivante depuis la racine du dossier (repository) de votre application, que vous aurez clonée au préalable évidemment (git clone) :

docker-compose build && docker-compose up -d

Et là magie, à l'adresse IP de votre VPS :

Monitoring

Et pour couronner le tout, on balance un DockProm pour monitorer :

git clone https://github.com/stefanprodan/dockprom

cd dockprom

Attention, Grafana est paramétré sur le port 3000, ce qui est également le cas de notre application NuxtJS, je vous conseille donc de modifier le port d'écoute de celle-ci dans le fichier docker-compose.yml, vers le port 4000 par exemple afin que les deux ne se chevauchent pas.

Puis on lance :

ADMIN_USER=admin ADMIN_PASSWORD=admin docker-compose up -d

Creating nodeexporter ...
Creating prometheus   ...
Creating alertmanager ...
Creating nodeexporter ... done
Creating prometheus   ... done
Creating alertmanager ... done
Creating cadvisor     ...
Creating pushgateway  ... done
Creating grafana      ... done
Creating cadvisor     ... done

Et on en prend comme d'habitude, plein les yeux :

Have fun !

Biblio :