将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定
1.前言
前段时间,自己搞了个阿里云的服务器。想自己在上面折腾,但是不想因为自己瞎折腾而污染了现有的环境。毕竟,现在的阿里云已经没有免费的快照服务了。要想还原的话,最简单的办法就是重新装系统。而一旦重装,之前的搭建的所有环境就都白搭了。
再加上之前本身就想引入docker,所以就打算利用docker容器来部署这次的前端应用。
2.构建前端应用
在打包之前,首先需要一个可正常运行的前端应用。这个可以使用umi或者create-react-app来构建。
3.nginx的默认配置文件
然后需要在项目中加上默认nginx配置文件。
server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } }
4.编写本地构建脚本
4.1. 移除上次的目录和Dockerfile
#!/bin/bash if [ -d "./dist" ]; then rm -rf ./dist fi if [ -f "./Dockerfile" ]; then rm -f ./Dockerfile fi
因为每次更改后dist中的内容肯定与之前不同,其实这一步显得不是那么必要。运行npm的打包命令也会自动清楚该目录。
而清除Dockerfile则是为了防止更新了Dockerfile,而这次却不能得到最新的配置。
4.2. 打包前端应用
执行前端的打包命令,生成静态文件目录。
yarn build
4.3. 生成Dockerfile
echo "FROM nginx:latest" >> ./Dockerfile echo "COPY ./dist /usr/share/nginx/html/" >> ./Dockerfile echo "COPY ./default.conf /etc/nginx/conf.d/" >> ./Dockerfile echo "EXPOSE 80" >> ./Dockerfile
FROM
制定了该定制容器的基础镜像为nginx:latest
;COPY
命里将打包好的静态文件目录复制到容器内的/usr/share/nginx/html/
目录下,然后将nginx的配置写入容器中对应的位置; EXPOSE
则是设置对外暴露容器的80端口。
4.4. 生成并推送定制image
docker build -t detectivehlh/mine . docker login -u detectivehlh -p ******** docker push detectivehlh/mine
这里是在开发本地,使用docker命令来打包,所以该脚本对docker有强依赖。build
命令表示打包docker应用的,-t
选项则制定了docker镜像的名字和tag,tag会默认为latest。
然后登录dockerHub,将定制好的镜像推送到dockerHub中。detectivehlh
就是dockerHub的用户名,mine
是image的名字。
4.5. 删除tag为none的无用image
第一次构建不会生成tag为none
的image,但是后面每次再次执行该命令就会出现这样的情况。所以每次构建了一个新的image后,需要清除调不需要的image。
docker images | grep none | awk '{print $3}' | xargs docker rmi
使用grep
命令匹配到tag为none
的image,awk
是一个强大的文本分析工具,{print $3}
表示打印出匹配到的每一行的第三个字段,也就是docker的image id
。如果是$0
的话表示当前整行的数据。
xargs
是一个给其他命令(也就是后面的docker rmi)传递参数的一个过滤器,将标准输入转换成命令行参数。
总结来说,上述命令就是找到tag为none
的image的ID,然后使用docker rmi命令移除该image。
4.6. 执行部署
cmd="cd ~ && sh deploy.sh mine" ssh -t USER_NAME@IP_ADDRESS "bash -c \"${cmd}\""
通过ssh命令,登录远程服务器,并且执行参数中的脚本。
deploy.sh
是放在服务端的构建脚本。放在默认的登录用户下。我们发现,后面还跟了个mine,这是在服务器上运行的docker镜像的名字。这里暂时没有对container的名字加上hash,因为自己的小项目,暂时没有必要。
在项目中的完整构建脚本如下。
#!/bin/bash if [ -d "./dist" ]; then rm -rf ./dist fi if [ -f "./Dockerfile" ]; then rm -f ./Dockerfile fi yarn build echo "FROM nginx:latest" >> ./Dockerfile echo "COPY ./dist /usr/share/nginx/html/" >> ./Dockerfile echo "COPY ./default.conf /etc/nginx/conf.d/" >> ./Dockerfile echo "EXPOSE 80" >> ./Dockerfile docker build -t detectivehlh/mine . docker login -u detectivehlh -p ******** docker push detectivehlh/mine docker images | grep none | awk '{print $3}' | xargs docker rmi cmd="cd ~ && sh deploy.sh mine" ssh -t USER_NAME@IP_ADDRESS "bash -c \"${cmd}\""
5. 编写服务器部署脚本
从上面步骤来看,我们还需要一个服务器端的部署脚本。大家可能会说,标题不是说一个脚本搞定吗?em。。。服务器一个,本地一个...简称只需一个脚本。
5.1 接收参数
在本地的构建脚本中,我们传入了docker运行的container的名字。在服务器构建脚本中需要来接收它。然后更新刚刚推送的docker image。
#!/bin/bash name=$1 docker pull detectivehlh/$name
5.2. 启动container
在启动container时我们会面对两种情况,名字为传入参数的container已经在运行了。而在此时如果再次运行docker run
命令就会报错而导致我们无法使用最新的container,也无法达到更新应用的目的。
if docker ps | grep $name | awk {'print $(NF)'} | grep -Fx $name; then echo "Container mine is already start" docker stop $name docker rm $name docker run -d --name $name -p 3000:80 detectivehlh/$name else echo "Container mine is not start!, starting" docker run -d --name $name -p 3000:80 detectivehlh/$name echo "Finish starting" fi docker images | grep none | awk '{print $3}' | xargs docker rmi
所以在这里做一个判断,第一个if判断如果存在名字为传入参数的container正在运行,就停止当前容器再重新启动。如果不存在则直接启动容器。
run
命令就不过多解释了。-d
表示后台运行容器并返回容器ID,--name
表示设置容器的名字,-p
表示设置端口,将阿里云服务器的3000端口映射到容器的80端口,最后一句表示要启动哪个image(好像还是解释了一遍)。
最后一句就是移除多次更新后出现的tag为none
的无用镜像。完整的脚本如下。
#!/bin/bash name=$1 docker pull detectivehlh/$name if docker ps | grep $name | awk {'print $(NF)'} | grep -Fx $name; then echo "Container mine is already start" docker stop $name docker rm $name docker run -d --name $name -p 3000:80 detectivehlh/$name else echo "Container mine is not start!, starting" docker run -d --name $name -p 3000:80 detectivehlh/$name echo "Finish starting" fi docker images | grep none | awk '{print $3}' | xargs docker rmi
6. 如果你只是想打个包
看到标题进来的兄dei,如果只是想打包一个docker镜像,那么你只需要Dockerfile
文件和docker build
命令就OK了。
7. 总结
最初写这个脚本,主要目的是为了方便。所以脚本中为了达到这个目的做了一些调整。最终我达成了满足我需求的一个方便的部署脚本。
它的方便体现在,当我完成了项目代码的更新,只需要跑一下这个脚本,然后等待一会儿,项目就会自动打包成docker image,并且自动的在我的服务器上运行该container。
但是这种方式会给实际的生产环境带来一些不可控的问题。比如,脚本必须不能上传,因为涉及一些服务器的敏感信息。但是如果你不小心上传了,那你的服务器就相当于裸奔了;再比如,你对你的代码必须要十分自信,没有经过测试的代码就直接部署,会带来一些风险。
如果是自己用的,那完全不用担心,想怎么搞怎么搞。但是如果是开放给所有人用的并且有一定的访问量,比如博客,那么对于其他用户来说,这种方式就不怎么友好。
所以我的观点是,分情况来。目前来说我的项目只有少数几个人在用,也还在处于迭代阶段。并且代码仓库是私有的,所以我完全不用担心隐私的问题。服务未经测试就直接上线对于我来说,其实问题也不大。首先我会在本地测试,确认无误后才会执行部署操作。所以在不同的阶段,找到最适合自己的方案就OK。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
阿里云公共镜像、自定义镜像、共享镜像和镜像市场的区别
阿里云ECS云服务器镜像分为阿里云公共镜像、自定义镜像、共享镜像和镜像市场,镜像之间有什么区别?新手站长分享: 公共镜像、自定义镜像、共享镜像和镜像市场的区别 购买创建ECS云服务器时必须选择镜像,阿里云ECS镜像分为公共镜像、自定义镜像、共享镜像和镜像市场,有什么区别?参考下表: 镜像类型 描述 费用 公共镜像 阿里云官方提供的镜像,皆以正版授权,安全性好,稳定性高。公共镜像包含了Windows Server系统镜像和主流的Linux系统镜像 仅Windows Server和Red Hat Enterprsie Linux镜像会涉及资源计费,具体费用以创建实例时显示的信息为准。您购买的Windows Server和Red Hat Enterprise Linux的公共镜像均已获得微软和Red Hat官方支持和正版授权:Red Hat Enterprsie Linux:计费与实例规格大小有关。Windows Server:在中国大陆地域为免费服务,其他国家和地区为计费服务。其余公共镜像免费。 自定义镜像 您使用实例或快照创建的镜像,或是您从本地导入的自定义镜像。只有自定义镜像的创建者可...
- 下一篇
4月23日云栖精选夜读 | 阿里云首次在ASPLOS'19发布重磅论文:揭秘帮助ECS快速迭代的热升级技术
【点击订阅云栖夜读周刊】 阿里云首次在ASPLOS上发表论文,第24届ACM编程语言和操作系统(ASPLOS'19),于2019年4月13日至17日,在普罗维登斯召开,阿里云高级技术专家郑晓代表团队在会上发表了技术报告。 热点热议 阿里云首次在ASPLOS'19发布重磅论文:揭秘帮助ECS快速迭代的热升级技术 作者:宝惜 因热爱而编码,创造至美生活,挑战高效工作 阿里云智能开发者创新应用大赛全记录 作者:阿里ACE 彭飞发表在:阿里云MVP 嘘!偷偷看下阿里技术大牛的私人书单 作者:技术小能手发表在:阿里技术 知识整理 好程序员技术教程分享JavaScript运动框架 作者:好程序员 MySQL共有data和redo的后果 作者:powdba 好程序员web前端分享18个用CSS制作出来的东西 作者:好程序员 BMIP002协议介绍 作者:比原链bytom Android 凉了?聊聊Android的出路,架构必备技术 作者:Android进阶开发 美文回顾 浅谈 Spark 的多语言支持 作者:开源大数据EMR发表在:阿里云E-MapReduce(EMR) 嵌入式视觉,边缘AI驱动器智...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Hadoop3单机部署,实现最简伪集群
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7