Docker 部署前后端分离项目

1,290 阅读5分钟

首先感谢 jonssonyan 的前后端分离项目让我进行实战演练

部署方式:将后端项目和前端项目;分别生成两个容器运行。

jonssonyan 项目和视频

Docker上部署前后端分离项目视频地址: www.bilibili.com/vide...

权限系统前端项目地址:github.com/jonssonyan.…

权限系统后端项目地址: github.com/jonssonyan.…

以下是我实战中遇到的一些问题和在学习中进行项目的优化

默认是已经安装完成Docker项目,并且能够 docker run hello-world

Docker 运行环境安装

需要安装mysql、ngnix和 java 环境

1、mysql 和 java 环境安装

拉取 Mysql 5.7.31 镜像
docker pull mysql:5.7.31
1. 运行 Mysql 5.7.31
docker run -d --name myMysql -p 9506:3306 -v /data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.31

参数解析:

  • -d: 后台运行容器,并返回容器 ID
  • --name myMysql: 为容器指定一个名称
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -v: 绑定一个卷,容器的 /var/lib/mysql 映射到 主机的目录 /data/mysql
  • -e MYSQL_ROOT_PASSWORD=123456: 设置环境变量,密码设置为 123456
  • mysql:5.7.31:使用镜像 mysql:5.7.31

**为什么不用3306:**其实我本来想用3306,但是因为服务器已经被非docker的mysql占用了,所以沿用视频的9506地址

2. 拉取 Java 镜像

因为项目中的项目java环境是java8,所以指定版本

docker pull java:8
3. 拉取 nginx 镜像

因为项目中的没有要求,就用最新的

docker pull nginx:latest

2、数据库搭建

1. 创建数据库

通过数据库可视化工具,连接服务器的docker mysql

如果是阿里云的云服务器,还需要再安全组开通对应的端口,比如9506 image.png

2. 创建表

连接成功后,使用项目资源中的 sql文件,导入到数据库中 image.png

3、后端打包(mvn)

本项目采用的是8888端口,如果是阿里云的云服务器,还需要再安全组开通8888的出和入规则

1. 修改application.properties中的相关参数

image.png

2. 尝试运行后端程序,成功运行后;点击maven中的 package 打包成jar

image.png

3. 当打包成功后,会在target生产jar文件

image.png

4、前端打包

原则上,前端的项目内容不需要修改;但是因为跨域问题困扰了好几天,所以顺手弄了个多环境配置 image.png

开发环境

# 开发环境
NODE_ENV = 'development'

# 开发环境,api前缀
VUE_APP_BASE_API = '/api'

# 开发环境,Url地址
VUE_APP_BASE_RUL = 'http://localhost:8080/

测试环境

# 测试环境
NODE_ENV = 'test'

# 测试环境,api前缀
VUE_APP_BASE_API = '/test-api'

# 测试环境,Url地址
VUE_APP_BASE_RUL = 'http://localhost:8080/

生产环境

# 生产环境
NODE_ENV = 'production'

# 生产环境,api前缀
VUE_APP_BASE_API = '/prod-api'

# 生产环境,Url地址
VUE_APP_BASE_RUL = 'http://116.62.57.216:8888/

image.png

终端运行 npm run build:prod 会在当前项目目录中生成dist文件夹 image.png

5、撰写 Dockerfile 文件

通过ftp工具前端的 dist 文件夹和后端的 jar文件夹复制到远程服务器中

分别创建 backend 和 frontend 存放前后端的文件。

1. 撰写后端 Dockerfile

FROM java:8 #采用java:8 镜像
VOLUME /tmp 
ADD authority.jar authority.jar #将jar包加入到容器中
EXPOSE 8888 #声明 8888 端口
ENTRYPOINT ["java","-jar","/authority.jar"] #容器默认参数

2. 撰写前端 Dockerfile

FROM nginx:latest #采用nginx: latest镜像
COPY ./dist /usr/share/nginx/html/  #将dist文件夹复制到ngnix对应目录里
COPY nginx.conf /etc/nginx/nginx.conf #将自定义nginx.conf替换原有conf(可不要)
EXPOSE 80 #声明 80 端口

后续会贴出 nginx.conf 的内容,以为在解决前端跨域的问题时,很多人贴出来的nginx.conf都是混乱零散的。 如果你是前端或后端精通者,可以无需查看

6、运行容器

1. 运行后端容器

# cd 到后端的Dokerfile文件目录下
cd backend
# 打包镜像,名称为 authority
docker build -t authority .
# 依据名称为 authority 的运行容器,容器内外端口都是8888;命名为authority-8888
docker run -d -p 8888:8888 --name authority-8888 authority

2. 运行前端容器

# cd 到后端的Dokerfile文件目录下
cd frontend
# 打包镜像,名称为 authority-ui
docker build -t authority-ui .
# 依据名称为 authority-ui 的运行容器,容器内外端口都是80;命名为 authority-ui3
docker run -d -p 80:80 --name authority-ui3 authority-ui

image.png

image.png

7. 前后端跨域

因为本人还在学习后端,是前端小白;在用ngnix解决跨域问题时,卡了很久。 因为生产环境的url 为 /prod-api 但是我在配置ngnix.conf 一直未生效; 后来发现,我将后端的serve和前端的serve写在一起;分成2个serve就好了。。。不知道原理,如果查找很多资料依旧没解决,可以采用这种方式试试。

ngnix.conf

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }

        location / {
			root html/build;
			index index.html index.htm;
			try_files $uri /index.html;  # try_files:检查文件; $uri:监测的文件路径; /index.html:文件不存在重定向的新路径
        }

    }
    server {
        listen       80;
        server_name 116.62.57.216;

        root         /usr/share/nginx/html;

        location /prod-api {
            # 把 /prod-api 路径下的请求转发给真正的后端服务器
            proxy_pass http://xx.xx.xx.xx:8888/authority;

            # 把host头传过去,后端服务程序将收到your.domain.name, 否则收到的是localhost:8888
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;

            # 把cookie的path部分从localhost:18080替换成your.domain.name
            # proxy_cookie_domain 116.62.57.216:8888 tosim.top;
        }

    }


# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }
}