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。

将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定的更多相关文章

  1. golang应用打包成docker镜像

    golang编译的应用是不需要依赖其他运行环境的,那么为什么还需要打包成docker镜像呢?当需要附带配置和日志等文件时可以更方便的移植和运行,下面介绍从dockerfile编译成镜像. 在项目根目录 ...

  2. SpringBoot打包成Docker镜像

    1. 本文环境 Maven:3.6.3(Maven配置参考) SpringBoot version:2.3.4.RELEASE Docker version: 19.03.11(Docker搭建参考) ...

  3. 将java项目打包成docker镜像

    简介:将jar打包成镜像好说,毕竟jar包长的都是一样的,但是我们只是写了一个普通的java项目,我也不方便封装成jar包什么的,但是我们也想打包docker image怎么办呢,我们可以用编译后的j ...

  4. 将java项目打包成docker镜像:镜像=副本

    简介:将jar打包成镜像好说,毕竟jar包长的都是一样的,但是我们只是写了一个普通的java项目,我也不方便封装成jar包什么的,但是我们也想打包docker image怎么办呢,我们可以用编译后的j ...

  5. IDEA中直接将 SpringBoot项目打包成 Docker镜像时 pom.xml的配置

    <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactI ...

  6. JAVA SpringBoot 项目打包(JAR),在打包成 docker 镜像的基本方法

    1,打包 SpringBoot 项目,使用 IDEA 如下图 2,将 JAR 包上传到安装了 Docker 的 linux 服务器上,并且在相容目录下创建一个名为 Dockerfile 的文件 3,在 ...

  7. 【Docker】Maven打包SpringBoot项目成Docker镜像并上传到Harbor仓库(Eclipse、STS、IDEA、Maven通用)

    写在前面 最近,在研究如何使用Maven将SpringBoot项目打包成Docker镜像并发布到Harbor仓库,网上翻阅了很多博客和资料,发现大部分都是在复制粘贴别人的东西,没有经过实践的检验,根本 ...

  8. 操作系统-容器-Docker:如何将应用打包成为 Docker 镜像?

    ylbtech-操作系统-容器-Docker:如何将应用打包成为 Docker 镜像? 1.返回顶部 1. 虽然 DockerHub 提供了大量的镜像,但是由于企业环境的多样性,并不是每个应用都能在 ...

  9. BI系统打包Docker镜像及部署的技术难度和实现

    BI系统打包Docker镜像及部署的技术难度和实现 随着容器化技术盛行,Docker在前端领域也有着越来越广泛的应用:传统的前端部署方式需要我们将项目打包生成一系列的静态文件,然后上传到服务器,配置n ...

随机推荐

  1. Windows 使用 Visual Studio 编译 caffe

    说明:最近看 caffe 发现在 github 上下载的源码没有windows版本的,需要自己生成项目文件才能用 Visual Studio 编译,这里记录一下生成Windows项目文件的方法以及编译 ...

  2. bzoj 3505 [Cqoi2014]数三角形 组合

    ans=所有的三点排列-共行的-共列的-斜着一条线的 斜着的枚举每个点和原点的gcd,反过来也可以,还能左右,上下挪 #include<cstdio> #include<cstrin ...

  3. BZOJ_2743_[HEOI2012]采花_离线+树状数组

    BZOJ_2743_[HEOI2012]采花_离线+树状数组 Description 萧芸斓是Z国的公主,平时的一大爱好是采花.今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花 .花园足够大 ...

  4. 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...

  5. 【英国毕业原版】-《博尔顿大学毕业证书》Bolton一模一样原件

    ☞博尔顿大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...

  6. ruby整理

    参考博客:https://www.cnblogs.com/felixzh/p/8081622.html 官网地址 https://rvm.io/rvm/install 一.前提  centos6.8下 ...

  7. css3新增动画

    1.transiition过渡:样式改变就会执行transition (1)格式:transiition:1s width linear,2s 1s height; (2)参数: transition ...

  8. Go中原始套接字的深度实践

    1. 介绍 2. 传输层socket 2.1 ICMP 2.2 TCP 2.3 传输层协议 3. 网络层socket 3.1 使用Go库 3.2 系统调用 3.3 网络层协议 4. 总结 4.1 参考 ...

  9. surging 微服务引擎 1.0 正式发布

    surging 是一个分布式微服务引擎,提供高性能RPC远程服务调用,服务引擎支持http.TCP.WS.Mqtt协议,采用Zookeeper.Consul作为surging服务的注册中心,集成了哈希 ...

  10. 面试题:求第K大元素(topK)?

    一.引言二.普通算法算法A:算法B:三.较好算法算法C:算法D:四.总结 一.引言 ​ 这就是类似求Top(K)问题,什么意思呢?怎么在无序数组中找到第几(K)大元素?我们这里不考虑海量数据,能装入内 ...