制作 Nuxt 3 应用的 Docker 镜像 2025-06-06

1. 前期注意点

Nux 3 类型的前端应用,我们要想制作其 docker 镜像,需要注意两个点:

  1. Nuxt 3 本身构建后,可以直接使用 node 启动,所以按 node 模式制作镜像即可。
  2. Nuxt 3 前端应用会调用后端 API,这里可能需要用到 proxy 模式。

2. 制作Nuxt 3的node镜像

2.1 制作 Dockfile 文件

Dockerfile 文件内容如下:

FROM node:18.14.2

WORKDIR /app

EXPOSE 3000

CMD [ "yarn", "run", "dockerdeploy" ]
# ENTRYPOINT ["node","/app/server/index.mjs"]

这里的本质是运行 yarn run dockerdeploy 这个命令,其内容在,package.json文件里

{
  "private": true,
  "name": "mindpress",
  "version": "1.0.0",
  "description": "Press your mind(markdown) gracefully, which is powered by [nuxt.js 3.0](https://v3.nuxtjs.org) and [nuxt content 2.0](https://github.com/nuxt/content).",
  "keywords": [
    "nuxt",
    "content",
    "mindpress"
  ],
  "repository": "aborn/mindpress",
  "license": "MIT",
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev --port=7001",
    "generate": "MINDPRESS_MODE=ghpages nuxt generate",
    "preview": "nuxt preview",
    "start": "nuxt build && PORT=8001 node .output/server/index.mjs",
    "deploy": "touch ./dist/.nojekyll && push-dir --dir=dist --branch=gh-pages --cleanup",
    "gh": "npx nuxi generate && npx serve -s ./dist",
    "dockerbuild":"BUILD_MODE=docker nuxt build",
    "dockerdeploy": "PORT=3010 node .output/server/index.mjs"
  },
  "devDependencies": {
    "@nuxt/content": "2.12.1",
    "@nuxtjs/color-mode": "^3.4.1",
    "nuxt": "3.11.2",
    "push-dir": "^0.4.1"
  },
  "dependencies": {
    "md-editor-v3": "^4.15.6",
    "axios": "^1.1.3"
  }
}

2.2 构建 Nuxt 3 应用的静态文件

根据上文中的 package.json ,这里使用的是 yarn dockerbuild 这个命令,整体的脚本如下:

#!/usr/bin/env bash
########################################
# front-end rebuild package and boot it!
# /Users/aborn/github/mindpress/docker/h5/scripts/rebuild.sh
#########################################

DIR="$( cd "$( dirname "$0" )" && pwd )"

cd $DIR
cd ../../../../mindpress-fe
git pull

# building ,如果出现 /bin/sh: vite: command not found ,则需要重新yarn install下
yarn dockerbuild

# copy nuxt build files;
if [ ! -d "$HOME/docker/nuxt/mindpress" ];then
    mkdir -p $HOME/docker/nuxt/mindpress
else
    echo "$HOME/docker/nuxt/mindpress exists, no need to create it!"
fi

# delete origin file
if [ ! -d $HOME/docker/nuxt/mindpress/.output ];then
    echo "dir not exists!"
else
    rm -rf $HOME/docker/nuxt/mindpress/.output
fi

# copy files
cp -r .output $HOME/docker/nuxt/mindpress/
cp *.json $HOME/docker/nuxt/mindpress/

实则这里的核心就是先通过 yarn dockerbuild构建出 .output 这个目录文件,然后将其 copy 到 $HOME/docker/nuxt/mindpress/这个目录下

2.3 制作镜像和容器的命令

#!/usr/bin/env bash

DIR="$( cd "$( dirname "$0" )" && pwd )"
cd $DIR

# build docker image
docker build -t mindpress_nuxt:v1 .

# boot up container,jar in folder: $HOME/docker/packages
docker run --name mindpress_nuxt -it -v $HOME/docker/nuxt/mindpress:/app -d -p 3010:3010 --net=mindpress_net mindpress_nuxt:v1

