发布于 2026-01-05 5 阅读
0

使用 Github actions 和 Docker 将 Next.js 应用程序部署到 VPS DEV 的全球展示与讲述挑战赛,由 Mux 呈现:展示你的项目!

使用 GitHub Actions 和 Docker 将 Next.js 应用部署到 VPS

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

最近,我需要将一个项目部署到 DigitalOcean 服务器上。我非常希望这个项目能够实现的一个功能是持续交付流水线。

持续交付网站将其定义为

能够以可持续的方式,安全、快速地将各种类型的变更(包括新功能、配置变更、错误修复和实验)投入生产环境或交付给用户。

目标是使部署(无论是大规模分布式系统、复杂的生产环境、嵌入式系统还是应用程序)成为可预测的、例行的事情,并可按需执行。

就我而言,我希望每当我向主GitHub分支推送更改时,Web应用程序都能自动部署到VPS上。这样就能节省大量的开发时间。

替代方案

还有其他更便捷的解决方案,例如VercelDigitalOcean 应用平台。但是,如果符合以下条件,您也可以选择我的方法:

  1. 你想更好地了解 GitHub Actions
  2. 了解更多关于 Docker 的信息
  3. 以 Vercel 为例,您的客户或组织可能希望将他们的应用程序保存在一个中央平台上,以便于管理。

先决条件

请注意,以下部分链接为联盟链接,您无需支付任何额外费用。我只会推荐我亲自使用过且真心认为有用的产品、工具和学习服务。最重要的是,我绝不会建议您购买超出您经济能力范围或您尚未准备好实施的产品。

  1. 一个GitHub 帐户
  2. 一台虚拟专用服务器。我使用的是 DigitalOcean 的服务器,运行的是 Ubuntu 20.04 LTS。使用我的推荐链接注册,即可获得 100 美元信用额度,有效期为 60 天。

创建 Next.js 应用

我们将使用 npx 创建一个标准的 Next.js 应用

npx create-next-app meta-news && cd meta-news
Enter fullscreen mode Exit fullscreen mode

进入项目目录后,我们将安装一些依赖项以进行演示。

yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 axios
Enter fullscreen mode Exit fullscreen mode

我们还将在.env.local文件中声明环境变量。然后,我们可以像这样在应用程序中引用这些变量。process.env.NEXT_PUBLIC_VARIABLE_NAME

NEXT_PUBLIC_BACKEND_URL=http://localhost:8000/api
NEXT_PUBLIC_META_API_KEY=your_api_key
Enter fullscreen mode Exit fullscreen mode

这些变量仅用于演示目的,因此我们的应用程序实际上不会引用它们。例如,在实例化 axios 实例或设置 Google Analytics ID 时,如果您不想将这些信息提交到版本控制系统,则可能会用到它们。

localhost:3000我们来做个快速测试。如果一切设置正确,应用程序应该可以运行。

yarn start
Enter fullscreen mode Exit fullscreen mode

将应用程序容器化

Docker 是一款开源工具,它可以自动将应用程序部署到软件容器中。这些容器类似于虚拟机,但更具可移植性、资源占用更少,并且对宿主机操作系统的依赖性更高。要了解有关 Docker 工作原理的详细信息,我建议阅读这篇文章。对于那些不习惯阅读长篇文章的人,YouTube 上的这个教程系列对介绍 Docker 的概念特别有帮助。


touch Dockerfile我们将通过在命令行界面中运行命令,将 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 update && apk add --no-cache libc6-compat && apk add git
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --immutable


# Rebuild the source code only when needed
FROM node:alpine AS builder
# add environment variables to client code
ARG NEXT_PUBLIC_BACKEND_URL
ARG NEXT_PUBLIC_META_API_KEY


ENV NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL
ENV NEXT_PUBLIC_META_API_KEY=$NEXT_PUBLIC_META_API_KEY

WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
ARG NODE_ENV=production
RUN echo ${NODE_ENV}
RUN NODE_ENV=${NODE_ENV} yarn build

# Production image, copy all the files and run next
FROM node:alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# You only need to copy next.config.js if you are NOT using the default configuration. 
# Copy all necessary files used by nex.config as well otherwise the build will fail

COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/pages ./pages

USER nextjs

# Expose
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.
ENV NEXT_TELEMETRY_DISABLED 1
CMD ["yarn", "start"]
Enter fullscreen mode Exit fullscreen mode

这次部署我们采用的是多阶段构建
。 注意到 ARG 和 ENV 关键字了吗?因为我们无法访问.env容器内的任何文件,所以我们需要通过它们将环境变量传递给客户端代码。稍后会详细介绍。

然后我们将构建并标记我们的图像

docker build --build-arg NEXT_PUBLIC_BACKEND_URL=http://localhost:8000/api --build-arg NEXT_PUBLIC_META_API_KEY=your_api_key -t meta-news .
Enter fullscreen mode Exit fullscreen mode

这可能需要一些时间,具体取决于您的网络连接和硬件配置。
一切检查完毕后,运行容器。

docker run -p 3000:3000 meta-news
Enter fullscreen mode Exit fullscreen mode

启动浏览器,您应该可以通过“ http://localhost:3000 ”访问您的应用🎉

