这篇文章以部署vue3项目和nuxt2项目为例结合github-action,docker,nginx等介绍不同的项目自动部署流程

2.gif

部署vue3项目

步骤:

1、腾讯云开启镜像仓库

2、github配置secrets

3、项目根目录创建dockerfile文件(在action工作流中创建镜像)

4、github配置action工作流(yml文件)

上面步骤执行结束后就能实现在本地push项目到github仓库后自动触发action执行自动部署到服务器

最主要的步骤就是配置action的yml工作流文件,这个文件包含接收到push指令后执行的所有自动部署的流程

接下来我以部署vue3项目为例一步一步详细介绍

1、腾讯云开启镜像仓库

首先登录腾讯云,搜索容器镜像服务,然后创建个人版实例(记住用户名和密码)

然后点击命名空间,点击创建,新建一个命名空间(命名空间名称随便取,命名空间就是存放镜像仓库的空间)

创建了命名空间后点击镜像仓库,然后点击新建创建镜像仓库,每一个镜像仓库可以存放多个镜像(这里我是把每个项目对应的docker镜像存放到一个单独的镜像仓库中)

注意创建的镜像仓库的地址,后面创建github的secrets会用到

tip:点击快捷指令可以看到自己仓库的用户名

2、github配置secrets

首先打开github对应的项目仓库,点击setting->Secrets->Actions

点击新建secret,对应一个name和value,新建的每个secret在后面的action的yml文件都会用到

列举一下我使用的几个secret:

DOCKER_REPOSITORY: 镜像仓库地址,也就是上面创建的镜像仓库镜像地址

DOCKER_USERNAME:登录docker镜像仓库的账号

DOCKER_PASSWORD: 登录docker镜像仓库的密码

HOST:部署项目的服务器ip

HOST_PORT:服务器ssh端口号(默认是22)

HOST_USERNAME:服务器登录用户名(一般为root)

HOST_PASSWORD: 登录服务器的密码

3、项目根目录创建dockerfile文件

项目根目录创建的dockerfile会在工作流执行时根据这个文件创建docker镜像

我的项目用到了nginx,所有还需要在项目根目录创建nginx的conf文件

(1)创建nginx

# ./nginx/blog-vue3.conf
server{
    listen 80;
    server_name haixtx.cn;
    #静态资源
    location / {
        root /usr/share/nginx/html/blog;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    #反向代理获取动态资源(解决跨域)
    location /api {
        proxy_pass http://haixtx.club/node;
    }
    # #静态资源缓开启缓存
    # location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
    # {
    #     expires 30d;
    # }
    # location ~ .*.(js|css)?$
    # {
    #     expires 12h;
    # }
}
# ./nginx/gzip.conf
# /etc/nginx/conf.d/gzip.confgzip on; # 默认off,是否开启gzip
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
​
gzip_static on;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_min_length 1k;
gzip_http_version 1.1;

(2)创建dockerfile

#nginx镜像
FROM nginx
LABEL name="blog-vue3"
LABEL version="latest"
# 新建nginx静态资源目录
RUN mkdir -p /usr/share/nginx/html/blog
# 将打包后的文件夹放在docker容器中的nginx静态资源文件夹目录下
COPY  ./dist/ /usr/share/nginx/html/blog
# 将项目根目录的nginx配置文件放在docker容器中的nginx子配置文件夹目录下
COPY ./nginx/blog-vue3.conf /etc/nginx/conf.d/
COPY ./nginx/gzip.conf /etc/nginx/conf.d/
# docker容器对外暴露端口号设置为80
EXPOSE 80

(3)创建.dockerignore忽略文件(生成docker镜像的时候不会打包的文件夹目录)

.git
node_modules
package-lock.json
Dockerfile
.dockerignore
4、github配置action工作流(yml文件)

还是在github的项目仓库中,点击Actions,选择nodejs后点击configure创建工作流

点击后开始编写yml文件,这个是整个部署阶段最重要的地方

在内容区域ctrl+a全选然后删除,粘贴进以下内容:

name: BlogVue3 Docker Image CI/CD
on:
  push:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest      
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: "16.x"
      - name: Install and Build
        run: |
          npm install
          npm run build
      - name: Build Image
        run: docker build -t ${{ secrets.DOCKER_REPOSITORY }}:latest ./
      - name: Login to registry
        run: docker login ccr.ccs.tencentyun.com --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
      - name: Push Image
        run: docker push ${{ secrets.DOCKER_REPOSITORY }}:latest
  pull-docker:
    needs: [build]
    name: Pull Docker
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.HOST_USERNAME }}
          password: ${{ secrets.HOST_PASSWORD }}
          port: ${{ secrets.HOST_PORT }}
          script: |
            docker stop $(docker ps --filter ancestor=${{ secrets.DOCKER_REPOSITORY }} -q)
            docker rm -f $(docker ps -a --filter ancestor=${{ secrets.DOCKER_REPOSITORY }}:latest -q)
            docker rmi -f $(docker images ${{ secrets.DOCKER_REPOSITORY }}:latest -q)
            docker login ccr.ccs.tencentyun.com --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
            docker pull ${{ secrets.DOCKER_REPOSITORY }}:latest
            docker run -d -p 8000:80 ${{ secrets.DOCKER_REPOSITORY }}:latest

