前言
最近做的一个网站流量稍微起来一些了,把Vercel的免费额度用完了,为了让网站正常运转,开了Vercel的Pro,一个月20刀,有点小贵,就琢磨琢磨着自部署省点钱。
研究了两天把整个流程跑通了,还有一些踩坑的点,记录一下帮助下有同样需求的人。
服务器设置
要自部署得先有一台服务器,官方推荐服务器至少要2G的内存和30G的磁盘空间。
To ensure a smooth experience with Dokploy, your server should have at least 2GB of RAM and 30GB of disk space. This specification helps to handle the resources consumed by Docker during builds and prevents system freezes. 官方安装文档
我在腾讯云买了一台199/年(差不多一个多月Vercel的订阅费用)的在硅谷的2核4G内存60G磁盘的机器,海外机器部署服务不用备案,不用担心买国内云服务商的机器需要备案,不过这个机器每个用户限购一台,对我来说够用了,想要参考的也可以看看。
服务器的系统按官方的推荐选择了Ubuntu 22.04 LTS。
部署Dokploy
直接执行脚本安装Dokploy:
arduino
curl -sSL https://dokploy.com/install.sh | sh
安装完成后,需要在防火墙打开3000端口,如下配置即可:

然后访问: http://你服务器的ip:3000

设置你的管理员的账号密码即可。
如果不想通过ip访问也可以绑定域名,点击左侧的Web Server设置你的域名即可,这个地方可以使用你某个域名的子域名即可。
然后在你的域名DNS解析中增加一条A记录,把对应的子域名解析到服务器IP。

这样就可以直接通过子域名访问Dokploy的管理界面了。
项目部署
Dokploy部署完成后,可以开始部署项目了。
Github配置
首先配置需要配置好Git仓库,方便Dokploy去拉取代码部署。
点击左侧的Git菜单,选择Github,点击创建Github App。

创建完成后,点击去授权,并选择你需要的仓库或者所有仓库,这样Dokploy就能获取Github的代码仓库了。

接下来还需要配置一下Github token和Registry,这个配置是为了让Dokploy能从Github拉取你使用Github Actions构建的镜像进行部署,推荐使用这种方式,这样可以避免使用你的服务器进行打包镜像,减轻你服务器的压力,要是你服务器很屌可以不用操作这个配置,直接在服务器上构建部署就行。
首先需要新建一个Github Token,然后勾选write:packages权限,创建Token的URL:
然后复制Token,到Dokploy中点击左侧Registry菜单,点击新增,username是你的Github账号吗,Password是刚才复制的Token,Registry URL是:ghcr.io

项目创建及部署
在Dokploy管理后台的Projects中先创建Project再创建Service,Service才是对应的Vercel中的项目,Dokploy的Project下可以有多个Service。

接下来就可以部署了。
Github Actions构建,Dokploy部署(推荐)
先讲比较推荐的部署方式,使用Github Actions构建镜像,然后Dokploy使用Docker Provider的方式部署。
这种方式镜像的构建不在你的服务器上,而是白嫖了Github Actions来帮忙构建,对于配置不高的服务器来说很有用。
首先需要在你要部署的代码仓库中添加Github Actions的工作流配置,在根目录中创建文件:.github/workflow/docker-image.yml,内容如下:
yaml
# https://docs.github.com/zh/actions/use-cases-and-examples/publishing-packages/publishing-docker-images
name: Create and publish a Docker image
# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
push:
branches: ['main']
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
attestations: write
id-token: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
NEXT_PUBLIC_WEB_URL=${{ secrets.NEXT_PUBLIC_WEB_URL }}
NEXT_PUBLIC_PROJECT_NAME=${{ secrets.NEXT_PUBLIC_PROJECT_NAME }}
# Trigger redeploy on dokploy => project webhooks settings
- name: Trigger dokploy redeploy
run: |
curl -X GET https://dokploy.test.com/api/deploy/ZdYZjoiNxZ5nDIbjO1E2x
这个配置文件中有两点需要注意的:
- 构建镜像时的build-args,如果你没有NEXT_PUBLIC_*变量需要设置可以删去,如果有就修改成你自己的变量名,并在Github对应仓库的settings中增加secret变量

- 最后的curl请求的链接需要替换成对应Dokploy上项目的部署Webhook URL

然后在根目录上新增构建的Dockerfile
bash
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat && yarn global add pnpm
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json pnpm-lock.yaml* ./
RUN pnpm i --frozen-lockfile
# Rebuild the source code only when needed
FROM deps AS builder
WORKDIR /app
# -----------------------------------------------------------------------------
# Build Arguments for NEXT_PUBLIC_* variables
# -----------------------------------------------------------------------------
ARG NEXT_PUBLIC_WEB_URL
ARG NEXT_PUBLIC_PROJECT_NAME
# Set environment variables for build
ENV NEXT_PUBLIC_WEB_URL=${NEXT_PUBLIC_WEB_URL}
ENV NEXT_PUBLIC_PROJECT_NAME=${NEXT_PUBLIC_PROJECT_NAME}
COPY . .
RUN pnpm build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs && \
mkdir .next && \
chown nextjs:nodejs .next
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV NODE_ENV production
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
CMD ["node", "server.js"]
这个文件中需要修改环境变量,改为你自己的环境变量即可,和上面的Github Actions的构建文件中的变量对应。
ini
ARG NEXT_PUBLIC_WEB_URL
ARG NEXT_PUBLIC_PROJECT_NAME
# Set environment variables for build
ENV NEXT_PUBLIC_WEB_URL=${NEXT_PUBLIC_WEB_URL}
ENV NEXT_PUBLIC_PROJECT_NAME=${NEXT_PUBLIC_PROJECT_NAME}
接下来就可以在Dokploy进行部署了。 打开需要部署的项目,Provider选择Docker,Docker Image参数填:ghcr.io/[Github账号名]/[Repository项目名]:[分支名]
如果有环境变量需要设置,可以点击Environment,然后设置环境变量即可。

设置完成后,点击Deploy部署即可。

然后可以在Deployments中查看是否部署成功,以及如果部署失败的日志。

部署成功后,可以在Domain菜单中给服务绑定域名,这样就可以通过域名来访问对应的服务了,从Vercel迁移过来的时候,先使用一个子域名进行测试,如果没问题再切换到正式域名上。

服务绑定域名后,去给域名增加一条DNS解析,我这里是使用的cloudflare。

搞定之后,你就可以通过你域名访问你刚刚部署的服务了。
Dokploy构建并部署
如果你的服务器配置比较好,也可以直接使用Dokploy进行部署。 打开项目,Provider选择Github,Github Account选择之前配置的账号,Repository选择要部署的仓库。

Build Type选择Dockerfile,保存后,选择部署即可。

总结
自己实操下来使用Dokploy自己部署项目还是很简单的,我中间只被项目的变量设置卡了一下,其他的都很顺利。
买个服务器花了199/年,Vercel一个月订阅就要20美元,一年还是能省不少钱的。