使用Docker将vue跨域的项目部署到云服务器

一 背景

之前在开发完项目后,部署过Django和Flask的项目,同时也做了相应的笔记,但是那个时候部署都是一个一个配置文件,配置完文件后,不敢乱改,稍有不慎,可能就出问题了.同时那个时候,我是采用supervisor来管理各个服务进程的.但是对于我个人来说,只有一台服务器,那么绑定到一台服务器上,这样的方式也还好,但是对于一家大公司来说,有着成百上千的服务器,如果都用这种方式肯定不醒,所以,恰好这次实习过程中做了一个vue.js的项目,之前也了解过docker技术,正好将这个vue项目使用docker容器进行部署.以下是我部署过程中的过程和心得.


二 部署过程

由于本地和服务器上都有docker,但是出于第一次使用docker部署,不是特别熟练,所以首先在本地进行部署测试.然后测试通过后,无问题后,再将镜像打包,直接扔到服务器上启动容器即可.

使用容器技术可以确保应用在不同的环境,如生产,测试,上线环境中正常的运行,并且在部署过程中不会出现令人头疼的问题,使用docker可以确保每个环境下的每个服务都具备一直的配置和文件,具备很高的可移植性,可配置性和可隔离性.

假设你已经安装了docker,没有的去官网下载与本机操作系统匹配的版本.


1.pull nginx 镜像

命令:sudo docker pull nginx


2.在项目的根目录创建nginx文件夹,在nginx文件夹中创建default.conf

命令:

mkdir nginx

sudo vim default.conf

将下面代码写入default.conf

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
server {
listen 80;
server_name localhost;

#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
error_log /var/log/nginx/error.log error;

location / {
root /usr/share/nginx/html; # 将定位到该目录下的dist模块,我将在dockerfile中将dist模块copy到这里
try_files $uri $uri/ /index.html;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; # 从中的最后一截获取用户真是IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 同上
proxy_set_header X-Forwarded-Proto $scheme;

index index.html index.htm;
}
# 正向代理vue中转发的请求,请求网易云的API
# 找到以/api开头的请求
location ^~ /api/ {
# ip是node容器中的ip地址,port是其内部暴露的端口号
proxy_pass http://172.17.0.2:3000/;
}

#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 /usr/share/nginx/html;
}
}

注意:这里只写了server服务,其将被引入到nginx的主配置文件中,因此需要编写如下的Dockerfile


3.编写dockerfile

1
2
3
4
5
6
FROM nginx:latest

COPY dist/ /usr/share/nginx/html/

COPY nginx/default.conf /etc/nginx/conf.d/default.conf

说明:

第一行:表示基于nginx:latest 镜像上镜像上进行搭建

第二行:将vue打包文件 copy到/usr/share/nginx/html/下,需要和nginx.conf中的root转发的地址一致

第三行:将在nginx文件夹下的default.conf配置文件copy到/etc/nginx/conf.d/default.conf


4.构建docker镜像

命令: sudo docker build -t vue-smartcloudmusic .

其中 -t 指明构建后的镜像名. . 表示在当前目录下进行构建


5.本地运行docker容器

命令: sudo docker run --name vuesmartcloudmusic -d -p 8080:80 vue-smartcloudmusic

其中 –name制定容器名 , -d 表示守护进程方式运行, -p指明映射关系,将本机的8080端口映射到容器内部的80端口, 最后指明了实例那个镜像名.


6. 查看nginx服务是否正常运行

命令:ps aux|grep nginx

查看nginx服务是否启动成功,同时可以访问本机的地址127.0.0.1:8080看是否正常显示.


到此为止,部署纯vue项目,不带任何跨域,任何负载,就基本完成了由于我在项目中还需要调用网易云的API,因此还需要构建一个node容器来运行其项目,同时还要配置跨域的配置.因此请往下看.


7. 网易云API的项目自带了Dockerfile,因此我就偷个懒,直接用它的Dockerfile进行构建

Dockerfile文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM node:lts-alpine

WORKDIR /app
COPY . /app

RUN rm -f package-lock.json \
; rm -rf .idea \
; rm -rf node_modules \
; npm config set registry "https://registry.npm.taobao.org/" \
&& npm install

EXPOSE 3000
CMD ["node", "app.js"]

说明:说下大概的意思

第一行: 基于node:lts-alpine版本镜像进行构建,如果没有则会自动pull下来

第二行: 设置工作目录为 /app下

第三行:将当前目录所有文件拷贝到 /app下

第四行:执行一系列的指令,删除一系列的文件和依赖包,为npm设置镜像源,然后重新安装依赖包.

倒数第二行:暴露node服务器的端口号为3000

最后一行:执行命令行 node app.js启动服务器

备注: 请注意要实现本地项目访问网易云的node项目,还需要在nginx中配置路由转发

1
2
3
4
location ^~ /api/ {
# ip是node容器中的ip地址,port是其内部暴露的端口号
proxy_pass http://172.17.0.2:3000/;
}

上面的ip地址通过检查目标容器信息找到Address IP, 使用指令 sudo docker inspect CONTAINER_ID,
不是云服务器的内网ip,而是容器的内部ip.


8.在了解了dockerfile基本指令后,就可以构建镜像了

命令: sudo docker build -t neteasecloudmusic .

根据当前目录构建镜像

9.启动node容器

命令:sudo docker run --name neteasecloudmusic -d -p 3000:3000 neteasecloudmusic

10. 测试浏览ip:port,看服务能否正常启动

网址输入127.0.0.1:3000

截图效果:

https://django-blog-syz.oss-cn-shanghai.aliyuncs.com/netcloudmusicapi.png{width=80%}


三 过程错误总结

前前后后构建镜像,出错,删除镜像,修改,重新构建,出错,删除….正确.经过了很多次,终于成功了.这里主要写几个非低级错误.

1.首先第一个错误:

Resource interpreted as Stylesheet but transferred with MIME type application/octet-stream

项目启动成功后,在css样式渲染不出来,查看控制台发现如下错误,Resource interpreted as Stylesheet but transferred with MIME type text/html.

这个错误意思是静态资源被渲染成了stylesheet但是被转化为二进制类型.

错误产生的原因:

我在构建我自己的项目时,我在本地独自启动nginx,没有用docker时,nginx.conf中的配置文件 include /usr/local/nginx/conf/mime.types;
这一行不正确,没有包含正确mime.type路径,它应该是nginx安装路径中的mime.types文件.

解决方案:

在找到目标文件,修改路径后,清除缓存并刷新浏览器,就正常的渲染出界面了.


2.第二个错误:

在编写Dockfile时,一定要仔细,如果配置某一个server,nginx允许直接在一个新文件中写server,然后在nginx.conf总配置文件中引入这些子配置文件即可.

错误产生的原因:

我将nginx.conf替换到/etc/nginx/conf.d/default.conf,导致nginx服务直接启动不起来.

解决方案

要么将nginx.conf,替换掉/etc/nginx/nginx.conf要么,将子配置文件替换/etc/nginx/conf.d/default.conf或者/etc/nginx/site-availabled/default.conf,或者该文件夹下的其他文件名即可.


总结

虽然这是第一次使用docker部署,虽然花了我一上午,但是最终成功了,自己还是蛮欣慰的.做一个项目,在平时学习过程中,
应该做到精益求精,可能工作上不需要我部署,但是平时学习的过程还是值得自己探索一番的!