Docker搭建前端开发环境
前言
项目地址
Docker Game
- 4:20起床,debug
- 在google中搜索100条docker相关的post
- 在社交软件的时间线上写道”fuck docker”
- 看10本docker的书
- 穿docker的T-shirt
- 不跟任何人说你搞不定docker
- 说出自己搞定docker的日期并接受它
- 宣誓自己学会了docker
- 最后砸烂你的电脑
NEVER TOUCH NON-LINUX DOCKER!
Docker简介
- Docker就是一个启动很快的“虚拟机”,它仅提供必要的功能,体积小;它能更充分利用宿主的资源。
- Docker原配“只有”linux。Mac和Win所谓的支持Docker归根到底是通过在虚拟机上安装linux系统,再在linux上安装docker。(这句话不完全正确,参见
[解决方案与心路历程8]
) - Docker三个基本概念:Registry注册中心,Image镜像,Container容器
- Registry包含多个Repo(仓库)和Tag(标签),从Registry下载Image的方式是
pull <仓库名>:<标签名>
,如pull ubuntu:16.04
- Image是一个静态概念,相当于面向对象中的类,类不能直接使用,需要实例化。
- Container是一个动态概念,相当于面向对象中的实例化,启动镜像生成容器就是实例化类的过程。只有容器才能被用户使用。
- Registry包含多个Repo(仓库)和Tag(标签),从Registry下载Image的方式是
- 使用Docker的容器Container,任何的操作和数据在退出或重启后不会保存,只能通过Volume(卷)的方式保存常驻文件并和宿主机共享文件。可以理解成网吧的电脑每次重启都自动还原系统,只有U盘里面的东西不会变。
- Docker的容器Container所做的任何修改都不会影响到Image。除非用commit命令,将修改提交,才能将修改应用到Image,类似git的管理方式。
一、 旧的开发环境及可能产生的问题
传统的前端开发环境搭建方式可能产生的问题主要有两点:
- 新同事、新电脑或重装系统后,开发环境的搭建显得很繁复。
- 每个前端开发人员可能由于操作系统的不同,开发环境版本及插件版本不同造成开发环境不统一。
早几年,大公司都会采用开发机和多用户的方式来统一开发环境。每个开发人员只需要一台显示器和外设,全部连接到中型或大型开发机上进行开发。这种方式经济成本较高,管理成本也高。而现在更提倡轻量管理。节约成本的前提下如何解决上述的两个问题?
二、 解决方案与心路历程
寻找一个优秀解决方案的过程向来是艰辛的,下面是我的心路历程:
**思维导图[/vm]**:最初考虑用虚拟机的方式,每个开发人员安装虚拟机和统一的镜像文件,镜像包含了统一的开发环境,本地开发目录和虚拟机共享,即可在虚拟机中对开发目录进行操作。这种方式简单易行。缺陷主要是性能相对会降低,同时对虚拟机镜像的维护不方便。虚拟机镜像如同一个黑盒,历史维护记录,目录结构不清楚,很容易引起混乱,当前的维护人员不清楚之前的维护人员到底安装了哪些东西,如何配置的等等。
**思维导图[/docker]**:虚拟机的方案被Pass之后,目光聚焦到Docker,如
[简介1]
所述,Docker的轻量和高性能值得一试。于是查找相关资料,看到《用 Docker 快速配置前端开发环境》一文,见[附录1]
。文中主要提及两点:- 使用Docker的图形化工具Kitematic管理Docker并基础平台
- 使用linux的samba共享文件夹操作工作目录
**思维导图[/docker/docker toolbox]**:Kitematic是Docker的UI壳子,上文提及使用Docker Toolbox进行安装,Docker Toolbox是Docker官方开发的 Docker套装,里面有全套Docker环境,也有图形化工具 Kitematic。注意Docker Toolbox在win下仅支持win7 X64到win10,这里开始就是茫茫多的坑了。如下图所示,Docker Toolbox默认安装Docker Client和Docker Machine。什么是Docker Machine?
**思维导图[/docker/docker toolbox/docker machine]**:弄懂Docker Machine,先要弄清楚什么是boot2docker,如
[简介2]
所述,Docker原生只支持linux,Docker的诞生基于linux的底层虚拟化技术。为了能在非linux系统运行Docker,boot2docker才诞生。boot2docker实际上就是打包一个Virtual Box或Vagrant虚拟机,在虚拟机上安装一个最小化linux,在linux上安装Docker,同时boot2docker负责将使用者本机的docker命令和虚拟机linux里面的docker“无缝”连接起来。这就是boot2docker。由于boot2docker非原生非官方,存在诸多bug,如早期boot2docker兼容docker命令不全,由于Virtual Box和Vagrant不稳定经常导致崩溃等等。2015年Docker官方发布了Docker Machine,它的实现原理和boot2docker基本一样,但它能更好的替代boot2docker。直到如今,很少再看到使用boot2docker了,而是使用官方的Docker Toolbox打包的Docker Machine。当然我们并不是再也见不到boot2docker,在Docker Toolbox安装后的目录里,我们还是能看到boot2docker.iso
这个文件,也就是说Docker Machine最终安装在虚拟机里面的linux系统,还是boot2docker当初创建、发布并维护至今的linux最小系统的镜像文件。**思维导图[/docker/docker toolbox/docker machine/platform]**:如你所想,无论是boot2docker还是Docker Machine,都是在非linux环境搭建虚拟机,再在虚拟的linux中安装Docker。这就与
[简介1]
的特性相矛盾。事实如此,非linux的Docker几乎不会用于当正式的生产环境,多用于研究Docker技术。那么这条路要走到尽头了?win10的出现带来了一些曙光,微软官方称win10“兼容”Docker,而Windows Server2016 更是宣称支持原生Docker。win7、win10、server 2016,这三者对Docker的支持究竟有什么不同?**思维导图[/docker/docker toolbox/docker machine/platform/win10]**:在第4节中,介绍了早几年,win10还没发布,win又缺乏对Docker的支持,于是采用了boot2docker和Docker Machine来支持Docker。他们的原理是基于Virtual Box或Vagrant虚拟机。也说到Virtual Box或Vagrant的不稳定性带来的问题。自win8开始,操作系统自带Hyper-V虚拟机。至此,市面上三大虚拟机软件齐聚一堂。
- Virtual Box开源免费、安装包小、相对不稳定
- Hyper-V作为win自带软件,在win下最稳定,但对于图形界面渲染性能较差
- VMware workstation商用、收费、各方面都不错
由于VMware收费和商用的性质,所以boot2docker和Docker Machine官方发布都仅支持开源免费的Virtual Box,民间不少开发者制作了boot2docker和Docker Machine支持VMware workstation、Hyper-V乃至其他虚拟机的插件,这里不再过多叙述。Hyper-V在经历win8、win8.1的磨合后,新的版本无论兼容性、稳定性还是运行效率,都有了更好的提升。于是微软在win10里,可以直接将docker安装运行在Hyper-V中,并在操作系统中直接加入了本机和Hyper-V中的Docker通讯交互的功能。也就是说win10基于Hyper-V,实现了boot2docker或Docker Machine的功能,基于Hyper-V的Docker更稳定。但是,说到底,win10的Docker还是跑在虚拟机下啊!穿个马甲还不认识你了???
**思维导图[/docker/docker toolbox/docker machine/platform/win10/hyperv]**:所以win10可以在docker官网直接下载docker安装包,同时win10也支持Docker Toolbox使用Docker Machine的方式(参见
[解决方案与心路历程3]
)。这里需要提醒一下,win10支持两种安装Docker的方式,而在[解决方案与心路历程3]
中也提到Kitematic是docker的一个可视化UI,两种Docker安装Kitematic的方式也不一样,具体可参考[附录2]
。简述步骤如下:- Docker Toolbox安装包自带Kitematic,可勾选后安装
- win10的Docker安装包,安装完成后可在任务栏右键Docker,下载并安装Kitematic
既然win10的Docker比基于Virutal Box的Docker Machine性能更好,那么自然而然就想考虑使用win10的Docker。然而却遇到一些不符合实际环境的问题:
- 团队中确实有一些开发人员仍在使用win7
- Hyper-V和VMware workstation冲突。由于Hyper-V独占硬件虚拟化,所以不能和VMware workstation或Virtual Box共存,而VMware workstation却能和Virtual Box共存(可能会产生网络冲突情况,但可以解决)。
在
[解决方案与心路历程6]
中有提到Hyper-V的图形界面渲染性能比较差,再加上部分开发人员需要在虚拟机中安装其他windows系统进行兼容性调试测试,甚至安装“黑苹果”,这方面Hyper-V基本没法满足。还有些开发人员使用基于Virtual Box的安卓模拟器,Hyper-V也无法与之共存。所以在实际环境面前,基于Hyper-V的Docker基本走到头了。**思维导图[/docker/docker toolbox/docker machine/platform/server2016]**:win10的Docker方案被Pass后,接着
[解决方案与心路历程5]
,看看Windows Server 2016的原生Docker是什么。[附录3]
中,微软官方介绍了Windows Container。主要是说Windows Server 2016上安装Docker可以切换到Windows Container模式。这是一个怎样的功能?[简介2]
中说道Docker原生只支持linux,这句话现在不一定对了。Windows Container让Docker可以直接跑在Windows Server 2016下,不需要依赖任何linux虚拟机。但是,但是,但是!Windows Container的Docker容器目前只能跑.net或.net core的应用。不能安装其他操作系统的镜像。哈?半成品?Pass!**思维导图[/docker/docker toolbox/kitematic]**:Docker在win平台的3种“生命形态”已经全部了解完了,根据实际环境,为了兼容win7和VMware workstation,只能选择回到Docker Toolbox,拥抱Docker Machine。
[解决方案与心路历程2]
以及[附录1]
中提到使用Kitematic可以更方便的管理Docker。《用 Docker 快速配置前端开发环境》[附录1]
一文中,介绍了使用Kitematic搭建前端开发环境的整个流程。但是文中也提到“Windows 的 Kitematic 有严重 bug,改动 Settings 下的任何选项都会导致所有配置项丢失”,该文自2016.8提出,至今(2017.6)仍存在这个Bug。不能用图形化界面配置,用Kitematic启动Docker后还要执行脚本甚至写Docker命令?我要这UI有何用?我要这界面又如何???还不如基于Docker Machine,直接写一个脚本,前端开发人员按顺序点,就可以使用。所以至此,彻底摒弃Kitematic,参考Docker Toolbox安装目录里面的start.sh,重写一个脚本,完成所有功能。同时,我开始怀疑使用Docker搭建开发环境还有没有意义,毕竟基于Virtual Box再安装Docker,已经失去了Docker的优势。**思维导图[/docker/docker toolbox/docker machine/image]**:《用 Docker 快速配置前端开发环境》
[附录1]
一文中,基于官方的centos或者ubuntu,提前搭建好前端的开发环境,commit后生成新的Image,提供给前端开发人员使用。这种方式与[解决方案与心路历程1]
中提到的虚拟机镜像方式几乎一模一样,经过几番折腾,我已经对Docker搭建前端开发环境产生怀疑。非linux平台下,使用Docker本来就不存在性能优势,还存在镜像不透明会导致管理混乱的问题。这样算下来,还不如使用虚拟机。考虑再三,决定不再使用打包Image的方式,而是采用Dockerfile的方式生成镜像。这才是Docker的天生优势,也是我决定继续完成这个项目的唯一理由。Dockerfile可以理解成一个批处理,里面包含生成镜像的所有指令,build Dockerfile时,会顺序执行这些指令,最终将镜像生成出来。详细的说明可参考[附录4]
。使用Dockerfile,能让维护人员清晰的看到镜像生成的过程,修改和管理起来就非常清晰了。**思维导图[/docker/docker toolbox/docker machine/volume]**:
[简介4]
提到Docker的容器不会保存数据,持久化数据需要通过Volume方式挂载。也举了一个形象的例子,网吧电脑和U盘,在这里Volume就是U盘。Volume的挂载规则如下:- 挂载方式为 -v [宿主机路径]:[Docker容器路径]。 这里得理解宿主机是谁?由于我们使用的Docker实际上安装在虚拟机上,也就是说这里的宿主机路径是Virtual Box中linux虚拟系统内的路径。
- Docker容器的路径必须是绝对路径
- 可以挂载多个Volume,也就是可以插多个U盘
- 可以不指定宿主机路径,这时候会在宿主机的默认路径下自动生成对应的volume路径,如
/var/lib/docker/volumes/XXX
根据上面的规则,可以看出Docker中的持久化数据通过挂载Volume,实际上存在宿主机的文件夹中,实现了Docker和宿主据的资源共享。也就是说我们已经把前端开发环境封装在Docker的Image中了,但是项目的源码不能放在Docker中,只能通过Volume的方式挂载到Docker中。那么我们怎么实现在我们本机编辑项目代码,并在Docker中build呢?
[解决方案与心路历程2]
中也提到《用 Docker 快速配置前端开发环境》[附录1]
一文,使用Samba来实现这一流程。Samba是linux环境下的文件共享技术,在制作Image时,安装samba,并做好配置,将挂载的volume文件夹共享出来,这时候我们在本机就可以通过//192.168.99.100/share
的方式进入Docker的文件夹系统,实现与Docker的数据交互。这是一个正向思维:- 通过
-v [宿主机路径]:[Docker容器路径]
,先创建Docker的Volume - 在Docker中安装samba,将Volume共享出来
- 在本机,通过读取网络共享文件夹的方式进入Docker的文件夹
使用这种方法,数据其实是保存在宿主据路径,也就是linux虚拟机上。好处就是磁盘格式就是linux的磁盘格式。缺点也很明显,数据在虚拟机上,本机只是远程访问虚拟机数据而已。数据安全性很差,Virtual Box的稳定性大家都懂的,一旦虚拟系统奔溃或被误删。整个本地项目源码就没了!虽然我们可以通过git等工具上传,但容易丢失本地数据,这个也很致命!所以我们必须换一种方式,通过逆向思维:
- 将本机的工作目录共享给Virtual Box 虚拟机
- 再将Virtual Box 虚拟机中的这个目录挂载到Docker上
这种方式,数据是保存在本机上的。好处当然是安全,缺点就是磁盘格式可能是windows下的NTFS,可能会产生一些问题。往下看,就踩坑了。
**思维导图[/docker/docker toolbox/docker machine/volume/virtual box]**:为何要把本机目录共享给Virtual Box虚拟机?如下图所示,我们在安装好Docker Toolbox后,手动打开Virtual Box,查看名称为
default
的默认linux虚拟系统的配置。在共享文件夹一栏中可以看到,默认配置中,已经将本机C盘的User文件夹共享给linux虚拟系统。本机的其他目录并没有和虚拟机有连接。也就是说Docker通过Volume与宿主机共享文件,要想Docker和本机有数据交互,就先把本机目录共享给虚拟机(宿主机),再由虚拟机挂载到Docker上。
通过手动挂载本机目录给Virtual Box,可以满足我的需求,但我更希望使用脚本的方式,自动完成这一工作,参考Virtual Box官方的文档,使用VBoxManage sharedfolder add
命令可以实现脚本自动化挂载。详情参见[附录5]
。**思维导图[/docker/docker toolbox/docker machine/volume/virtual box/symlink]**:成功将本机目录与虚拟机中的Docker连接后,本以为万事大吉,不料却又是一个个大坑。在Docker中,切换到共享目录,对现有的前端项目使用
npm install
安装所需的module,提示报错Error: EROFS, read-only file system ...
,经过查阅资料,原来是Virtual Box自4.1.8版本起,为了安全性,禁止在虚拟机挂载共享目录中创建symlink
,此时可以继续使用VBoxManage命令来解决,VBoxManage setextradata VM_NAME(虚拟机名称) VBoxInternal2/SharedFoldersEnableSymlinksCreate/SHARE_NAME(共享文件夹名称) 1
,详情见[附录6]
。**思维导图[/docker/docker toolbox/docker machine/volume/virtual box/ntfs]**:给虚拟机开启symlink后,继续遇到问题,仍提示symlink创建不成功,仔细想一下,NTFS是windows磁盘格式,它与linux的符号连接symlink本身就不一样,这个底层不兼容问题就是在
[解决方案与心路历程11]
中提到的又一个坑。再次查阅资料,通过第三方开源软件NTFS-3G
挂载NTFS磁盘,可以使linux读写NTFS。但Virtual Box是虚拟机,没有物理磁盘一说,怎么挂载就成了问题。再考虑一下,既然linux中有NTFS-3G
这类的软件支持NTFS,难道Virtual Box就没有想到?最终问题还是得到了解决,解决的方式很奇葩,用管理员权限打开Virtual Box就行了。详情见[附录7]
。**思维导图[/docker/docker toolbox/docker machine/volume/virtual box/uac]**:在
[解决方案与心路历程12]
中,我们使用了VBoxManage sharedfolder add
命令来实现自动挂载本机目录给虚拟机,所以当初的设置是打开脚本,提示用户输入本机工作目录。为了方便,可以直接拖拽这个文件夹到控制台中。然而,为了使用管理员权限打开Virutal Box,我不得不把管理员权限挂到脚本上,然后就会产生一个老问题,拖拽文件夹的功能不能用了。这是因为脚本是管理员权限,而文件夹是用户权限,权限不同级,不能实现拖拽。具体原理可以参考我之前的一篇文章[附录8]
。解决的方法只有三种:- win7可以直接使用管理员登陆,除了安全性较差,没其他问题。由于全局管理员权限,可以实现拖拽。
- win8/8.1/10,也可以使用管理员登陆,也是安全问题。但还有一个问题,使用admin登陆后,不能使用Metro UI
(Modern)里面的应用。 - 放弃拖拽,手动输入路径,这里就需要注意,由于linux和windows磁盘目录管理方式不同,比如本机的工作路径是
e:\workplace
,那么在脚本的启动终端git bash中,对应的路径应该是/e/workplace
**思维导图[/other]**:当然,整个过程遇到的坑并不仅是上述这些,再节选一部分问题和解决方案,说明如下:
- 使用Kitematic时,启动卡在99%或100%的问题:我是手动删除Virtual Box里面的
default
虚拟系统,再重启解决。可以参考[附录9][附录10]
。 - 在Docker中使用CentOS 7的
systemctl
提示权限不足或者提示Failed to get D-Bus connection: Operation not permitted
的问题:Docker下的每种系统镜像基本都有坑,比如centos7就是这个问题,据说centos7.2会解决,但目前7.3仍是这个问题。解决方案见[附录11]
。 - 在本机的git bash中使用
-it
与docker交互,提示the input device is not a TTY
的问题:windows下使用sh可以通过git自带的git bash,windows在安装git时,可选择两种终端模式:
默认使用MinTTY
,在这种模式下,使用docker run -it XXX
时,就会报上述错误。具体解决方案见[附录12]
。要不就是重新安装git,更换终端模式为Windows' default
,要不就是在执行交互模式的docker命令前加winpty
,如winpty docker run -it XXX
。为了统一起见,我在脚本启动docker容器并实现交互时,都在前面添加winpty
。
- 使用Kitematic时,启动卡在99%或100%的问题:我是手动删除Virtual Box里面的
三、 项目简介(以Github最新Readme为准)#
项目地址
基本功能:
基于Docker Toolbox,在start.sh
的基础上实现了以下功能:
- 自动启动Docker Machine(Virtual Box)
- 设置本地工作目录,自动共享至虚拟机Docker Machine(Virtual Box)的
/develop
下 - 基于centos:latest和自定义的Dockerfile一键安装前端开发环境
- 一键启动并进入前端开发环境
- 进入Docker Machine终端
- 重启Docker Machine
镜像的修改和安装软件如下:
- 使用centos:latest
- 替换yum源为163软件源
- 安装常用工具如curl、gcc等
- 安装nginx,初始版本为1.13.1
- 安装nodejs,初始版本为v6.11.0
- 安装cnpm
- 安装pm2工具
项目目录结构如下:
- setup
- DockerToolbox.exe
- source
- CentOS7-Base-163.repo
- nginx.conf
- nginx-1.13.1.tar.gz
- node-v6.11.0-linux-x64.tar.xz
- boot2docker.iso
- centos.tar
- docker_machine_shell.sh
- Dockerfile
- nginx_config.conf
- start.bat
支持的操作系统:
win7 x64及以上
其他说明及限制:
- 在BOIS中开启虚拟化技术
- win8及以上需关闭Hyper-V
- 默认只开启了Docker的80端口,其他端口不可访问,如需修改请参考“开发者文档”
综述:
由于项目使用Docker Machine在非linux环境下安装Docker,不能提现出Docker的秒级启动特性,同时由于Docker Machine基于Virtual Box,稳定性和综合性能都有所损耗。使用Dockerfile创建前端开发环境所需的镜像文件,使维护和管理更加清晰方便是唯一的优势。 所以该项目更多用于团队内学习和了解Docker的使用。
四、 使用者文档(以Github最新Readme为准)#
运行setup文件夹下的
DockerToolbox.exe
安装DockerToolbox。如果系统中已安装Virutal Box和Git,则不需要勾选,否则一定要注意勾选这两项。运行
start.bat
,等待自动安装,直至出现如下的界面输入
1
,回车,绿色文字提示输入工作目录。注意这里输入的是所有项目所在的文件夹。路径使用linux规范,如本机工作目录是e:\Repository
,则应该输入/e/Repository
。如果路径输入错误或路径不存在,则会提示,并要求重新输入。随后等待直至出现绿色文字提示Set Sharedfolder Success!
。按回车继续。输入
2
,回车,等待安装开发环境的镜像,直至出现绿色文字Setup Develop Dockerfile Sucess!
。按回车继续。输入
3
,回车,进入Docker容器,绿色文字提示WelCome to Docker! IP: 192.168.99.100
,即为成功,使用这个IP就可以访问Docker。使用命令cd /develop
,即可进入第3步中挂载的本地工作目录。注意,步骤1-4只需要执行一次,安装完成后,需要时只执行这一步骤即可进入Docker!除非需要更换工作目录,或更新、重装整个环境,按需要再次执行1-4步。- 通过
cd
命令进入所需的项目 - 使用npm或cnpm install 必要的module
- 根据实际要求编译或启动整个项目
- 复制该Docker项目文件夹根目录的
nginx_config.conf
到工作目录的根目录,修改文件名为项目名称.conf
(如e:\Repository\website.conf) - 编辑该文件,不要修改
listen
端口,修改server_name
为所需的域名,修改location
为本地nodejs服务路径。
- 在控制台输入命令
nginx -s reload
,重启Docker中的nginx服务器,若无任何消息提示,则表示配置文件无误,重启完成。 - 随后可在本机修改
hosts
文件,将nginx配置文件中填写的域名指向到Docker的IP。
- 在本机浏览器输入域名,即可访问。
- 通过
在控制台菜单输入
4
,即可进入Docker Machine的终端,一般用于维护,查看等进阶操作。在控制台菜单输入
5
,可重启Docker Machine。某些时候重启以解决奔溃或者虚拟机异常等问题。在控制台菜单输入
6
,退出控制台。
五 、 开发者文档(以Github最新Readme为准)#
维护建议说明:
- 建议维护:代表建议开发者定期更新或修改
- 一般维护:代表开发者无需频繁维护或可以对该文件不予理会
- 不建议维护:代表不建议开发者修改该文件
维护文件:
**[setup\DockerToolbox.exe]**(建议维护):可在docker官网下载,由于国内网络部分被墙,速度非常慢,需要ss或vpn访问。开发者可定期下载,更新替换项目中的DockerToolbox安装包。国内网络也可在代理网站下载。
**[source\CentOS7-Base-163.repo]**(一般维护):centos7的163yum源
**[source\nginx-1.13.1.tar.gz]**(一般维护):nginx_1.13.1安装包
**[source\node-v6.11.0-linux-x64.tar.xz]**(一般维护):nodejs_6.11.0安装包
**[source\nginx.conf]**(一般维护):nginx配置,用于替换Docker中安装的nginx_1.13.1的默认配置文件。主要增加一行配置
include /develop/*.conf;
,将/develop文件夹下的所有配置文件加载进来。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#user nobody;
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include /develop/*.conf;
}**[boot2docker.iso]**(建议维护):boot2docker发布的用于安装docker的linux最小系统。Docker Toolbox安装后,目录中已经有boot2docker.iso文件,但有可能版本不是最新,启动Docker Machine时会检查对应的boot2docker.iso的版本,如果不是最新,会从github下载,还是国内网速影响,经常会失败。所以开发者可以定期通过ss或vpn下载新版的boot2docker.iso,启动脚本时,会自动将该目录的boot2docker.iso拷贝到Docker Machine中。
**[centos.tar]**(不建议维护):制作的centos:latest 文件的导出包。如果需要更新最新的centos:latest版本,或者使用其他版本如centos:6.5。可以参考“使用者文档”,通过控制台选择
4. Enter Docker Machine
,进入Docker Machine终端:- 键入命令
docker images
查看是否存在centos:latest镜像 - 如果存在,键入命令
docker rmi -f centos:latest
删除现有的centos:latest - 键入命令
docker pull centos:latest
或docker pull centos:6.5
下载最新的centos或指定版本的centos - 若下载非centos:latest,建议使用命令
docker tag centos:6.5 centos:latest
将其命名成latest,因为在[docker_machine_shell.sh]和[Dockerfile]中,很多指令基于centos:latest,以免引起不必要的麻烦。如果你很熟悉docker命令,可以修改[docker_machine_shell.sh]和[Dockerfile]的内容。 - 键入命令
docker save centos:latest > /e/centos.tar
,就可以将centos:latest导出到E盘根目录,名称为centos.tar
- 键入命令
**[docker_machine_shell.sh]**(不建议维护):基于Docker Toolbox安装目录的
start.sh
修改的脚本。代码中凡是添加了##Custom Addition Begin
标注的都是自定义的内容并配有注释,其他的均是Docker Toolbox的start.sh
源码。部分自定义源码片段如下:1
2
3
4
5
6
7
8
9##Custom Addition Begin
#check docker toolbox
if [ -z "${DOCKER_TOOLBOX_INSTALL_PATH}" ]; then
echo "Docker ToolBox is not installed. Please re-run the Toolbox Installer and try again."
read -p "Press enter to continue."
exit
fi
cd "${DOCKER_TOOLBOX_INSTALL_PATH}"
##Custom Addition End1
2
3
4
5
6
7
8
9
10
11
12
13
14
15##Custom Addition Begin
#use local boot2docker.iso
echo -e "${GREEN}Copy local boot2docker.iso... ${NC}"
currentFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ ! -e "${currentFolder}/boot2docker.iso" ]; then
echo -e "${GREEN}Can not find boot2docker.iso in ${currentFolder} ${NC}"
else
if [ ! -d "~/.docker/machine/cache" ]; then
mkdir -p ~/.docker/machine/cache
fi
cp "${currentFolder}"/boot2docker.iso ~/.docker/machine/cache/
fi
##Custom Addition End1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89##Custom Addition Begin
#Boot Manager
STEP="Boot_Manager"
Boot_Manager(){
clear
echo -e "${BLUE}-----Docker Machine Manager-----${NC}"
echo -e "${BLUE}1. Set Sharedfolder ${NC}"
echo -e "${BLUE}2. Setup Develop Environment ${NC}"
echo -e "${BLUE}3. Enter Develop Environment ${NC}"
echo -e "${BLUE}4. Enter Docker-Machine Bash ${NC}"
echo -e "${BLUE}5. Restart Docker-Machine ${NC}"
echo -e "${BLUE}6. Exit ${NC}"
read choose
case $choose in
1) #1. Set Sharedfolder
hasNoDir=true
while ${hasNoDir}
do
echo -e "${GREEN}Input hostPath:${NC}"
read hostPath
hostPath=`echo $hostPath | sed "s/\"//g" | sed "s/'//g"`
if [ -d "$hostPath" ]; then
hasNoDir=false
else
hasNoDir=true
echo -e "${GREEN}Can not find dir: ${hostPath} ${NC}"
fi
done
if [ "${VM_STATUS}" == "Running" ]; then
"${DOCKER_MACHINE}" stop "${VM}"
fi
#remove sharedfolder named develop
"${VBOXMANAGE}" sharedfolder remove "${VM}" --name develop
#add sharedfolder named develop
"${VBOXMANAGE}" sharedfolder add "${VM}" --name develop --hostpath "${hostPath}" --automount
#support symlink
"${VBOXMANAGE}" setextradata "${VM}" VBoxInternal2/SharedFoldersEnableSymlinksCreate/develop 1
#start vm
"${DOCKER_MACHINE}" start "${VM}"
yes | "${DOCKER_MACHINE}" regenerate-certs "${VM}"
eval "$(${DOCKER_MACHINE} env --shell=bash --no-proxy ${VM})"
echo -e "${GREEN}Set Sharedfolder Sucess! ${NC}"
read -p "Press enter to continue."
Boot_Manager
;;
2) #2. Setup Develop Environment
currentFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ ! -e "${currentFolder}/Dockerfile" ]; then
echo -e "${GREEN}Can not find dockerfile in ${currentFolder} ${NC}"
read -p "Press enter to continue."
Boot_Manager
fi
if [ ! -e "${currentFolder}/centos.tar" ]; then
echo -e "${GREEN}Can not find centos.tar in ${currentFolder} ${NC}"
read -p "Press enter to continue."
Boot_Manager
fi
#rm image named centos:latest
docker rmi -f centos:latest || true
#rm image named centos:heygears
docker rmi -f centos:heygears || true
#load image
docker load < "${currentFolder}/centos.tar"
#build dockerfile to generate centos:heygears
cd "${currentFolder}"
docker build --no-cache --rm -t centos:heygears .
cd -
echo -e "${GREEN}Setup Develop Dockerfile Sucess! ${NC}"
read -p "Press enter to continue."
Boot_Manager
;;
3) #3. Enter Develop Environment
#rm container named heygears
docker rm -f `docker ps -a -f name=heygears -q` || true
#run centos:heygears in docker machine
#--privileged=true means run docker with the highest privileges
#-p 80:80 means expose port 80
#-v /develop:/develop means mount docker machine's path "/develop" to docker "/develop" based on setp 1(Set Sharedfolder)
docker-machine ssh "${VM}" 'docker run -d --name heygears --privileged=true -p 80:80/tcp -v /develop:/develop centos:heygears'
#show docker ip
echo -e "${GREEN}WelCome to Docker! IP: `docker-machine ip` ${NC}"
#use winpty enter container
winpty docker exec -it heygears bash
Boot_Manager
;;
4) #4. Enter Bash
cat << EOF## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""\___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\_______/
EOF
echo -e “${BLUE}docker${NC} is configured to use the ${GREEN}${VM}${NC} machine with IP ${GREEN}$(${DOCKER_MACHINE} ip ${VM})${NC}”
echo “For help getting started, check out the docs at https://docs.docker.com“
echo
docker () {
MSYS_NO_PATHCONV=1 docker.exe “$@”
}
export -f docker
if [ $# -eq 0 ]; then
echo “Start interactive shell”
exec “$BASH” –login -i
else
echo “Start shell with command”
exec “$BASH” -c “$*”
fi
;;
5) #5. Restart Docker-Machine
if [ “${VM_STATUS}” == “Running” ]; then
“${DOCKER_MACHINE}” stop “${VM}”
fi
“${DOCKER_MACHINE}” start “${VM}”
yes | “${DOCKER_MACHINE}” regenerate-certs “${VM}”
eval “$(${DOCKER_MACHINE} env –shell=bash –no-proxy ${VM})”
;;
6) #6. exit
exit
;;
*) #other operation
Boot_Manager
;;
esac
}Boot_Manager
##Custom Addition End1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
9. **[Dockerfile]**(建议维护):默认基于centos:latest,生成前端开发环境系统镜像的指令集。如需安装新版nginx或nodejs,执行其他系统命令,或安装其他软件,可以直接修改Dockerfile。使用者执行“使用者文档”步骤4,重新安装开发环境即可完成更新。
``` dockerfile
FROM centos:latest
MAINTAINER wurang
#复制本地yum源、nodejs安装包、nginx安装包
COPY source/CentOS7-Base-163.repo /etc/yum.repos.d
COPY source/node-v6.11.0-linux-x64.tar.xz /usr/local
COPY source/nginx-1.13.1.tar.gz /usr/local
#nodejs 环境变量
ENV PATH="/usr/local/node-v6.11.0-linux-x64/bin:$PATH"
#nginx 环境变量
ENV PATH="/usr/local/nginx/sbin:$PATH"
#支持库
#更新源、安装常用库、安装nginx、nodejs、cnpm、pm2、nginx
RUN cd /etc/yum.repos.d/ \
&& mv CentOS-Base.repo CentOS-Base.repo.bak \
&& mv CentOS7-Base-163.repo CentOS-Base.repo \
&& yum clean all \
&& yum makecache \
&& yum -y update \
&& yum -y install gcc-c++ \
&& yum -y install pcre pcre-devel \
&& yum -y install zlib zlib-devel \
&& yum -y install openssl openssl--devel \
&& yum -y install autoconf libjpeg libjpeg-devel libpng libpng-devel \
&& yum -y install freetype freetype-devel curl curl-devel libxml2 libxml2-devel \
&& yum -y install glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel \
&& cd /usr/local \
&& tar -zxvf nginx-1.13.1.tar.gz \
&& cd nginx-1.13.1 \
&& ./configure \
&& make \
&& make install \
&& cd /usr/local \
&& rm -rf /usr/local/nginx-1.13.1.tar.gz \
&& rm -rf /usr/local/nginx-1.13.1 \
&& xz -d node-v6.11.0-linux-x64.tar.xz \
&& tar -xvf node-v6.11.0-linux-x64.tar \
&& rm -rf node-v6.11.0-linux-x64.tar \
&& npm install -g cnpm --registry=https://registry.npm.taobao.org \
&& cnpm install -g pm2 \
&& yum clean all
#复制nginx配置
COPY /source/nginx.conf /usr/local/nginx/conf
CMD ["nginx", "-g", "daemon off;"]**[nginx_config.conf]**(一般维护):使用者基于该配置文件,在工作目录的根目录,为每一个项目配置nginx,通过代理,访问nodejs。
**[start.bat](不建议维护):为了解决NTFS磁盘在Virtual Box共享目录以及linux下的种种问题,需使用管理员权限打开Virtual Box。于是在[docker_machine_shell.sh]**外,再包了一层批处理,自动使用windows管理员权限。
附录
- 用 Docker 快速配置前端开发环境
- Install Kitematic on Windows 10, 8, and 7 all Editions? GUI for Docker
- Windows Containers on Windows Server
- 使用 Dockerfile 定制镜像
- VBoxManage命令详解
- Creating symlinks in Virtual Box 4.1.8
- Correct way to setup Virtualbox 4.3 to use symlinks on guest
- 管理员权限打开VisualStudio无法访问网络磁盘的解决办法
- Stuck at 99%
- Windows 10 Starting Docker VM freezes @ 100%
- CentOS 7.2 Base Image Dockerfile with systemd Enabled
- Docker for Windows: Interactive Sessions in MinTTY Git Bash
Docker搭建前端开发环境