基于Docker与Github Actions的Next.js自动部署

2,054 阅读2分钟

如果前端是React项目,不用这样配置,使用scp的Action部署到服务器中即可。

前置知识

在读本文之前,需要对以下概念有所简单的了解。

目标进度

  • 在Github Actions中build Docker镜像并push到阿里ACR。
  • 在Github Actions中使用SSH链接阿里ECS,pullrun镜像。
  • ACR中自动删除过期版本的镜像。
  • 服务器中自动删除过期版本的镜像。
  • 构建缓存。
  • 配置docker的network与其他容器交互。

主要流程

  1. 本地使用git push origin main命令。
  2. Github Actions根据根目录的.github/workflows下的yaml文件的配置进行jobs操作。

Dockerfile

# Install dependencies only when needed
FROM node:alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /information-manage-com
COPY package.json yarn.lock ./
RUN yarn config set registry https://registry.npm.taobao.org/
RUN yarn install --frozen-lockfile

# Rebuild the source code only when needed
FROM node:alpine AS builder
WORKDIR /information-manage-com
COPY . .
COPY --from=deps /information-manage-com/node_modules ./node_modules
RUN yarn build

# Production image, copy all the files and run next
FROM node:alpine AS runner
WORKDIR /information-manage-com

ENV NODE_ENV production

# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /information-manage-com/next.config.js ./
COPY --from=builder /information-manage-com/public ./public
COPY --from=builder /information-manage-com/.next ./.next
COPY --from=builder /information-manage-com/node_modules ./node_modules

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
RUN chown -R nextjs:nodejs /information-manage-com/.next
USER nextjs

EXPOSE 3000

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry.
# RUN npx next telemetry disable

CMD ["node_modules/.bin/next", "start"]d

Next.js的docker官方配置,我在其中加了npm的国内镜像。

build-docker

创建了两个job,依此是build-docker功能是构建dockerpushDocker Hub或阿里ACR

build-docker:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        ref: main
    - name: Login to ACR
      uses: aliyun/acr-login@v1
      with:
        login-server: <ACR 公网路径>
        username: "${{ secrets.ACR_USERNAME }}"
        password: "${{ secrets.ACR_PASSWORD }}"
    - name: Build and push image
      env:
        IMAGE_TAG: ${{ github.sha }}
      run: |
        docker build -t <ACR 公网路径>/<ACR namespace>/<ACR iamges name>:$IMAGE_TAG .
        docker push <ACR 公网路径>/<ACR namespace>/<ACR iamges name>:$IMAGE_TAG

其中涉密信息可以放在github项目的setting中设置secrets。项目中就可以使用${{ secrets.<你设置的键> }}${{ github.sha }}代表这次提交的独一无二的id可用做dockertag。其次使用了两个Action,具体参数参考文档。

ecs-pull

  ecs-pull:
    needs: build-docker
    runs-on: ubuntu-latest
    steps:
    - name: Execute SSH commmands on remote server
      uses: fifsky/ssh-action@master
      with:
        user: root
        host: "${{ secrets.ECS_HOST }}"
        key: ${{ secrets.ECS_PRIVATE_KEY }}
        command: |
          cd /
          docker login --username=${{ secrets.ACR_USERNAME }} --password=${{ secrets.ACR_PASSWORD }} <ACR 公网路径>
          docker pull <ACR 公网路径>/<ACR namespace>/<ACR iamges name>:${{ github.sha }}
          docker run -p 80:3000 -d <ACR 公网路径>/<ACR namespace>/<ACR iamges name>:${{ github.sha }}

注意:其中的key是服务器生成的私钥(全文复制,不只复制中间部分),而且需要将与这私钥一起生成的公钥放到授权文件中(阿里云就是authorized_keys)。 其中的needs代表此job需要等待build-docker完成才执行。否则会并行处理jobs。 其中的Action官方文档如下:

横向对比

肤浅的对比:使用自己服务器的Jenkins与其他网站的Web Hook联动也能做到自动部署,但Jenkins需要耗费自己的服务资源。而GitHub Actions提供了免费的服务资源。而且不使用Docker的话需要在自己的服务器上安装配置一堆的服务非常麻烦,易错。