胖蔡说技术
随便扯扯

使用Docker部署nextjs应用

最近使用nextjs网站开发,希望使用docker进行生产环境的部署,减少环境的依赖可重复部署操作。我采用的是Dockerfile编写应用镜像方式+ docker-compose实现容器部署的功能。

nextjs

Docker

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。我们可以通过将开发代码打包到docker 镜像中,上传到docker hub中,待发布时通过拉取docker hub镜像启动docker 容器,实现代码运行环境的高度一致,并提高部署效率。

安装

docker 提供了各种不同系统的安装方式,,因为我们常用的正式部署环境使用linux的缘故,我这里只介绍linux里如何安装docker以及如何配置docker国内镜像加速。

1、脚本安装

$ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

2、手动命令安装

# 先卸载旧版本的docker安装包,后安装新版
$  sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

镜像加速

docker在国内网络环境使用会出现镜像下载过慢,甚至无法下载的问题,这里提供几个配置国内加速镜像源头地址, 在/etc/docker/daemon.json文件中写入如下内容:


{
  "registry-mirrors": [
         "https://<your-mirror-id>.mirror.aliyuncs.com", // 阿里云的加速地址,每个人都不一样
         "https://docker.mirrors.sjtug.sjtu.edu.cn", // 上海交大
         "https://docker.nju.edu.cn", // 南京大学
         "https://docker.m.daocloud.io",// DaoCloud
         "https://mirror.baidubce.com", // 百度云
         "https://dockerproxy.com"// DockerProxy 代理
         
  ]
}

配置的时候需要将后面的备注信息删除,配置后需要重启docker服务:

 sudo systemctl restart docker

重启完成后可以通过拉取一个docker镜像来验证镜像源是否可用,如:

$ docker pull node:18

常用命令 

docker中又几个命令是需要我们记住的,因为需要经常使用到,如下简单介绍下几个常见的docker命令:

$ docker pull nginx:latest # 从镜像仓库拉取nginx:latest镜像
$ docker search nginx  # 搜索镜像库的nginx相关镜像
$ docker push nginx:0.0.1 # 提交本地镜像nginx:0.0.1到当前登录的镜像仓库
$ docker ps -a # 列出当前主机中所有的docker容器
$ docker run -it nginx /bin/bash  # 基于nginx镜像启动一个docker容器
$ docker pause containername # 暂停docker 容器
$ docker start containername # 启动docker容器
$ docker stop containername # 停止docker容器
$ docker restart containername # 重启docker容器
$ docker attach -it containername /bin/bash # 进入docker 容器,此种方式进入退出后会使得docker容器停止
$ docker exec -it containername /bin/bash # 进入docker 容器,此种方式进入退出后不会使得docker容器停止
$ docker export containername > containername.tar  # 导出docker容器快照
$ docker rm containername # 删除docker 容器
$ docker logs -f containername # 持续输出docker容器的日志信息
$ docker cp containerID:container_path host_path # 复制主机文件到对应docker容器的地址

Dockerfile

Docker可以通过从Dockerfile中读取指令来自动构建图像。Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以组装图像的所有命令。本文介绍了可以在Dockerfile中使用的命令。

 编写DockerFile

1、在项目根目录创建Dockerfile文件

构建应用镜像的基础是创建对应的dockerfile文件,常规的我们会选择将dockerfile文件创建在项目的根目录,当然也可以自定义指定位置,只要在之后的构建过程指定路径就可以了

2、dockerfile编写依赖

我这里为了减少容器的大小,所以dockerfile使用了多阶段构建的方式实现,首先是依赖阶段实现依赖库的下载,具体如下:

FROM node:18-alpine AS deps
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn config set registry https://registry.npm.taobao.org
RUN yarn install --frozen-lockfile

需要注意:

  • nodejs对应版本,查看package.json中的版本要求
  "engines": {
    "node": ">=18.17.0"
  }

  • 我这里将软件源修改为国内镜像,默认的国外镜像可能导致软件无法更新下载
  • 更新前端库镜像为淘宝镜像

3、构建阶段

由于已经完成依赖的下载,构建阶段只需要进行编译打包即可:

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN yarn config set registry https://registry.npm.taobao.org
RUN yarn build && yarn install --production 

4、运行阶段

