[譯] 面向 React 和 Nginx 的 Docker 多階段構建

原文:progressivecoder.com/docker-mult…html

Docker 多階段構建(Multi-Stage) 是一種建立生產環境 Docker 鏡像的極佳途徑。前端

若是你是一位 Docker 新手,強烈推薦你先閱讀「理解 Docker 基礎」一文 (progressivecoder.com/understandi…)。另外一篇「從頭爲 NodeJS 應用建立 Dockerfile」 (progressivecoder.com/creating-a-…) 也頗有意思。vue

若你已經掌握了 Docker 基礎知識,就能夠跟隨如下每一步的細緻講解繼續閱讀了。node

1. 爲何要用 Docker 多階段構建?

Docker 多階段構建 是 Docker 17.05 版本開始纔有的一個相對較新的特性。多階段構建容許咱們將多個 FROM 語句放在同一個 Dockerfile 中。react

每條 FROM 指令均可以使用各自不一樣的基礎鏡像。每一個 FROM 語句也都標記了 Docker 構建過程當中一個新階段的開始。咱們能夠拷貝一個階段的產出物到另外一個階段,也能夠拋棄不須要的部分。nginx

基本上,在咱們不但願構建過程依賴項被拷貝到最終鏡像的狀況下這是個很是有用的特性。換句話說,Docker 多階段構建幫助咱們把鏡像變得更小了git

2. 開發和生產過程的區別

爲了演示 Docker 多階段構建,咱們將以一個 React 應用爲例github

下圖展現了要成功構建和運行一個 React 應用所須要完成的事情。web

Docker 多階段構建

如上所示,整個過程被分爲 構建階段運行階段vue-cli

在構建階段,咱們以 node:alpine 基礎鏡像開始。基本上,咱們要作的就是使用 NodeJS 安裝依賴項。最後,以生產環境爲目的使用 npm run build 構建應用。

今後刻起,構建階段就結束了。對於隨後開始的運行階段,使用 nginx 做爲基礎鏡像。而後,咱們將構建階段中 npm run build 命令的結果,也就是 構建產物(諸如 index.htmlmain.js 等文件),拷貝到 nginx 服務器目錄中。這時候,除了咱們拷貝的構建產物以外,構建階段產生的其它全部文件和目錄都將被拋棄,並不會歸入最終鏡像。

在最後一個步驟,咱們能夠啓動 nginx 以伺服 React 應用。

3. 創建 React 應用

先生成一個簡單的 React 應用。

要快速開始的話,咱們先安裝 create-react-app 包,它能夠快速生成一個 ReactJS 應用。如下面的命令全局安裝:

npm install -g create-react-app
複製代碼

一旦安裝完成,就能夠用其生成項目。在終端中進入想要創建項目的目錄,並執行如下命令。

create-react-app docker-react-app
複製代碼

這將建立一個名爲 docker-react-app 的應用,用於咱們的例子。

4. 建立多階段的 Dockerfile

如今能夠建立咱們的 Dockerfile 以支持多階段 Docker 構建過程了。 注意該文件要放置在項目根目錄下

react application dockerfile
供參考的項目目錄結構

接下來,在 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
複製代碼

下面詳細解釋這兩個階段。

構建階段

步驟 1 – 以 node:alpine 做爲基礎鏡像。同時咱們將該階段定名爲 builder。這將幫助咱們在其後引用這個階段。

步驟 2 – 接下來,爲應用指定工做目錄。這也是構建產物將要被建立的位置。

步驟 3 – 將 package.json 文件拷貝到工做目錄。npm 須要該文件以安裝所需依賴項。注意咱們只拷貝了 package.json 文件以確保對於隨後因爲代碼更改而發生的構建,不會使 docker 鏡像緩存失效(譯註:對於 COPY 和 ADD 命令,會計算鏡像內的文件和構建目錄文件的校驗和,而後作比較來判斷本層是否有改動;若是隻改了 src 的文件但依賴項沒變,就能夠利用這層的緩存從而加速構建)。

步驟 4 – 在下一步中,使用 npm install 命令安裝依賴項。也就是安裝了被 .dockerignore 忽略的 node_modules 目錄。

步驟 5 – 而後,將其它文件拷貝到工做目錄,也就是包含了應用真正代碼的那些文件。

步驟 6 – 下一步,執行 npm run build 命令。該命令將準備好 React 應用的生產環境構建產物。也就是說,該命令會生成用來伺服客戶端的 index.html 文件和 main.js 文件。

運行階段

步驟 1 – 以 nginx 基礎鏡像開始運行階段。Nginx 是一個很是流行的 web-server,是伺服靜態文件的理想工具。

步驟 2 – 接着,咱們從 builder 階段拷貝構建產物到 nginx 所需的位置。注意咱們經過 –from=builder tag 引用了 構建階段,並從構建階段的工做目錄拷貝了 /app/build

這樣咱們就完成了 Docker 多階段構建的 Dockerfile

這裏的一個重點是對於 nginx 不須要顯式的 RUN 命令。nginx 基礎鏡像自己會在 80 端口啓動 web-server(譯註:實際項目中明確寫好啓動命令仍是比較常見的,參考 github.com/tonylua/vue… )。

5. 測試 React 應用

爲了測試 React 應用,先如下面的命令,基於多階段 Dockerfile 構建一個鏡像:

docker build -t docker-react-app .
複製代碼

在第一次執行時這會費一點時間,由於全部的基礎鏡像和依賴項都會被下載。

一旦構建完成,運行下面的命令來運行它:

docker run -p 8080:80 docker-react-app
複製代碼

這裏基本就是運行了鏡像並將 nginx 的 80 端口映射到了咱們本機上的 8080 端口。

咱們沒在命令行窗口中看到太多可視化的輸出。可是,當咱們打開瀏覽器並訪問 http://localhost:8080 ,將看到如下 React 應用運行界面:

docker multi stage react app

總結

在本文中,咱們使用 Docker 多階段構建 過程成功運行了一個 Nginx server 上的 React 應用。

咱們將構建的過程分爲了構建階段和運行階段。應用在構建過程當中被建立後,將其產出拷貝到運行階段並拋棄無用的部分。這大大地減小了鏡像的整體積。



--End--

查看更多前端好文
請搜索 fewelife 關注公衆號

轉載請註明出處

相關文章
相關標籤/搜索