iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
DevOps

DevOps 好想學!新手也能打造雲端 Study Lab系列 第 29

Day29 - 以 NodeJS 留言板走過 GitOps 工作流程

前言

今天我們以開發者的角度,實際走過 GitOps 的工作流程,這次 Lab 準備了 NodeJS 留言板應用。

https://ithelp.ithome.com.tw/upload/images/20210928/20139235giBNQ1h918.png

建立 NodeJS 留言板專案

  1. 進入 Cloud Shell 網站

  2. 建立所需檔案

cd ~/project
mkdir models views
touch models/message.js views/index.js
  1. 安裝所需套件
npm install express path mongoose method-override dotenv ejs
  1. 點擊左上 Explorer -> Open Folder -> 選擇 project 資料夾 -> Open

  1. 在各檔案貼上以下內容
  • app.js
const express = require('express')
const path = require('path');
const mongoose = require('mongoose');
const methodOverride = require('method-override');
const Message = require('./models/message');
const app = express();
const port = 8080
require('dotenv').config()

const DATABASEURL= `mongodb://${process.env.MONGO_INITDB_ROOT_USERNAME}:${process.env.MONGO_INITDB_ROOT_PASSWORD}@${process.env.MONGO_HOST}:27017/message?authSource=admin`;

mongoose.connect(DATABASEURL,{
    useNewUrlParser: true,
    useUnifiedTopology: true
})
    .then(() => console.log('CONNECTION SUCCESS!!'))
    .catch(err => console.log(err));

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));


app.get('/', async (req, res) => {
    const messages = await Message.find({});
    res.render("index",{ messages });
})

app.post('/message', async (req, res) => {
    const message =  new Message(req.body.message);
    await message.save();
    res.redirect('/');
});

app.delete('/message/:id' , async (req,res) =>{
    const { id } = req.params;
    await Message.findByIdAndDelete(id);
    res.redirect('/');
});

app.listen(port, () => {
  console.log('Example app listening at port %s', port)
})
  • models/message.js
const mongoose = require("mongoose");

const messageSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    content: {
        type: String,
        required: true
    }
});

const Message = mongoose.model("Message", messageSchema);
module.exports = Message;
  • views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IT-Home Project</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz"
        crossorigin="anonymous">
</head>
<body style="background-color: #E8F0FE">
    <nav class="navbar bg-dark navbar-dark">
        <div class="container">
            <a href="#" class="navbar-brand"><i class="fas fa-comment-dots"></i> Message Board</a>
        </div>
    </nav>
    <section id="header" class="jumbotron text-center mt-4">
        <h1 class="display-3"> Ithome Message Board</h1>
    </section>
    <div class="container mt-4">
        <form action="/message" method="POST">
            <div class="row justify-content-md-center">
                    <div class="col-2 offset-1">
                        <input type="text" name="message[name]" class="form-control" placeholder="user" value="Anonymous" required>
                    </div>
                    <div class="col-6">
                        <input type="text" name="message[content]" class="form-control" placeholder="message" required>
                    </div>
                    <div class="col-2">
                        <button class="btn btn-primary">Send</button>
                    </div>
            </div>
        </form>
    </div>
    <div class="container mt-5">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th scope="col" width="20%">Name</th>
                    <th scope="col" width="70%">Message</th>
                    <th scope="col" width="10%"></th>
                </tr>
            </thead>
            <tbody id="teacherTable">
                <% for(let message of messages) { %>
                <tr>
                    <td><%= message.name %></td>
                    <td><%= message.content %></td>
                    <td>
                        <form class="d-inline" action="/message/<%= message.id %>?_method=DELETE" method="POST">
                            <button class="btn btn-danger">Delete</button>
                        </form>
                    </td>
                </tr>
                <% }%>
            </tbody>
        </table>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
</body>
</html>

完整的程式碼可以到 WebApp 查看。

專案建立完成後,可以在 dev 環境建立 MongoDB 測試應用。

  1. 使用 Docker 建立 MongoDB 容器
docker run -d -p 27017:27017 --name mongo \
    -e MONGO_INITDB_ROOT_USERNAME=localuser \
    -e MONGO_INITDB_ROOT_PASSWORD=localpasswd \
    mongo
  1. 執行 app.js
node app.js
  1. 在cloud shell點擊網頁預覽->透過以下通訊預覽 : 8080

在 Cloud Shell 測試專案可以成功運行。

https://ithelp.ithome.com.tw/upload/images/20210928/20139235fuiCQYSSAE.png

上傳到 Git 完成測試與部屬

當專案完成準備進入部屬環境,開發者就可以上傳到 Git Repo ,並建立 Merge Request 來觸發 CI/CD Pipeline 。

  1. 建立 Commit 並 Push 到 Git Repo
git checkout dev
git add .
git commit -m "add message board"
git push origin dev
  1. 在 GitLab 上建立 Merge Request ,等待測試 Pipeline 完成後按下 Merge

https://ithelp.ithome.com.tw/upload/images/20210929/20139235LW6QUQPenY.png

  1. 等待 Pipeline 完成後, ArgoCD 就會將專案部屬到 Stage 環境

https://ithelp.ithome.com.tw/upload/images/20210929/20139235MZYPXfbRjS.png

https://ithelp.ithome.com.tw/upload/images/20210929/20139235vry3ZVO4uA.png

  1. Stage 環境測試完成後,就可以在 Pipeline 觸發 prod-deploy ,專案就會部屬到 Prod 環境。

https://ithelp.ithome.com.tw/upload/images/20210929/201392352JW3ybYwCF.png

https://ithelp.ithome.com.tw/upload/images/20210929/20139235Rqm3gyGf0s.png

總結

DevOps 的核心目標是讓開發完成到部屬的交付時間變得更迅速,透過 CI/CD Pipeline 將部屬工作自動化,開發者只需要將程式碼上傳,就能迅速完成部屬工作。


上一篇
Day28 - 開發者的環境變數設置
下一篇
Day30 - 雲端 Study Lab 總結,清除 GCP 專案
系列文
DevOps 好想學!新手也能打造雲端 Study Lab30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言