Dokcer + nginx + Gitee Go 实现一键化部署你的项目

发布时间 2023-11-30 14:53:11作者: 柯基与佩奇

- 什么是 CICD

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

  • 什么是 DevOps

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

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

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

    • 通俗易懂的话

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

为什么要使用 Gitee Go?

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

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

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

  • Jenkins 是什么

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

    Gitee Go Jenkins
    是否安装 不需要安装,直接使用 使用该服务需要安装
    执行特点 异步 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(邮件代理服务器)
  • nginx 官网配置地址:www.nginx.com/resources/w…

前端 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,提前编写好多个容器之间的创建和启动命令;
    最后只要一个命令,就能同时启动/关闭这些容器,方便管理容器
    
  • 官方文档地址:

  • 举例

    • 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

这样项目就部署成功!