3. Nuxt 3 的代理模式配置

配置文件在 nuxt.config.ts

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
    app: {
        baseURL: process.env.MINDPRESS_MODE ===  ghpages  ?  /mindpress/  :  / ,   // default  /   (change to your need.)
        head: {
            title:  MindPress, Press your mind gracefully. ,
            link: [
                {
                    rel:  stylesheet ,
                    href:  https://unpkg.com/@picocss/pico@latest/css/pico.min.css 
                }
            ]
        }
    },
    routeRules: {
         /api/v1/** : { proxy: process.env.BUILD_MODE ===  docker  ?  http://mindpress-serv:3012/api/v1/**  :  http://localhost:3012/api/v1/**  },
         /_nuxt/** : { cors: true },
    },
    css: [
         @/assets/css/app.css ,
    ],
    modules: [
         @nuxt/content ,
         @nuxtjs/color-mode 
    ],
    content: {
        highlight: {
            theme: "one-dark-pro",
            preload: [ bash ,  c ,  csharp ,  c# ,  css ,  docker ,  go ,  groovy ,  html ,  java ,  javascript ,  js ,  jsx ,
                 json ,  julia ,  kotlin ,  markdown ,  lua ,  less ,  md ,  nginx ,  objc ,  python ,  py ,  ruby ,  rb ,  rust ,
                 rs ,  swift ,  sql ,  typescript ,  ts ,  tsx ,  vue ,  xml ,  yaml ]
        }
    },
    runtimeConfig: {
        public: {
            minpress: {
                mode: process.env.MINDPRESS_MODE ===  ghpages  ?  static  :  server ,   //  static  (default) or  server 
                baseUrl:  /api/v1/mindpress/ 
            }
        }
    }
})

注意看 routeRules 这个配置,我这里将 /api/v1/打头的 api 全部路由到 “`http://mindpress-serv:3012/api/v1/** 这里。
注意点:

  1. mindpress-serv 是我服务端的 docker 容器名。
  2. process.env.BUILD_MODE === docker 用来区分日常的构建和容器构建的不一样的点,可以看到 "dockerbuild":"BUILD_MODE=docker nuxt build" 这里使用了这个环境变量。

4. 遇到的其他问题

4.1 tomcat 的容器名不能为下划线格式

如果用 mindpress_serv 作为容器名,会导致 Bad Request 的错误,前端请求不到。缘由是 mindpress_serv是不合法的域名,所以需要改成 mindpress-serv 这样的容器名:

制作 Nuxt 3 应用的 Docker 镜像 2025-06-06

参考

4.2 Nuxt 3 运行过程中如何获取 host 的问题

使用了代理模式会有一个问题,如下代码,如果 url 不是全路径的话,getDataAx这种使用axios调用的方法会报错,而使用useFetch Nuxt 3 原生支持的方法不会报错。

async function getDataAx() {
    return await request({
        url: url,
        method: "get",
        headers: {
            uid:   
        }
    }) as any;
}

async function getData() {
    return await useFetch(
        url,
        {
            method: "get",
            headers: {
                uid:   
            }
        }) as any;
}

if (articleid.value) {
    const dataAx = await getDataAx()
    mkdContent.value = dataAx.content
    title.value = dataAx.title

    // console.log(dataAx)
    // const { data: dataS } = await getData()
    // mkdContent.value = dataS.value.content
    // title.value = dataS.value.title
}

解决方法是将 url 改成全路径:

const useReqURL = useRequestURL()
const apiBaseURL = useReqURL.protocol +   //  + useReqURL.host
const mp = mpConfig(useRuntimeConfig().public.minpress)
const url = apiBaseURL +  mp.contentUrl +  /  + articleid.value

相当于将原先请求 /a.api 改成了 http://host.com/a.api的请求,这样两种写法都不会有问题。

参考

5. 源代码

https://github.com/aborn/mindpress/tree/main/mindpress-serv/scripts/docker/nuxt
https://github.com/aborn/mindpress

© 版权声明

相关文章

暂无评论

none
暂无评论...