整个yml文件需要严格遵循yml文件的格式,下面来一遍上面代码的注释

name: BlogVue3 Docker Image CI/CD  # workflow名称,可以随意改
on:   # workflow的事件钩子,告知程序什么时候出发自动部署
  push:
    branches: [ master ]   # 在master分支有push操作的时候自动部署
jobs:
  # 第一个工作-build
  build:  # 打包并上传docker镜像
    runs-on: ubuntu-latest   # 依赖的环境,注意:actions提供的linux环境只有ubuntu
    steps:
      # 使用actions/checkout@v2获取项目中的代码(name是阶段名,可以随便填,每一个name必须对应一个run/uses)
      - name: Checkout
        uses: actions/checkout@v2
      # 下载node版本环境
      - name: Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: "16.x"
      # 下载项目依赖并打包(如果上传了package-lock.json文件到github仓库,注意依赖包的源地址,我这里本地npm源地址是公司内网,所以lock文件里面有的依赖包地址也是公司内网,这时github执行install就会请求失败)
      - name: Install and Build
        run: |
          npm install
          npm run build
      # 创建docker镜像
      - name: Build Image
        # ${{ secrets.DOCKER_REPOSITORY }}是读取之前在Secret创建的名为DOCKER_REPOSITORY的值
        # 从项目根目录的dockerfile文件创建docker镜像
        run: docker build -t ${{ secrets.DOCKER_REPOSITORY }}:latest ./
      # 登录刚刚创建的腾讯云docker镜像仓库
      - name: Login to registry
        run: docker login ccr.ccs.tencentyun.com --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
      # 将镜像提交到镜像仓库
      - name: Push Image
        run: docker push ${{ secrets.DOCKER_REPOSITORY }}:latest
  # 第二个工作-pull-docker
  pull-docker:
    needs: [build]
    name: Pull Docker
    runs-on: ubuntu-latest
    steps:
      # 登录腾讯云服务器并将docker镜像仓库的镜像pull下来后启动新容器
      - name: Deploy
        # 使用appleboy/ssh-action@master完成ssh登录服务器
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.HOST_USERNAME }}
          password: ${{ secrets.HOST_PASSWORD }}
          port: ${{ secrets.HOST_PORT }}
          # 登录上服务器后执行的代码步骤(停止旧容器->删除旧容器->删除旧镜像->登录镜像仓库->pull新镜像->利用新镜像启动新容器)
          script: |
            docker stop $(docker ps --filter ancestor=${{ secrets.DOCKER_REPOSITORY }} -q)
            docker rm -f $(docker ps -a --filter ancestor=${{ secrets.DOCKER_REPOSITORY }}:latest -q)
            docker rmi -f $(docker images ${{ secrets.DOCKER_REPOSITORY }}:latest -q)
            docker login ccr.ccs.tencentyun.com --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
            docker pull ${{ secrets.DOCKER_REPOSITORY }}:latest
            docker run -d -p 8000:80 ${{ secrets.DOCKER_REPOSITORY }}:latest

