[微服務] Docker基礎(7) - 讓Docker進入實務的專案(一)

前言

我們會用到前六篇文章的內容,創造一個真實實務的Docker體系,包含

  • 開發
  • 測試
  • 部屬

工具

在這個實務專案我們會用到

  • GitHub
    • 包含master和feature觀念
  • Travis CI
    • 由GitHub提供的CI工具
  • AWS
    • 我們會將AWS的服務當作最終生產環境
  • React
    • 我們只單純的使用React的初始APP不會做太多的React Code主要是要看到他的畫面

流程

Dev

  • 創建/更新code 在feature branch中
  • 將code merge到master中

Test

  • 將code push到Travis CI中
  • 測試程式碼

Prod

  • 將PR merge進master中
  • 測試
  • 部屬到AWS Beanstalk中

Docker 在哪?

其實我們並不會真的使用到Docker,我們只會用Docker讓這過程變得簡單

開始開發環境

開始前知識

  • npm run start
    • 啟動react app可以馬上看到畫面
  • npm run test
    • 執行單元測試
  • npm run build
    • 將分散的js包裝成一個js檔,通常開發完放上生產環境就是這包js

為何要選擇ract而不是python?java原因很簡單,npm比較方便

建立React專案

只要找到目標資料夾,輸入

npx create-react-app my-app

就可以看到我們React app專案建好了,接下來的操作都會在這個資料夾的根目錄進行操作

創立Dockerfile

這個環節的Dockerfile我們會加上.dev,為了強調這是在開發環境時的Dockerfile,所以裡面的Image配置也會是以開發環境為主

Dockerfile.dev

FROM node:alpine

WORKDIR '/app'

COPY package.json .
RUN npm install

COPY . .

CMD  ["npm", "run", "start"]

這裡我們呼叫的docker build .必須做一點小小的改變

docker build -f Dockerfile.dev .

告訴docker我們要他依照有.dev的版本去創建image

啟動

使用

docker run -p 3000:3000 image-id

我們就可以看到我們範例的react app可以透過瀏覽器使用了

Volume

如同port的映射,Volume的變數就是將本機的File映射到Docker File體系中。

作為範例我們改掉src/App.js中的p標籤中的字串,改成hi there

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          Hi there!
        </p>
      </div>
    );
  }
}

export default App;

在將之前啟動的指令改為

docker run -p 3000:3000 -v $(pwd):/app image-id

啟動後我們可以看到web app中的內容已經跟著改變,不需要重新build一次image

指令好複雜好麻煩- Docker compose

docker-compose.yml

version: '3'
services:
    web:
        build:
            context: .
            dockerfile: Dockerfile.dev
        ports:
            - "3000:3000"
        volumes: 
            - /app/node_modules
            - .:/app
  • build變數的拆解
    • context:告訴docker-compose要build檔案(環境) 這邊我們直接取目前目錄(docker-compose所在的目錄)
    • dockerfile:告訴docker-compse要以哪個dockerfile作為image的設定檔
  • volumes
    • 我們排除掉了node_modules (因為沒有聲明本機的modules資料夾所以不會做映射),為什麼要排除?因為modules只是我們開發過程的工具,在最後start或build時並不會真的參與

在我們的資料夾下加上了這個docker-compose.yml後就可以輕鬆的docker-compose up了

開始測試

之前透過busybox有嘗試過在container run指令後增加command line指令,讓container執行,

docker run -it image-id npm run test

這樣我們在啟動conatiner時,就可以同步測試了。

建立生產環境

生產環境和開發環境最大的差別在於我們會以Nginx當作server,所以在這環節我們會多了如何讓Nginx進入Docker並且將我們的build裡面的內容放置於Ngnix中

下圖是我們要做的事情

我們只需要在專案根目錄新增一個Dockerfile就好,這次不需要再加上.dev因為這是我們生產環境要使用的Dockerfile

FROM node:alpine as builder

WORKDIR '/app'

COPY package.json .
RUN npm install

COPY . .
RUN npm run build

FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html

可以看到前面的設定都跟開發環境一至,差別在於我們需要讓第一個container執行build產出生產結果,並且將結過複製到nginx的server之中,新增完dockerfile之後啟動就好了

docker run -p 8080:80 image-id

nginx沒有啟動的log所以我們直接到我們的8080 port去看就可以看到結果

總結

Docker實務開發有分上下兩級,這一級我們介紹了基本的開發環境Docker的設定,在後面我們引入了Nginx當作生產環境,下一集會介紹如何將GitHub CI和AWS引入近來。

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

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