设置 GitHub Actions

GitHub Actions 是一个持续集成和持续交付 (CI/CD) 平台,可用于自动化构建、测试和部署流程。您可以创建工作流,对仓库中的每个拉取请求进行构建和测试,或者将合并后的拉取请求部署到生产环境。

想了解更多关于这个优秀平台的信息,请访问他们的官方教程页面。

我们将通过在命令行界面 (CLI) 中运行以下命令来创建第一个工作流程。如果您不熟悉命令行,也可以使用图形用户界面 (GUI) 🤗。

mkdir .github && mkdir ./github/workflow && touch ./github/workflows/deploy.yml && nano ./github/workflows/deploy.yml
Enter fullscreen mode Exit fullscreen mode

请在 deploy.yml 文件中填充以下值。

name: Build and Deploy

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    container: node:14

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Build and Publish to Github Packages Registry
        uses: elgohr/Publish-Docker-Github-Action@master
        env:
          NEXT_PUBLIC_BACKEND_URL: ${{ secrets.APP_NEXT_PUBLIC_BACKEND_URL }}
          NEXT_PUBLIC_META_API_KEY: ${{ secrets.APP_NEXT_PUBLIC_META_API_KEY }}
        with:
          name: my_github_username/my_repository_name/my_image_name
          registry: ghcr.io
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets. GITHUB_TOKEN }}
          dockerfile: Dockerfile
          buildargs: NEXT_PUBLIC_BACKEND_URL,NEXT_PUBLIC_META_API_KEY
          tags: latest

      - name: Deploy package to digitalocean
        uses: appleboy/ssh-action@master
        env:
          GITHUB_USERNAME: ${{ secrets.USERNAME }}
          GITHUB_TOKEN: ${{ secrets. GITHUB_TOKEN }}
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          port: ${{ secrets.DEPLOY_PORT }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_KEY }}
          envs: GITHUB_USERNAME, GITHUB_TOKEN
          script: |
            docker login ghcr.io -u $GITHUB_USERNAME -p $GITHUB_TOKEN
            docker pull ghcr.io/my_github_username/my_repository_name/my_image_name:latest
            docker stop containername
            docker system prune -f
            docker run --name containername -dit -p 3000:3000 ghcr.io/my_github_username/my_repository_name/my_image_name:latest

Enter fullscreen mode Exit fullscreen mode

您可能已经注意到我们的操作非常隐秘😂。别担心,这是为了保护您的敏感信息不被窥探而特意采取的措施。这些是您(仓库所有者)为使用 GitHub Actions 的仓库创建的加密环境变量。

需要注意的是,运行此操作时,系统GITHUB_TOKEN自动为我们创建密钥。

要创建密钥,请转到您的存储库 > 设置 > 左侧边栏 > 密钥
秘密的创造

如需详细步骤,请参阅本指南

预期的 GitHub 密钥是

APP_NEXT_PUBLIC_BACKEND_URL - live backend server url
APP_NEXT_PUBLIC_META_API_KEY - prod api key to thirdparty integration
DEPLOY_HOST - IP to Digital Ocean (DO) droplet
DEPLOY_KEY - SSH secret (pbcopy < ~/.ssh/id_rsa) and the public key should be added to `.ssh/authorized_keys` in server
DEPLOY_PORT - SSH port (22)
DEPLOY_USER  - User on droplet
USERNAME - Your Github username
Enter fullscreen mode Exit fullscreen mode

起飞🚀

推送到主分支

git add -A
git commit -m "Initial commit"
git push origin main
Enter fullscreen mode Exit fullscreen mode

如果一切运行正常,您应该会在仓库中看到一个绿色对勾,表示构建步骤已完成。

Github_actions_deploy

从那里,您可以在服务器中设置反向代理(例如 nginx),并将主机指向“ http://localhost:3000 ”。

太棒了!🥳 我们已经成功创建了持续交付管道,希望现在您可以专注于代码而不是基础设施。

如有任何疑问,请随时在推特上联系我
如果您有任何反馈或补充意见,请在下方留言。

无耻的广告

你需要进行大量的数据挖掘吗?

Scraper API 是一家专注于提供安全策略的初创公司,旨在减轻您在进行网络爬虫时 IP 地址被封禁的担忧。他们利用 IP 地址轮换技术来规避检测。该公司拥有超过 2000 万个 IP 地址和无限带宽。

除此之外,他们还提供验证码处理功能,并支持无头浏览器,让您看起来像个真实用户,不会被检测为网络爬虫。它集成了 Python、Node.js、Bash、PHP 和 Ruby 等常用平台。您只需在 HTTP GET 请求中将目标 URL 与其 API 端点连接起来,然后像使用其他网络爬虫一样继续操作即可。不知道如何进行网络爬虫?别担心,我在网络爬虫系列教程
中详细讲解过这个主题。所有内容完全免费!

爬虫 API

使用我的 scraperapi 推荐链接和优惠码 lewis10,首次购买即可享受 10% 的折扣!您可以先使用他们慷慨的免费套餐,需要时再升级。

文章来源:https://dev.to/lewiskori/deploying-nextjs-apps-to-a-vps-using-github-actions-and-docker-564n