Dokcer + nginx + Gitee Go 实现一键化部署你的项目(保姆级别)

1,570 阅读10分钟

- 什么是CICD

是指持续集成、持续发布,是⼀套实现软件的构建测试部署的⾃动化流程。

  • 什么是DevOps

    • ⼀词是由英⽂ Development(开发)和 Operations (运维)组合⽽成

    • ⼀种思想,强调软件开发测试运维的⼀体化,减少各个部⻔之间的沟通成本从⽽实现软件的快速⾼质ᰁ的发布

    • DevOps与CICD紧密相关,DevOps要实现⼈员⼀体化,须要借助CICD⼯具来⾃动化整个流程

    • 通俗易懂的话

      • DevOps是 开发+测试+运维 交集
      • 以前是单⼀职责 现在⼀专多能 考虑配合提效,
      • CI/CD 多环境-构建-打包-测试-上线-监控
      • 快速迭代产品,每次代码的改动都触发校验,每刻都可进⾏新版本的上线

为什么要使用Gitee Go?

  • 项目部署需要使用docker-compose同时运行多个容器

  • 配置简单,构建部署速度较快

  • Github Actions由于需要科技上网,不过两者的使用大同小异

  • Jenkins是什么

    • Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成
    • 官方地址:www.jenkins.io/

 

  • 两者的优缺点

     Gitee GoJenkins
    是否安装不需要安装,直接使用使用该服务需要安装
    执行特点异步CI/CD执行打包、构建等操作时同步的
    兼容性兼容任何环境需要运行环境兼容的Docker镜像

前后端项目代码自动化部署流程图

image.png

开通gitee go

image.png

Docker

如何生成或者构建一个镜像呢?

  • Dockerfile

    • 定义

      Dockerfile是由一系列指令和参数构成的脚本文件,也即是docker中镜像的的描述文件 一个Dockerfile里面包含了构建整个镜像的完整命令,通过docker build执行Dockerfile中的一系列指令自动构建镜像

      Dockerfile就是需要将一堆零散待执行的命令和参数整理到一个脚本文件,我们通过命令docker build执行后生成一个镜像

      Dockerfile

  • 官方网址:docs.docker.com/engine/refe…

  • 配置

    • FROM          # 基础镜像,依赖哪个镜像构建
    
    
    • MAINTAINER    # 镜像维护者的姓名
    
    
    • RUN           # 容器构建时运行的命令
    
    
    • CMD           # 容器启动时运行的命令
    
    
    • EXPOSE        # 对外保留的端口
    
    
    • ENV           # 设置环境变量
    
    
    • ADD           # 将宿主机的文件复制到镜像
    
    
    • COPY          # 用法和ADD类似,会自动解压文件
    
    
    • ENTRYPOINT    # 用法和CMD类似
    
    
    • VOLUME        # 用于数据保存和持久化工作
    
    
    • USER          # 指定运行容器时的用户名
    
    
    • WORKDIR       # 配置工作目录
    
    
    • ONBUILD       # 被作为基础镜像时执行的命令
    
  • 实例

    FROM node:16-alpine
    
    
    #复制文件
    RUN mkdir /app
    ADD backend/ /app
    WORKDIR /app
    
    
    # 安装
    RUN npm set registry https://registry.npmmirror.com
    RUN yarn install
    RUN npm i pm2 -g
    
    
    # 启动
    EXPOSE 8081
    CMD ["pm2-runtime","start","ecosystem.config.js"]
    

Dockerfile配置构建前端next项目镜像

我是直接使用next脚手架所以直接使npm run build 进行项目的打包

dockerfile

# frontend.build.Dockerfile
FROM node:16-alpine

# 复制文件
RUN mkdir /app
ADD frontend/ /app
WORKDIR /app

# 安装
RUN npm set registry https://registry.npmmirror.com
RUN npm install
RUN npm run build
RUN npm i pm2 -g

# 启动
EXPOSE 3000
# docker中监测不到pm2后台运行,需要用pm2-runtime命令运行
CMD ["pm2-runtime","start","ecosystem.config.js"]

具体的步骤如下:

  1. 使用基于 Node.js v16 的 Alpine 镜像作为基础镜像。
  2. 创建一个名为 /app 的目录,并将本地的 frontend/ 目录中的内容复制到容器的 /app 目录中。
  3. 将容器的工作目录设置为 /app
  4. 修改默认的 npm 源为 https://registry.npmmirror.com,加快安装依赖的速度。
  5. 运行 npm install 命令,安装项目依赖。
  6. 运行 npm run build 命令,构建前端应用。
  7. 使用 -g 参数全局安装 pm2
  8. 暴露容器的 3000 端口。
  9. 使用 pm2-runtime 命令运行项目的启动脚本 ecosystem.config.js

