[微服務] Docker基礎(6) - 使用Docker compose加速我們容器運作

前言

我們會透過一個簡單的NodeJS web app搭配redis no-SQL資料庫做為範例,並且透過docker compose加速我們的Docker流程

範例介紹

初步的Node app原始碼如下
記得先開一個專屬的app資料夾,要在此資料夾呼叫docker build
index.js

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient();
client.set('visits', 0);
app.get('/', (req, res) => {
    client.get('visits', (err, visits) => {
        res.send('Number of visits is ' + visits);
        client.set('visits', parseInt(visits) + 1);
    })
})

app.listen(8081, () => {
    console.log('Listening on prot 8081');
})

package.json

{
    "dependencies": {
        "express": "*",
        "redis": "2.8.0"
    },
    "scripts": {
        "start": "node index.js"
    }
}

Dockerfile

FROM node:alpine

WORKDIR '/app'

COPY package.json .
RUN npm install
COPY . .

CMD ["npm", "start"]

啟動docker build . 拿到image id後再使用 docker run image-id啟動容器,會發現我們沒有redis-server

docker run redis

如果不想開另外的視窗做操作的話,可以使用run -d指令讓container在背景模式下啟動

建立好我們的redis container後再次啟動我們客製化的容器,

會發現還是不能使用redis,因為我們的容器之間還沒有設定溝通橋梁

建立Container的溝通橋樑

建立Container附加指令或屬性的方法有兩種

  • 最基本的,慢慢使用Docker CLI做設定
  • 使用Docker compose直接寫個yml檔並且一鍵啟動

甚麼是 Docker Compose

  • 可以將個別的Docker CLI指令封裝在yml設定檔中
  • 可以用簡單的Docker Compose指令啟動設定檔中的Docker CLI
  • 可以不用重複重複的設定每個port volume之類的屬性

使用Docker Compose操控我們的小專案

第一步我們希望Docker Compose可以將我們剛剛包裝啟動Docker container的流程簡化
我們將

docker build -t 你的名稱/image名稱:版本
docker run -p 本機port:容器port image名稱或ID
docker run redis

初版docker-compose.yml

包裝成一個初版docker-compose.yml檔案,整個docker-compose.yml會像下方一樣

version:  '3'
services: 
    redis-server:
        image: 'redis'
    node-app:
        build: .
        ports:
            - "4001:8081"
  • version是目前使用的docker-compose版本
  • services是此設定檔有哪些服務
    • redis-server (自己取名)
      • image才是真正要從docker hub拿下來的關鍵 (redis)
    • node-app (自己取名)
      • build就是單純的docker build .
      • port則為我們要將本機和容器間的port做映射 (之前文章提到盡量讓不常用的port和容器做映射,所以用4001)

container間的網路連接

更改我們的index.js連結

幫我們的redis增加網路連結的資訊,替我們的index.js redisClient增加host和port屬性

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
    host: 'redis-server',
    port: 6379
});
client.set('visits', 0);
app.get('/', (req, res) => {
    client.get('visits', (err, visits) => {
        res.send('Number of visits is ' + visits);
        client.set('visits', parseInt(visits) + 1);
    })
})

app.listen(8081, () => {
    console.log('Listening on prot 8081');
})

Docker可以根據docker-compose的設定自動判別’redis-server’,而port設定redis預設的6379 port

嘗試啟動docker-compose

若是沒有要重新build Node app的話直接使用第一個指令,如果有異動程式邏輯則使用第二個,docker-compose會幫你執行設定檔寫的build指令

  • docker-compose up
    • 就是使用docker run啟動每個services中的服務
  • docker-conpose up --build
    • 包含呼叫yml裡設定的build指令

記得只要在up指令後增加-d屬性就可以讓他在背景跑了

  • docker-compose up -d

輸入指令後就可以看到我們簡單的Node app和redis的小應用了

關閉docker-compose裡面的全部容器

  • docker-comopse down

此指令會將整個docker-compose裡的services都關閉

總結

這篇文章用一個超簡易的Node app搭配redis讓讀者嘗試使用docker-compose功能,
其實docker-compose就只是將繁瑣的docker CLI包裝成yml檔然後再透過他的指令啟動。

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)