1. 前期注意点
Nux 3 类型的前端应用,我们要想制作其 docker 镜像,需要注意两个点:
- Nuxt 3 本身构建后,可以直接使用 node 启动,所以按 node 模式制作镜像即可。
- 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/** 这里。
注意点:
- mindpress-serv 是我服务端的 docker 容器名。
-
process.env.BUILD_MODE === docker 用来区分日常的构建和容器构建的不一样的点,可以看到
"dockerbuild":"BUILD_MODE=docker nuxt build"这里使用了这个环境变量。
4. 遇到的其他问题
4.1 tomcat 的容器名不能为下划线格式
如果用 mindpress_serv 作为容器名,会导致 Bad Request 的错误,前端请求不到。缘由是 mindpress_serv是不合法的域名,所以需要改成 mindpress-serv 这样的容器名:

参考
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