在 Docker 容器内运行该 Dockerfile,即可构建并运行前端应用。

需要注意的是,该示例假设项目中已经有 frontend/ 目录和相应的配置文件,并且使用了 pm2 进行应用的管理和启动。如果你的项目结构和配置不同,或者使用其他方式进行应用启动,可能需要对 Dockerfile 进行适当的修改。

  • pm2是为了使node可以在服务器中持久化的运行

ecosystem.config.js

/**
 * pm2运行的配置文件 ecosystem.config.js
 */
module.exports = {
  apps: [
    {
      name: "frontend-course-pc", // 项目名字
      exec_mode: "cluster", // 生产模式
      instances: "max", // 全功率运行
      script: "./.next/server/app/page.js", // 执行的入口文件
    },
  ],
};
docker build -f frontend.build.Dockerfile . -t frontend-course-image


# -f 指定构建文件
# . 指定当前路径
# -t 设置镜像名
# 如果运行报错,可以重启docker

注意:项目的文件路径不应该有中文名,否则打包会发出错误

Dockerfile配置构建后端node项目镜像

  • 后端项目Dockerfile配置
FROM node:16-alpine
#复制文件
RUN mkdir /app
ADD backend/ /app
WORKDIR /app


# 安装
RUN npm set registry https://registry.npmmirror.com
RUN yarn install
RUN npm i pm2 -g


# 启动
EXPOSE 8081
CMD ["pm2-runtime","start","ecosystem.config.js"]
  • pm2运行的配置文件
module.exports = {
  apps: [
    {
      name: 'backend-course-pc',
      exec_mode: 'cluster',
      instances: 'max',
      script: './app.js'
    }
  ]
}
  • 后端项目Dockerfile调试运行

    • 执行构建命令
docker build -f backend.build.Dockerfile . -t backend-course-image

nginx反向代理配置和Dockerfile构建nginx镜像

你知道什么是nginx反向代理服务器吗?

  • 反向代理服务器

    • 客户端和目标服务器之间的服务器,客户端向代理发送一个请求,然后代理向目标服务器请求并获得内容,并返回给客户端。反向代理隐藏了真实的服务器
    • 核心:客户端不知道要访问的目标服务器是哪台服务器,代理会根据一定的策略选择一个真实的服务器进行请求
    • 场景:访问淘宝,知道访问的域名是taobao.com, 但是后面提供数据的具体是什么域名或ip我们是不知道的

image.png

正向代理

  • 客户端和目标服务器之间的服务器,客户端向代理发送一个请求指定目标服务器,然后代理向目标服务器请求并获得内容,并返回给客户端
  • 核心:用户知道自己访问的目标服务器
  • 场景:访问原来无法访问的网站,比如国外的一些站点(科技上网)

image.png

  • nginx反向代理服务器作用

    • 负载均衡
    • 静态文件服务器
    • 支持多种协议https、POP3(邮件代理服务器)

 

 

前端next项目nginx反向代理配置

  • 配置文件 nginx.conf

    http {
      # 开启缓存
      etag on; 
    
    
      # 开启压缩 
      gzip on; 
      
      # 压缩的配置
      gzip_disable "msie6"; # 对IE6浏览器的数据不进行gzip压缩
      gzip_vary on; # 告诉接收方发送的数据经过了压缩处理,Accept-Encoding: gzip
      gzip_proxied any; # 无条件使用压缩 
      gzip_comp_level 6; # 压缩等级
      gzip_buffers 16 8k; # 压缩缓冲区
      gzip_http_version 1.1; # 压缩版本
      gzip_min_length 256; # 最小压缩文件大小
    
    
      # 压缩的格式
      gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
    
    
        # 负载均衡的配置
        upstream frontend {
          server 172.27.67.172:8080 weight=1;
        }
    
    
        # 指定监听服务端口
        server {
            listen 80;
            server_name frontend-course.xdproject.top;
            # 如果访问frontend-course.xdproject.top重定向到https://frontend-course.xdproject.top$1 $1保留原访问的路径、参数
            rewrite ^(.*)$ https://frontend-course.xdproject.top$1 permanent; 
        }
    
    
        # 指定监听服务443(https)端口
        server {
            listen       443 ssl;
            server_name  frontend-course.xdproject.top;
    
    
            # 访问https证书
            ssl_certificate_key  /etc/nginx/conf/ssl/9068112_frontend-course.xdproject.top.key;
            ssl_certificate      /etc/nginx/conf/ssl/9068112_frontend-course.xdproject.top.pem;
    
    
            # ssl_session_cache:缓存时间,ssl_session_timeout:超时时间
            ssl_session_cache    shared:SSL:1m;
            ssl_session_timeout  5m;
    
    
            # 加密配置 多个算法用:分隔,ALL表示全部算法,!表示不启用该算法,+表示将该算法排到最后面去
            ssl_ciphers  HIGH:!aNULL:!MD5;
            
            # 当为on时,服务器加密算法将优于客户端加密算法
            ssl_prefer_server_ciphers  on;
            
            # 反向代理
            location / {
                proxy_pass http://frontend/; # 请求的地址匹配到http://frontend/则在后面追加路径和参数
                proxy_buffering off; # 关闭代理缓冲
                proxy_set_header Host $host; # 代理的服务器通过host头得知用户访问的真正域名
                proxy_set_header X-Real-IP $remote_addr; # 获取用户真实的ip
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 获取所有的代理ip和客户的ip。
                proxy_set_header X-Forwarded-Proto https; # 转发使用https协议
            }
        }
    }
    
    
    # 每个进程的最大连接数
    events {
        worker_connections 1024; ## Default: 1024
    }
    