总结:

上述配置完成后,本地push代码到仓库,仓库就会触发配置的actions工作流执行yml中提取配置好的步骤:

第一步先在github中将项目下载依赖后打包,然后根据打包内容及dockerfile创建镜像并上传到镜像仓库

第二步登录服务器后删除旧镜像旧容器,登录镜像仓库拷贝新镜像,再通过新镜像启动新容器

至此就完成了项目的自动部署

部署nuxt2项目

部署nuxt2项目主体流程和上面部署vue3一样,但是也存在一些不同的地方,主要就是docker容器的创建及启动

部署vue3项目的docker容器只存在nginx镜像,但是部署nuxt2项目的docker容器要存在node和nginx,所以nuxt2项目的docker镜像是基于node镜像创建,但是在创建过程中需要安装nginx

node环境是因为nuxt会启动后端服务来监听请求并整合请求对应资源返回html给浏览器,需要npm命令,nginx是因为在docker中启动nuxt项目后会启动后端服务,后端服务在127.0.0.1本地ip下,需要nginx代理转发请求到启动的127.0.0.1服务下

注: 部署nuxt项目和部署vue项目不同,vue项目只需build打包后把dist静态资源文件放在服务器中通过nginx代理就行,而nuxt不仅要build打包,还需要启动后端服务来监听浏览器的请求并从打包的文件中整合资源为html并返回给浏览器,所以部署nuxt项目既需要build打包项目,又需要执行start命令启动nuxt项目(启动后端服务)

直接放nuxt2项目的dockerfile

# node服务器
FROM node:16.14.2
LABEL name="blog-nuxt2"
LABEL version="latest"
RUN mkdir -p /usr/src
COPY . /usr/src
# 安装nginx(docker创建的默认都是debian系统的容器,安装命令为apt而不是yum)
RUN apt-get update
# 加上-y遇到确认会继续执行
RUN apt-get install nginx -y
COPY ./nginx/blog-nuxt2.conf /etc/nginx/conf.d/
COPY ./nginx/gzip.conf /etc/nginx/conf.d/
WORKDIR /usr/src
RUN npm install
RUN npm run build
EXPOSE 82
# 执行脚本命令
CMD sh ./nginx.sh

上面的dockerfile需要用到的其他文件及注意点:

1、dockerfile需要用到nginx对启动的nuxt项目进行端口的反向代理,nuxt2项目启动后也是类似于node启动的后端项目,但是需要注意:

node启动的项目(node app.js)在服务器可以直接通过服务器ip+端口访问,但是nuxt启动的项目(npm start)不能直接访问,需要nginx代理一下才能访问

# ./nginx/blog-nuxt2.conf
server{
    # 监听docker容器内部的82端口
    listen 82;
    server_name haixtx.cn;
    # 将82端口反向代理到启动的nuxt端口4000
    location / {
        proxy_pass http://127.0.0.1:4000;
    }
}

2、首先简要说明一下RUN和CMD的区别

相同点,都是执行命令,不同点在于,RUN 是在打包镜像的时候执行,CMD是在运行容器的执行

dockerfile的CMD可以执行多次,但是只会以最后一次为准,也就是说只能存在一个CMD,但是nuxt的docker需要在容器被创建时执行npm start启动nuxt项目,还需要重载docker容器内部的nginx(因为更新了nginx的配置项),所以需要CMD执行两个命令,我在这里使用的方法就是在项目根目录新建一个sh脚本,再CMD命令通过sh执行这个脚本达到执行多条命令的目的

# nginx.sh
nginx -c /etc/nginx/nginx.conf
nginx -s reload
npm start

CMD执行这个脚本就会在创建docker容器时在容器内部重载nginx并启动nuxt2项目

3、注意点:在install安装命令后加上-y会在安装过程中遇到是否继续执行(y/n)时选择继续执行比如上面安装nginx:apt-get install nginx -y

补充:放几个我经常用但是又经常忘的linux-centos系统命令

1、netstat -ntulp | grep 80 查看端口占用情况

2、安装curl查看网址返回内容yum -y install curl

curl http://localhost:3000/

3、docker exec -it 容器名 /bin/bash 进入docker容器

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