完成构建后,就需要我们配置容器的基础配置,如环境变量、工作目录、监听端口、应用启动命令等:

FROM node:18-alpine AS runner

WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED 1
ENV NODE_ENV production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
RUN yarn config set registry https://registry.npm.taobao.org

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

USER nextjs

EXPOSE 3000

ENV PORT 3000



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

 Docker-Compose

新的 Compose V2 支持将 compose 命令作为 Docker CLI 的一部分,现已推出。Compose V2 将 compose 功能集成到 Docker 平台中,继续支持之前的大部分 docker-compose 功能和标志。您可以通过使用 docker compose 而不是 docker-compose 将连字符 (-) 替换为空格来运行 Compose V2

Compose是Docker官方提供一个负责实现Docker 容器集群的快速编排,实现定义和运行多个Docker容器的应用。通过编写docker-compose文件可对多个服务同时进行启动/停止/更新(可定义依赖,按顺序启动服务)。

相关概念

  • 项目(project):一个docker-compose.yml 组成一个project
  • 服务(service):定义容器,配置需要运行的容器实例。一个project中由多个service组成,每个service定义了容器运行的镜像

命令

我们可以通过docker compose来查看帮助命令。


[root@VM_0_16_centos ~]# docker compose --help

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

常用命令

$docker-compose up #启动docker-compose.yml中的所有容器,命令退出时,所有容器都将停止
$docker-compose up -d   #启动docker-compose.yml中的所有容器,在后台启动容器并使它们保持运行
$docker-compose logs -f #查看该容器的日志打印
$docker logs -f contianer_id #查看某一个容器的启动日志打印
$docker-compose stop #停止compose服务
$docker-compose restart #重启compose服务
$docker-compose rm  #删除compose服务
$docker-compose ps #查看compose 服务
$docker-compose kill #杀死compose服务

 编写docker-compse.yml文件

完成dockerfile文件编写后,我们就需要通过编写docker-compose.yml配置文件来启动容器了。我这里是使用nginx来部署,配置如下:

version: "3.1"

services:
  db:
    image: mysql:8
    command:
      --default-authentication-plugin=mysql_native_password
      --sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
      --group_concat_max_len=102400
    restart: unless-stopped
    volumes:
      - ./data/mysql/:/var/lib/mysql/
    environment:
      TZ: Asia/Shanghai # 指定时区
      MYSQL_ROOT_PASSWORD: "nextjs" # 配置root用户密码
      MYSQL_DATABASE: "nextjs" # 业务库名
      MYSQL_USER: "nextjs" # 业务库用户名
      MYSQL_PASSWORD: "nextjs" # 业务库密码
    ports:
      - 3306:3306

  nextjs:
    build: .
    ports:
      - "3000:3000"
    environment:
      TZ: Asia/Shanghai # 指定时区
    container_name: nextjs
    volumes:
      - ./:/app/
    depends_on:
      - db
    restart: unless-stopped

  nginx:
    image: nginx:mainline-alpine
    container_name: nginxserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./.next:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d


networks:
  nodeapp-network:
    driver: bridge

 Nginx配置

如上可以看出,我一共创建了三个容器,一个数据容器db,一个nextjs容器是我们的应用还有一个nginx容器是web服务,nginx里还需要将我们的配置文件映射到容器内,nginx-conf内容如下:

server {
    listen 80;
    listen [::]:80;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    server_name patientplatypus.com www.patientplatypus.com localhost;

    # location /back {
    #   proxy_set_header X-Real-IP $remote_addr;
    #   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #   proxy_set_header Host $http_host;
    #   proxy_set_header X-NginX-Proxy true;

    #   proxy_http_version 1.1;
    #   proxy_set_header Upgrade $http_upgrade;
    #   proxy_set_header Connection "upgrade";

    #   proxy_pass http://nodejs:8000;
    # }

    location / {
      proxy_pass http://nextjs:3000;
    }

    location ~ /.well-known/acme-challenge {
      allow all;
      root /var/www/html;
    }
}

启动容器

通过如下的学习,只需要我们的宿主机器安装了docker-compse即可直接使用如下命令:

$docker-compose up -d

赞(1) 打赏
转载请附上原文出处链接:胖蔡说技术 » 使用Docker部署nextjs应用
分享到: 更多 (0)

请小编喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