用前端姿式玩docker【四】基於docker快速構建webpack的開發與生產環境

目錄

前言

關於docker構建前端環境,相關的坑點與難點,基本上都在這兒了,不少都是我的嘗試總結的經驗,都是從小白過來的,但願能幫助你們快速解決一些問題,拋開前端環境來看,差很少點的鏡像基本也夠用了。反而前端對易用性的要求更高(前端開發人員可不是每天跟linux打交道),還須要考慮類unix系統與windows的差別化問題,這點會在下一篇文章中重點說明。html

打賞啥的也不須要,若是能夠,很感激能在github上給個小星星,github入口在 博客最頂部前端

回顧

以前也說過 docker對於前端而言組重要的兩個優點:node

  1. 工做環境的快速構建
  2. 工做環境的統一
    因此利用docker的工程化工做流在想象中應該是這樣的:
    例如一個新人從0到1構建前端環境: 安裝docker => 拉取鏡像 => 根據環境(dev、build)的不一樣傳入不一樣的環境變量運行相應的容器 至此ok,易用性作到位以後,整一個開發環境基本至關因而在安裝軟件,這樣基本上就很香了。

難點與坑點

如下主要分享一下過程中出現的比較坑或比較重要的點,在此不作傻瓜式的教程,也但願你們可以多動手操做,遇到問題嘗試自我解決並開源分享。linux

坑點一:docker pull 基礎鏡像拉取緩慢

首先獲取鏡像有這麼如下三種方式:webpack

  1. dockerHub: 鏡像最全, 但訪問速度慢,很蛋疼
  2. 局域網倉庫:須要手動搭建,公司內部大批量使用的最佳方案,但不建議我的開發者使用
  3. 經過import 引入他人導出的壓縮包來獲取鏡像
    關於使用dockerhub鏡像緩慢的問題在第三篇文章中已經介紹過了,配置了DNS、切換了阿里,網易,中科大的國內源以後,極可能仍然很緩慢,以前的方法網上一抓一大把,效果有限,有時候拉取一個源,一下午都拉不下來,只能等晚上纔會稍微好點。關於這點,通過這麼屢次嘗試後(至少對於我我的所處的網絡拓撲結構下),最穩定,速度最快的是使用阿里雲的我的鏡像加速:登陸阿里雲 => 搜索容器鏡像服務 => 尋找 鏡像加速器 => 按照文檔操做便可。 至少使用第一種方法來講,這已是我嘗試過的最快的方法了。

坑點二:alpine安裝nvm夭折

  • 這裏首先要了解alpine是一個很是小巧的linux基礎鏡像, alpine + busybox 的架構與傳統雙系linux發行版不一樣,而且手動安裝直接安裝的時node最新版本,多版本的node難以同時存在,固然也不是不能安裝nvm,只是比較麻煩。在此建議直接跑apk的命令, 我的嘗試過切換穩定源後,安裝很是迅速,即使是經過反覆安裝切換node版本也很是迅速。

坑點三:命令找不到,例如 sh: 命令未找到

在linux鏡像中若出現not found或者命令未找到的報錯信息,多半是由於環境變量未找到,未在相應文件中(~/bashrc, ~/.zshrc, ~/.profile, ~/.bash_profile)導出環境變量, 根據不一樣的基礎鏡像與shell類型,與環境變量相關的文件也不盡相同: 例如ubuntu的文件爲 ~/.bash_profilegit

  • 單次生效可直接使用 export, 但須要注意,在dockerfile中,儘可能在同一個layer層中使用export,也就是在同一個RUN命令下導出。
  • 使用source命令執行相應的配置文件,此處須要注意 ubuntu的 sh命令是基於dash,所以source不能直接使用,須要利用 /bin/bash -c "source ~/.bash_profile"

坑點四:build失敗 網絡問題,build後不是最新的

  1. 首先說build失敗的網絡問題
    此項主要涉及yum、apt-get等update操做或者安裝軟件包的問題,須要保證兩點:
    • docker編譯環境 與 宿主機的 網絡鏈接問題,這點能夠經過參數 --network解決,注意 build是 --network, 而 run是 --net
    docker build -t <image>:<tag> --network=host .
    • 修改相應的鏡像源
      例如使用alpine須要修改 /etc/apk/repositories
    echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories \
      && echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
    使用ubuntu則須要修改 /etc/apt/sources.list
  2. 使用 docker build以後,發現build的鏡像不是最新的,與dockerfile不符
    若是肯定本身run的image和tag都正確,通常出現這種狀況大機率是由於緩存,緩存這個東西嘛,你是個前端你還不懂嗎?哈哈,清除緩存便可
    docker build -t <image>:<tag> --network=host --no-cache.

坑點五:npm install 易失敗,安裝時間長

  • 在此有必要說一下npm,cnpm,yarn的鎖機制:
    首先須要清除版本號前面^與的區別,1.2.3匹配的是1.2.3-1.2.x ; ^1.2.3 匹配的是 1.2.3-1.x.x
  1. npm: 存在鎖機制 ,高版本(具體忘記了) 增長 package-lock.json, 能夠再相同的package.json 與 package-lock.json 配合下安裝肯定版本的npm包。
  2. cnpm:不存在鎖版本,目的是使用符合嚴格規範的包(按照 大.中.小 來講, 大版本的數字表明的重大的更新, 中版本的數字表明着功能迭代,但要向下兼容,小版本則表明bug修復), 默認安裝大版本下最新的包。
  3. yarn: 存在鎖機制,使用yarn.lock(version字段、resolved字段共同起做用)
    install 時安裝時間長主要由於源不夠穩定快速,nrm是一個解決方案。
  • 其次主要涉及一些特殊的包例如: node-sass,這個包在不一樣的node大版本下,兼容的版本是不一樣的:
NodeJS Minimum node-sass version Node Module
Node 14 4.14+ 83
Node 13 4.13+ 79
Node 12 4.12+ 72
Node 11 4.10+ 67
Node 10 4.9+ 64
Node 8 4.5.3+ 57

坑點六:-v 掛載卷後,容器內文件被清空

  • 咱們起初的想法是,經過本機目錄掛載容器目錄,從而實現修改源碼的目的,但實際操做中會出現掛載後容器內 掛載卷內的文件缺失的狀況。主要緣由以下:
    宿主機 /home/files/src 與 容器 /home/src 相掛載, 是以宿主機目錄 /home/files/src/ 爲基準,若起初宿主機目錄爲空,容器對應目錄存在文件,則掛載後,容器內文件會被清空。在此有個小技巧: 大部分狀況下源碼都在版本控制器中,以git爲例,容器內文件被清空後,能夠經過 git status 查看,是存在操做記錄的,因此清空操做與git並不衝突, 使用正則作部分匹配還原便可:
git checkout -- src/**
  • 其次數據的通訊、備份、恢復等操做能夠經過數據卷容器,能夠回看個人第一篇文章。

坑點七:宿主機訪問docker容器內webpack-dev-server,端口映射失敗

  • 這裏首先要ping 一下127.0.0.1 保證本地的迴環地址是通的,而且TCP/IP功能正常。
  • 其次最重要的一點就是 webpack-dev-server的配置中要確保host設置爲: 0.0.0.0
    devServer: { ... host: '0.0.0.0', port: '9999', }
  • 而後使用 docker run 作端口映射便可
docker run -it -p 9999:9999 <image>:<tag>

坑點八:在宿主機訪問後,webpack 熱更新失敗

當時想達到的效果就是經過容器執行dev操做,開啓webpack-dev-server作端口映射,宿主機瀏覽器直接訪問相應網址, 因爲掛載卷中的文件與容器相連,修改後可根據熱更直接顯示在宿主機瀏覽器上,這樣就大功告成了。
但實際操做過程是這樣的:github

  1. 首先開啓容器
docker run -it -v /Users/tate/Documents/work/geek/docker/ws/src:/home/webpack-multipage-cli/src -p 9999:9999 ws:1 /bin/bash
  1. 在對應目錄下執行 npm run dev 啓動開發模式
  2. 在宿主機瀏覽器使用 localhost 訪問, 成功訪問。
  3. 修改掛載的數據卷中的文件,檢查是夠可以熱更新。
  4. 熱更新失敗,可是刷新後,修改內容生效。
    解決此問題須要保證如下幾點:
  • 按照坑七將devServer的host修改成 0.0.0.0
  • 將webpack的output配置按照如下修改:
// 此處的publicPath的端口號要與devServer中相同
module.exports = {
      output: {
          publicPath: `//localhost:9999/`,
          hotUpdateChunkFilename: 'js/hot-update-[name].js',
          hotUpdateMainFilename: `hot-update.json`
      }
}
* 在宿主機經過localhost或宿主機IP訪問,避免經過0.0.0.0訪問

成型

dockerfile配合shell腳本作差別化處理

  • 解決上述問題後,能夠再dockerfile中將宿主機的shell腳本copy至鏡像中,在默認啓動時執行:
COPY init.sh /home/
CMD ["/bin/bash", "-c", "/home/init.sh"]
  • init.sh 文件則根據傳入的環境變量構建不一樣的環境 dev or build
# !/bin/bash
source ~/.bash_profile
cd /home/webpack-multipage-cli
git checkout -- src/** page/**
echo "WEBPACK_MODE: $WEBPACK_MODE"
if [ $WEBPACK_MODE = 'dev' ]; then
      echo "running in develop mode"
      npm run dev
else
      echo "running in build mode"
      npm run build
fi
FROM pomelott/webpack-cli
WORKDIR /home/webpack-multipage-cli
COPY init.sh /home/
COPY cli-config.js /home/webpack-multipage-cli/
COPY output.js /home/webpack-multipage-cli/config/dev/
RUN chmod -R +x /home/init.sh
EXPOSE 9999
CMD ["/bin/bash", "-c", "/home/init.sh"]

實際使用

  • dev環境,掛載容器卷,端口映射開啓熱更
    注: 因不須要手動執行 npm run dev ,因此不須要手動指定/bin/bash
docker run -it -p 9999:9999 -v /Users/tate/Documents/work/geek/docker/ws/src:/home/webpack-multipage-cli/src --env WEBPACK_MODE=dev pomelott/webpack-cli:latest
  • build 環境
    注: 根據我的須要更換掛載目錄:/Users/tate/Documents/work/geek/docker/ws/src 、/Users/tate/Documents/work/geek/docker/ws/dist
docker run -it -v -v /Users/tate/Documents/work/geek/docker/ws/src:/home/webpack-multipage-cli/src \
       -v /Users/tate/Documents/work/geek/docker/ws/dist:/home/webpack-multipage-cli/dist --env WEBPACK_MODE=build pomelott/webpack-cli:latest
相關文章
相關標籤/搜索