后端node项目nginx反向代理配置

  • 配置文件

    http {
      upstream backend {
        server 172.27.67.171:8081 weight=1;
      }
    
    
      server {
        listen 80;
        server_name  backend-course.xdproject.top;
        rewrite ^(.*)$ https://backend-course.xdproject.top$1 permanent;
      }
    
    
      server {
          listen       443 ssl;
          server_name  backend-course.xdproject.top;
    
    
          ssl_certificate_key  /etc/nginx/conf/ssl/9068114_backend-course.xdproject.top.key;
          ssl_certificate      /etc/nginx/conf/ssl/9068114_backend-course.xdproject.top.pem;
    
    
          ssl_session_cache    shared:SSL:1m;
          ssl_session_timeout  5m;
          
          ssl_ciphers  HIGH:!aNULL:!MD5;
          ssl_prefer_server_ciphers  on;
    
    
          location / {
              proxy_pass http://backend/;
              proxy_set_header X-Real-IP $remote_addr; # 获取用户真实的ip
              proxy_set_header X-Forwarded-For $remote_addr;
              proxy_set_header X-Client-Verify SUCCESS; # 解析证书的状态
              proxy_set_header Host $http_host;
              proxy_set_header X-NginX-Proxy true;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
              proxy_redirect off;
              proxy_buffering off;
          }
      }
    }
    
    
    events {
        worker_connections 1024; ## Default: 1024
    }
    

前端项目nginx镜像的构建

  • 镜像构建(主要进行替换conf文件和ssl证书)

backend.nginx.Dockerfile

```
FROM nginx:1.23.0-alpine


RUN mkdir -p /etc/nginx/conf/ssl # -p 创建多个层级的目录,如果某个目录不存在就创建


# 本地配置文件替换远程
ADD frontend/nginx.conf /etc/nginx/nginx.conf


# 本地SSL证书替换远程
ADD ssl/frontend/9068112_frontend-course.xdproject.top.key /etc/nginx/conf/ssl/9068112_frontend-course.xdproject.top.key
ADD ssl/frontend/9068112_frontend-course.xdproject.top.pem /etc/nginx/conf/ssl/9068112_frontend-course.xdproject.top.pem


# 开放端口
EXPOSE 80
```

后端项目nginx镜像的构建

  • 镜像构建
FROM nginx:1.23.0-alpine


RUN mkdir -p /etc/nginx/conf/ssl


# 本地配置文件替换远程
ADD backend/nginx.conf /etc/nginx/nginx.conf


# 本地SSL证书替换远程
ADD ssl/backend/9068114_backend-course.xdproject.top.key /etc/nginx/conf/ssl/9068114_backend-course.xdproject.top.key
ADD ssl/backend/9068114_backend-course.xdproject.top.pem /etc/nginx/conf/ssl/9068114_backend-course.xdproject.top.pem


# 开放端口
EXPOSE 80

域名映射+服务器IP绑定+SSL证书申请

SSL证书申请

image.png

image.png

域名解析

image.png

进行前后端服务器的相关配置

  • 登录服务器

    ssh -o ServerAliveInterval=60 root@120.78.146.74
    
  • 前后端服务器都需要安装的应用

    • Git服务安装

      yum install git
      
  • Dokcer安装(课程5-1的安装方式部分同学反馈安装不上)

    yum install docker
    
    
    #运行
    systemctl start docker
    
  • Docker-Compose安装

    yum install docker-compose
    

