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。