属于前端开发者的Next.js结合Docker部署实践

588 阅读7分钟

前言

近期在开发自己的个人项目,借此将前端部署又学习一遍,特此记录下。个人项目是使用的Next.js,此文章记录Next个人项目部署上服务器的各个步骤,并没有达到企业级那么规范,对于个人项目部署来说是够用的,没有接触过部署的同学可以参考一下,有问题欢迎评论区指出哈哈

想到以前没有接触docker和nginx时候总觉得这个东西特别难,但实际操作下来其实并不像想象中的那么难,很多时候时候都是自己心理上给自己做了限制,少想多做!共勉

部署的流程

我们在本地进行开发完之后的代码是不能直接在服务器使用的,前端一半需要经过打包,打包后的代码才是在服务器运行的代码。那我们是不是要在本地进行打包,然后将打包的代码上传到服务器?其实是不需要的,我们可以将打包的操作交给Docker来进行操作,除了打包之外Docker还能帮我们进行很多操作。我们将代码交给Docker,让Docker帮我们进行安装依赖、打包代码、运行服务。

除了Docker之外,我们还需要使用到Nginx,将我们的服务进行反向代理,其实如果只是为了将服务部在服务器跑起来,可以不使用Nginx,我们直接在服务器中暴露出服务所使用的端口(比如3000),这样我们通过访问地址+端口号也可以访问到服务,但这很不好,不要使用这种方式!!!

众所周知http和https协议的端口号是80和443,所以我们还是使用Nginx来将访问80和443端口的服务代理到我们服务的端口号

Docker构建本地镜像

关于Docker相关的一些概念已经有很多文章已经解释的很清楚了,所以这边就不进行过多的阐述。个人理解Docker其实是一个轻量且功能更强大的虚拟机。 我们首先需要准备好Docker,关于Docker的安装也有太多文章了,这里不作阐述。

.dockerignore文件

在项目根目录创建一个.dockerignore文件,避免将多余的文件加入镜像中,类似gitignore的作用,如下

node_modules/
.vscode/
.git/

生成镜像

准备好Docker之后我们需要在项目根目录准备好一个Dockerfile文件,Dockerfile是用来定义Docker镜像的文本文件,里面包含了许多指令,比如我们所需要的安装依赖、打包编译、启动服务等,通过这些指令将我们的代码打包成镜像,配置如下

# 使用 Node.js 18 的官方镜像,版本可根据自己需求更改
FROM node:18-alpine

# 使用pnpm
RUN corepack enable && corepack prepare pnpm@8.5.0 --activate

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json 并安装依赖
COPY package.json pnpm-lock.yaml ./
RUN pnpm install

COPY . .

RUN pnpm run build

EXPOSE 3000

CMD ["npm", "start"]

定义好Dockerfile文件之后,我们还需要拉取node官方镜像作为基础镜像,执行下面命令即可

# 可根据自己的node版本选择官方镜像
docker pull node:18-alpine

如果本地的镜像仓库已经有基础镜像了则可以不拉取,可以使用docker imgaes命令来查看本地是否有基础镜像,如下图

image.png 以上都准备好的话就可以运行docker build -t 镜像名字 .来生成镜像了 看到类似的输出没有报错的的话我们的镜像就已经是生成好了

image.png 然后我们再使用docker images来看看本地镜像,此时就多了一个我们的服务镜像my-next

image.png

运行容器

我们通过上面步骤生成好我们的服务镜像后,就可以通过镜像运行容器了,我们在本地先运行一下以验证容器没有问题,之后我们再往服务器上面推

执行以下命令来生成我们的容器,具体参数可以对照下面列表

  • docker run:用于创建并启动一个新的容器
  • -d:表示容器在后台运行
  • -p 3000:3000:将主机的3000端口印社到容器的3000端口,这样可以通过localhost:3000来查看查看我们的服务
  • 镜像ID:替换为你要运行的具体镜像的ID或者名称
docker run -d -p 3000:3000 镜像ID

然后我们可以通过docker ps命令查看运行中的容器列表,来确认是不是正常启动,如下可以看到我们的容器就正常启动起来了。

image.png 如果docker ps没有看到对应的容器,那么说明我们的容器可能启动失败,此时我们可以通过docker ps -a来查看所有的容器,如果看到我们的容器退出状态不是0的话那说明可能容器内部可能有问题,此时可以通过执行命令docker logs <container_id_or_name>来查看容器内部报错

上传本地镜像

我们本地镜像构建完了之后应该怎么上传到我们的服务器呢?我这里使用的是阿里云镜像服务 我们打开阿里云控制台然后搜索容器镜像服务,然后选择个人实例就好(企业版要收费)

image.png 点进去之后我们创建一个镜像仓库就可以了,相关的操作在镜像仓库里已经说明的很详细了,跟容器镜像服务的操作指南一步步操作就可以将我们的本地镜像上传到镜像仓库了。

服务器Docker准备

我们服务器安装好Docker之后,需要准备一下我们的Nginx镜像,后续我们需要使用到Nginx,执行以下命令即可,需要什么版本的nginx可自己定义,我这边使用的是最新的Nginx镜像 docker pull nginx:latest

Docker Compose

在服务器上我们需要起两个容器,一个是我们的服务,一个是我们的Nginx容器,上文有说到我们需要使用Nginx来转发来自80端口和443端口的服务,按照我们传统命令行启动容器的方式去启动就会有点麻烦了,可能我们现在所需的服务只有两个,所以看起来还好,但如果是一个负责的应用,一个应用可能需要启动很多个容器,容器之间可能还有依赖关系,这时候再通过命令行的方式去启动容器的话,实在是太过于麻烦还容易出错

Docker Compose就是为了解决上面的痛点而存在的,通过配置yaml文件的方式来启动容器,相比于命令行更加方便,同时启动所需的东西(比如暴露的端口、数据卷等)也会更加清晰,所以我们在服务中定义一个docker-compose.yaml文件,如下

version: "1.0"

# 一共定义了两个服务,web是我们的应用,nginx则是nginx服务
services:
  web:
    container_name: 你的容器名字
    image: 阿里云容器镜像服务的地址
    # 服务的端口和主机的端口做映射
    ports:
      - "3000:3000"
  nginx:
    image: nginx:latest
    # 数据卷
    volumes:
      # 这边Nginx配置是跟docker-compose文件同目录,可根据自己需要更改
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./logs:/var/log/nginx
    ports:
      - "80:80"
    # 依赖于哪个服务,这边是依赖于web服务
    depends_on:
      - web

Nginx配置

关于Nginx的作用例如什么反向代理、负载均衡之类的这里就不多做阐述了,感兴趣可以看看官方文档或者相关文章,我们这边使用Nginx是为了反向代理,将我们服务器80端口转发到3000端口

我们同样也需要定义一个nginx.conf配置文件,如下

events {}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server {
        listen 80;
        location / {
            proxy_pass http://sci-media:3000/;
        }
    }
}

运行服务

定义好上面的docker-compose.yaml文件和nginx.conf文件后我们在文件所在目录执行docker compose up -d看到下面的输出说明我们容器就已经创建成功了

image.png 可以继续使用docker ps看看我们的服务是否正常启动,出现问题打印一下容器的日志排查即可