将代码内部访问本地127.0.0.1的地方换为线上地址

运行容器Docker-compose

Docker-compose是什么?

  • 定义

    是 Docker 推出的一个工具,可以管理多个容器组成一个应用服务;
    通过 YAML 格式的配置文件名为docker-compose.yml,提前编写好多个容器之间的创建和启动命令;
    最后只要一个命令,就能同时启动/关闭这些容器,方便管理容器
    

     

  • 官方文档地址:docs.docker.com/compose/com…

  • 举例

    • Docker-compose启动的命令

      // docker-compose.mysql.yml
      
      
      version: "3.0"
      services:               
         mysqldb:
           image: mysql:8.0
           restart: always
           container_name: xdclass_mysql
           volumes:
              - /usr/local/mysql/conf:/etc/mysql/conf.d
              - /usr/local/mysql/data:/var/lib/mysql
           environment:
             MYSQL_ROOT_PASSWORD: xdclass.net168
           ports:
             - 3306:3306
      
      
      version #docker-compose配置文件的版本,目前有三个版本,version 1将来会被弃用
      services #配置要启动的多个容器
        mysqldb #服务配置名
          image #指定服务的镜像名称或镜像ID,如果本地不存在则会在远程拉取
          restart #总是重启
          container_name #启动后的容器名
          volumes #容器的路径映射到宿主机,实现数据共享
          environment #配置环境变量
          ports #宿主机和容器的端口映射
      
  • 运行

      docker-compose -f docker-compose.mysql.yml up -d
      
      -f #指定运行的docker-compose配置文件
      up #启动命令
      -d #后台运行
    
  • 我们需要使用自己生成的镜像去运行

配置docker-compose文件运行前后端的容器

  • 前端配置文件编写

    // docker-compose.frontend.yml
    
    
    version: '3'
    services:
      frontend-course:
        image: frontend-course-image
        restart: always
        container_name: frontend-course
        ports:
          - 8080:3000
      frontend-course-nginx:
        image: frontend-course-nginx-image
        restart: always
        container_name: frontend-course-nginx
        ports:
          - 80:80
          - 443:443
    

 

  • 后端配置文件编写

    // docker-compose.backend.yml
    
    
    version: '3'
    services:
      backend-course:
        image: backend-course-image
        restart: always
        container_name: backend-course
        ports:
          - 8081:8081
      backend-course-nginx:
        image: backend-course-nginx-image
        restart: always
        container_name: backend-course-nginx
        ports:
          - 80:80
          - 443:443
    

配置前端+后端对应的服务器

image.png

image.png

image.png

image.png

image.png

执行之后

image.png

创建前端+后端项目的流水线

image.png

image.png

image.png

image.png

image.png

保存配置

输入自动化部署脚步命令

  • 前端自动化部署脚本
rm -rf /root/gitee_go/frontend || true
mkdir -p /root/gitee_go/frontend 
cd /root/gitee_go/frontend 
git clone https://39xxxxx%40qq.com:xxxxx@gitee.com/wen_zhao/xdclass-course-pc.git
cd xdclass-course-pc

# 清理之前的docker镜像和容器
docker stop frontend-course || true
docker stop frontend-course-nginx || true
docker rm frontend-course || true
docker rm frontend-course-nginx || true
docker rmi frontend-course-image || true
docker rmi frontend-course-nginx-image || true

# 打包构建
docker build -f frontend.build.Dockerfile . -t frontend-course-image
docker build -f frontend.nginx.Dockerfile . -t frontend-course-nginx-image

docker-compose -f docker-compose.frontend.yml up -d
  • 后端自动化部署脚本
rm -rf /root/gitee_go/backend || true
mkdir -p /root/gitee_go/backend 
cd /root/gitee_go/backend 
git clone https://1021199182%40qq.com:lwz.123456@gitee.com/wen_zhao/xdclass-course-pc.git
cd xdclass-course-pc


#删除上一次构建的镜像
docker stop backend-course || true
docker stop backend-course-nginx || true
docker rm backend-course || true
docker rm backend-course-nginx || true
docker rmi backend-course-image || true
docker rmi backend-course-nginx-image || true


#打包构建
docker build -f backend.build.Dockerfile . -t backend-course-image
docker build -f backend.nginx.Dockerfile . -t backend-course-nginx-image


docker-compose -f docker-compose.backend.yml up -d

image.png

image.png

这样项目就部署成功!