Nuxt3 with docker ( ㄧ )
紀錄使用 docker 配上全新的 Nuxt3 專案,包含本地開發還有部署
此篇假設讀者知曉基本的 docker、docker-compose 和 Nuxt3
然後為了方便會使用 dc 這 alias 來替代 docker compose
有別於其他做法,這邊所有的指令都需要進到 container 裡面去完成,所以即便 local machine 沒有安裝 yarn 以及 node 都可以完成。
想直接使用的人可以看 Source code
首先先創六個檔案
開一個全新的資料夾,在此資料夾底下創以下六個檔案
.env
.env.example
Dockerfile
docker-compose.yml
Readme.md
.dockerignore
.env 跟 .env.example 內容如下
這邊會區分 Docker 跟 Application 方便之後區分
### Application ##################################
### Docker ##################################
# Node 版本至少要 v18.0.0 or newer
# https://nuxt.com/docs/getting-started/installation
DOCKER_NODE_VERSION=18.16.1
Readme.md
## Installation
cp .env.example .env
## Other....
寫一下教學方便後續的人使用
.dockerignore
Exclude files and directories from the build context.
# .dockerignore
/.nuxt
/.output
/node_modules
.gitignore
README.md
Dockerfile
FROM node:${NODE_VERSION}-slim as base
MAINTAINER "example@gmail.com"
WORKDIR /app
# By default, just keep the container running
CMD ["tail", "-f", "/dev/null"]
上面要注意最下面那行
tail -f /dev/null
是因為如果沒有使用,docker container 便不會一直運行著
docker-compose.yml
version: '3.8'
services:
frontend:
container_name: frontend
restart: on-failure
build:
context: .
args:
# DOCKER_NODE_VERSION 會去讀取 .env 裡面
- NODE_VERSION=${DOCKER_NODE_VERSION}
volumes:
- .:/app
以下給 ChatGPT 回答
注意一下 volumes 這邊,這邊之後會解說
volumes:
- .:/app
前置作業建立好,接著先 build image
# In root directory
dc build frontend
可以透過 docker images 看到我們已經創了一個 image 了
透過 image 來啟動 container
# up 啟動 container
# -d 參數是背景運行 Detached mode: Run containers in the background
# In root directory
dc up -d frontend
frontend 這要跟 docker composer 裡面的 services 一樣
然後再透過以下指令來看一下 container 的狀態
# In root directory
dc ps
進去 container 裡面
# In root directory
dc exec frontend bash
然後
cd /
出現上面畫面代表已經成功進去了
Init Nuxt3 專案
我們透過 npx 來創建一個全新的 Nuxt3 專案
# In / directory
npx nuxi@latest init app -f
注意 app 跟 -f 這兩個,還記得上面 docker-compose.yml 裡面的 volumes 嗎
# . 代表當前 local machine 運行 docker 的根目錄
# /app 代表 container 裡面的路徑,這也是為什麼 npx nuxi@latest init app 要特別在 app 底下
volumes:
- .:/app
如果不用 -f ( override file ) 則會出現資料夾存在的 error
當成功之後你會發現多了很多檔案
測試一下
在 container 裡面
cd app/ && yarn dev
點開瀏覽器會發現
其原因是因為 container 裡面沒有把 3000 port 給 expose 出來
所以來改一下 docker-compose.yml,加上 ports
services:
frontend:
container_name: frontend
restart: on-failure
build:
context: .
args:
# DOCKER_NODE_VERSION 會去讀取 .env 裡面
- NODE_VERSION=${DOCKER_NODE_VERSION}
ports:
# 把本機的 port 跟 container 的 port 綁定
- '${DOCKER_HOST_MACHINE_PORT}:3000'
volumes:
- .:/app
然後在 .env.example 還有 .env 也加上
### Application ##################################
### Docker ##################################
# Node 版本至少要 v18.0.0 or newer
# https://nuxt.com/docs/getting-started/installation
DOCKER_NODE_VERSION=18.16.1
DOCKER_HOST_MACHINE_PORT=3000
這樣就綁定本機的 3000 跟 docker container 的 3000 port
但因為我們有修改 docker-compose.yml 所以這邊要重新啟動
首先 control + c 把當前 yarn dev 給 exit 掉,然後在 exit 離開 container
接著一次 run 三個指令
- dc down:停止當前所有正在運行ㄉㄜ container
- dc up -d frontend:啟動 container
- dc exec frontend bash:是進入 container
# In local machine root directory
dc down && dc up -d frontend && dc exec frontend bash
進入 container 裡面之後
yarn dev
這時候回到瀏覽器你會發現畫面已經正常顯示了
接著建立簡單的 pages
app.vue
<template>
<div>
<NuxtLoadingIndicator />
<NuxtPage />
</div>
</template>
新建一個 folder 叫 pages 底下有 index.vue 裡面簡單一個 count
<template>
<h1>{{ count }}</h1>
</template>
<script setup lang="ts">
let count = 0
</script>
我透過修改 count 然後看看畫面是否會有變動,如畫面變動恭喜成功
到這邊我們已經算是完成了全部,不透過 local machine 去創建專案,反而是進去 container 把 Nuxt3 專案創起來,然後在本機開發看看是否可以成功在瀏覽器顯示
當開發完畢要部署到 server
首先要 deploy 到 server 的話,我們要準備兩個檔案
1. build-prod.sh
創一個 bin 的 folder 裡面再創一個 build-prod.sh
#!/bin/bash
# 拿到當前路徑
CURRENT_DIRECTORY=$(dirname "$0")
echo "CURRENT_DIRECTORY: $CURRENT_DIRECTORY"
# 回到根路徑
cd "$CURRENT_DIRECTORY/../ || exit"
# 安裝 yarn
# --prefer-offline
#
# use network only if dependencies are not available in local cache
#
# --frozen-lockfile
#
# don't generate a lockfile and fail if an update is needed
#
# --non-interactive
#
# do not show interactive prompts
#
# --production=false
#
# install devDependencies
yarn install \
--prefer-offline \
--frozen-lockfile \
--non-interactive \
--production=false
# 執行 yarn build
yarn build
接著我們會需要另外一個檔案專門讓 docker-compose 處理 production 專用的
2. docker-compose.prod.yml
version: '3.8'
services:
frontend:
container_name: frontend
restart: on-failure
build:
context: .
args:
- NODE_VERSION=${DOCKER_NODE_VERSION}
ports:
# 把本機的 port 跟 container 的 port 綁定
- '${DOCKER_HOST_MACHINE_PORT}:3000'
volumes:
- .:/app
command: node .output/server/index.mjs
tty: true
stdin_open: true
command 跟 tty 還有 stdin_open 的解釋
接著一樣進到 container
dc exec frontend bash
執行 build-prod.sh
bash bin/build-prod.sh
執行完之後退出
接著執行 docker-compose
# In local machine
# 執行 docker-compose,而執行的時候讀取 docker-compose.prod.yml
# --build 是 build image
# -d 是 Detached mode: Run containers in the background
docker compose -f docker-compose.prod.yml up --build -d
這樣就完成 prod 的版本了
結論
所以整理一下,不管我們要做什麼事情,都一定要先進到 conainter 去執行,執行完才回到 local machine,
Nuxt3 with docker Nginx deploy ( 二 )