用前端姿势玩docker【四】基于docker快速构建webpack的开发与生产环境
目录
- 用前端姿势玩docker【一】Docker通俗理解常用功能汇总与操作埋坑
- 用前端姿势玩docker【二】dockerfile定制镜像初体验
- 用前端姿势玩docker【三】基于nvm的前端环境构建技巧
- 用前端姿势玩docker【四】基于docker快速构建webpack的开发与生产环境
- 用前端姿势玩docker【五】快速构建中类Unix系统与Windows系统的差量化处理【待发布,请持续关注】
前言
关于docker构建前端环境,相关的坑点与难点,基本上都在这儿了,很多都是个人尝试总结的经验,都是从小白过来的,希望能帮助大家快速解决一些问题,抛开前端环境来看,差不多点的镜像基本也够用了。反而前端对易用性的要求更高(前端开发人员可不是天天跟linux打交道),还需要考虑类unix系统与windows的差异化问题,这点会在下一篇文章中重点说明。
打赏啥的也不需要,如果可以,很感激能在github上给个小星星,github入口在 博客最顶部
回顾
之前也说过 docker对于前端而言组重要的两个优势:
- 工作环境的快速构建
- 工作环境的统一
所以利用docker的工程化工作流在想象中应该是这样的:
例如一个新人从0到1构建前端环境: 安装docker => 拉取镜像 => 根据环境(dev、build)的不同传入不同的环境变量运行相应的容器 至此ok,易用性做到位之后,整一个开发环境基本相当于是在安装软件,这样基本上就很香了。
难点与坑点
以下主要分享一下过程当中出现的比较坑或比较重要的点,在此不做傻瓜式的教程,也希望大家能够多动手操作,遇到问题尝试自我解决并开源分享。
坑点一:docker pull 基础镜像拉取缓慢
首先获取镜像有这么以下三种方式:
- dockerHub: 镜像最全, 但访问速度慢,很蛋疼
- 局域网仓库:需要手动搭建,公司内部大批量使用的最佳方案,但不建议个人开发者使用
- 通过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_profile
。
- 单次生效可直接使用 export, 但需要注意,在dockerfile中,尽量在同一个layer层中使用export,也就是在同一个RUN命令下导出。
- 使用source命令执行相应的配置文件,此处需要注意 ubuntu的 sh命令是基于dash,因此source不能直接使用,需要利用
/bin/bash -c "source ~/.bash_profile"
坑点四:build失败 网络问题,build后不是最新的
- 首先说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
- 使用 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
- npm: 存在锁机制 ,高版本(具体忘记了) 增加 package-lock.json, 可以再相同的package.json 与 package-lock.json 配合下安装确定版本的npm包。
- cnpm:不存在锁版本,目的是使用符合严格规范的包(按照 大.中.小 来说, 大版本的数字代表的重大的更新, 中版本的数字代表着功能迭代,但要向下兼容,小版本则代表bug修复), 默认安装大版本下最新的包。
- 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做端口映射,宿主机浏览器直接访问相应网址, 由于挂载卷中的文件与容器相连,修改后可根据热更直接显示在宿主机浏览器上,这样就大功告成了。
但实际操作过程是这样的:
- 首先开启容器
docker run -it -v /Users/tate/Documents/work/geek/docker/ws/src:/home/webpack-multipage-cli/src -p 9999:9999 ws:1 /bin/bash
- 在对应目录下执行
npm run dev
启动开发模式 - 在宿主机浏览器使用 localhost 访问, 成功访问。
- 修改挂载的数据卷中的文件,检查是够能够热更新。
- 热更新失败,但是刷新后,修改内容生效。
解决此问题需要保证以下几点:
- 按照坑七将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
- 测试阶段的dockerfile也做一下展示,详细的可见github:https://github.com/pomelott/webpack-multipage-cli
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
用前端姿势玩docker【四】基于docker快速构建webpack的开发与生产环境的更多相关文章
- 用前端姿势玩docker【五】快速构建中类Unix系统与Windows系统的差异化处理
目录 用前端姿势玩docker[一]Docker通俗理解常用功能汇总与操作埋坑 用前端姿势玩docker[二]dockerfile定制镜像初体验 用前端姿势玩docker[三]基于nvm的前端环境构建 ...
- 基于vue-cli快速构建
基于vue-cli快速构建 https://www.jianshu.com/p/2769efeaa10a Vue是近两年来比较火的一个前端框架(渐进式框架吧),与reactjs和angularjs ...
- 用前端姿势玩docker【一】Docker通俗理解常用功能汇总与操作埋坑
前言 首先一句话表达个人对docker的理解:与传统虚拟技术基于硬件及物理资源的虚拟化相比,Docker更加轻量化,docker为基于操作系统或内核级别的虚拟化,并且提供了从各种机制与操作以满足从开发 ...
- 【Docker】基于docker+etcd+confd + haproxy构建高可用、自发现的web服务
各个工具介绍 (1)Docker:Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux机器上,也可以实现虚拟化,docker ...
- Docker(四):Docker 三剑客之 Docker Compose
前两篇文章我们介绍了 Dockerfile 的使用Docker(二):Dockerfile 使用介绍,我们知道使用一个 Dockerfile 模板文件可以定义一个单独的应用容器,如果需要定义多个容器就 ...
- Docker(四):Docker常用命令
除过以上我们使用的Docker命令外,Docker还有一些其它常用的命令 拉取docker镜像 docker pull image_name 查看宿主机上的镜像,Docker镜像保存在/var/lib ...
- 《前端运维》四、Jenkins--持续构建
首先,我们先来了解下什么叫做持续构建.持续构建简称CI,负责拉取代码库中的代码后,执行用户预定义的脚本,通过一系列编译操作构建出一个制品,并将制品推送到制品库里.常用的持续构建工具有 Gitlab C ...
- 基于GBT28181:SIP协议组件开发-----------第一篇环境搭建
原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3930018.html,qq:1269122125. SIP协议在安 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)(转)
1.前言 在上一篇的内容里我们介绍了基于Android Studio构建ArcGIS Runtime SDK for Android开发环境的基本流程,流程中我们采用的是基于Gradle的构建方式,在 ...
随机推荐
- CSS中link和@import的区别
1.link属于HTML标签,而@import是CSS提供的 2.页面被加载时link会同时被加载:而@import引用的CSS会等到页面被加载完再加载 3.@import只在IE5以上才能识别,而l ...
- vc6.0创建文件时,出现很多烫烫烫解决方法
vc6.0创建文件时,出现很多烫烫烫烫解决方法 SWM2烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫.IA 如果项目文件放在桌面上 如:C:\Documents and Settings\txwtec ...
- phpmyadmin系列渗透思路连载(一)
当拿到phpmyadin的站点后,我一般会尝试一下几种攻击手法: 1.通过弱口令进入后台,尝试into outfile写入一句话 条件:(1)有写的权限 (2)知道web绝对路径 (3)w ...
- 这一次搞懂Spring Web零xml配置原理以及父子容器关系
前言 在使用Spring和SpringMVC的老版本进行开发时,我们需要配置很多的xml文件,非常的繁琐,总是让用户自行选择配置也是非常不好的.基于约定大于配置的规定,Spring提供了很多注解帮助我 ...
- Flask项目实战:创建电影网站-创世纪(1)
以后要养成写博客的习惯,用来做笔记.本人看的东西很多很杂,但因为工作中很少涉及,造成看了之后就忘,或者看了就看了,但是没有融入的自己的知识体系里面. 写博客一方面是做记录,一方面是给这段时间业余学习的 ...
- Java中时间加减的比较
public class TestDate{ public static void main(String[] args){try{ Date date=new Date(); DateFormat ...
- 1年转行资深前端工程师,开源项目过 1k stars,完整学习过程
先介绍下大致情况时间线. 18 年 8 月正式转方向为前端,之前做了一段时间的 iOS,后来因为对前端更感兴趣所以就打算转方向了.19 年 10 月入职当前公司,定级资深前端,分配到业务架构小组,自此 ...
- 泛型<T>,是你肿莫了,还是我错了...
委托自定义数组排序 项目一共三个文件如下. CSort.cs using System; using System.Collections.Generic; using System.Linq; us ...
- (私人收藏)2019WER积木教育机器人赛(普及赛)基础解决方案
2019WER积木教育机器人赛(普及赛)基础解决方案 含地图.基础解决方案.全部路线的往返.详细规则.视频.搭建方案 EV3;乐高;机器人比赛;能力风暴;WER https://pan.baidu.c ...
- 如何实现html页面自动刷新
使用场景: 1. 页面需要定时刷新,实时加载数据,需要实时查看监控数据(H5中的WebSocket和SSE可以实现局部刷新) 2. 一定时间之后跳转到指定页面(登录注册之类) 3. 前端开发使用伪数据 ...