用前端姿式玩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
相关文章
相关标签/搜索