[Express+Vue 搭建電商網站] 22 專案容器化 - 後端

專案 Docker 容器化-後端

後端容器化

前端容器化之後,接著準備進行後端的容器化。首先把寫死的 MongoDB 連線字串透過環境變數注入,修改 server/app.js 連線資料庫的部分成

mongoose.connect(process.env.MONGO_URI || `mongodb://localhost:27017/test`);

接著一樣新建 server/Dockerfile

FROM node:10
# 指定工作目錄為 /usr/src/app,接下来的指令全部在這個路徑下操作
WORKDIR /usr/src/app
# 將 package.json 複製到根目錄
COPY package*.json ./
# 安裝 npm 依賴
RUN npm install
# 複製全部程式內容
COPY . .
# 設定環境變數
ENV NODE_ENV=production
ENV MONGO_URI=mongodb://db:27017/test
ENV HOST=0.0.0.0
ENV PORT=3000
# 曝露出 3000 port
EXPOSE 3000
# 設定映像檔內執行的指令
CMD ["npm", "start"]

和前端一樣建立 server/.dockerignore 確定不會把 node_modules 給映射進容器裡
裡面也只有一行:

node_modules

Docker Compose

Docker Compose 可以讓我們很好的管理 docker 容器,只需要透過一個 YAML 檔就可以修改設定。
在專案的根目錄下建立(跟 client 和 server 兩個資料夾同層)docker-compose.yml

version: '3'
services: 
 db:
 image: mongo
 restart: always
 api:
 build: server
 restart: always
 ports:
 - 3000:3000
 nginx:
 build: client
 restart: always
 ports:
 - 8080:80

可以看到我們建立了三個 service,對應到前面說的 dbapinginx

  • db:指定使用 mongo 映像檔,然後當服務意外停止則總是重啟
  • api:映像檔透過 server 資料夾內來建立,對外 port 為 3000:3000
  • nginx:映像檔透過 client 資料夾內來建立,對外 port 為 8080:80,外部的 8080 port 會指向到內部 80 port

如果 docker-compose.yml 中的 service 使用 image 指定映像檔,則會去Docker Hub 上拉回指定的映像檔。若是使用 build 則會根據指定目錄下的 Dockerfile 來建立映像檔。
接著就是測試的時間!打開 Docker 之後,在終端機輸入

docker-compose up --build

第一次執行會多花一些時間,因為先前提過的要從Docker Hub 上拉回指定的映像檔,如下圖
docker_container.md
可以藉由

docker ps

來觀察目前所有的容器狀態,看起來沒問題的話就可以開啟 localhost:8080 來看看專案是不是跟原本一樣

MongoDB 身份驗證

在之前的設定中我們的 MongoDB 資料庫並沒定任何身份驗證,所以任何人只要能夠發送請求到資料庫都可以對資料庫做修改,這是一個可怕的資安問題!接著我們要來搞定 MongoDB 的身份驗證,增加系統的安全性

修改 MongoDB 連線設定

打開 server/app.js,修改連線資料庫的部分成以下

ongoose.connect(process.env.MONGO_URI || `mongodb://localhost:27017/test`, {
 useNewUrlParser: true,
 useUnifiedTopology: true,
 user: process.env.MONGO_USER,
 pass: process.env.MONGO_PASSWORD,
});

這代表

  • useNewUrlParser:使用新的 MongoDB 驅動 URL 解析器
  • useUnifiedTopology:使用新的連線管理引擎,支持重新連線,這樣可以大大提升連線穩定性
  • user:連線的使用者名稱,通過環境變數注入
  • pass:連線使用的密碼,通過環境變數注入

Dockerfile 中注入環境變數

server/Dockerfile 中加入下面的環境變數:

ENV NODE_ENV=production
ENV MONGO_URI=mongodb://db:27017/admin
ENV MONGO_USER=mongoadmin
ENV MONGO_PASSWORD=secret
ENV HOST=0.0.0.0
ENV PORT=3000

可以發現一些不同的地方,調整了 MONGO_URI,把預設的 test 換成 admin,這是為了啟用驗證功能並且
使用 admin 作為 Authentication Database 的使用者。

設定 Docker Compose 預設密碼

接著在 docker-compose.yml 裡面幫 db 服務加入預設密碼的環境變數

db:
 image: mongo
 restart: always
 environment:
 MONGO_INITDB_ROOT_USERNAME: mongoadmin
 MONGO_INITDB_ROOT_PASSWORD: secret

測試

首先使用

docker-compose down --volumes

不只關閉了原本運行中的 docker 容器,還透過 --volumes 把原本的建立 MongoDB 的容器徹底刪除。若不這麼做,之後重啟容器會跳過初始化使用者的過程,這樣我們的驗證資料庫就沒辦法被建立,會複用之前的資料
接著重新啟動容器

docker-compose up --build

應該會看到網頁一切正常,不過資料庫已經有了驗證,不是「裸奔」的狀態了

留言