「Docker 怎麼部署 Discord Bot?」這題比較偏部署與 Node.js runtime。
面試官通常想知道你是否理解:
- Docker image 和 container 的差異
- 機密資訊不能包進 image
- Bot 是長時間運行的 process
- crash 後要能自動重啟
- 部署後要能看 log、更新、回滾
Docker 部署 Bot 的核心想法
Discord Bot 通常是一個長時間運行的 Node.js process。
Docker 的價值是把這些東西封裝起來:
- Node.js 版本
- npm dependencies
- source code
- 啟動指令
- runtime 環境
然後在部署時用環境變數和 volume 注入設定與機密。
Dockerfile 範例
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
ENV NODE_ENV=production
CMD ["node", "index.js"]幾個重點:
- 固定 Node 版本,避免本機和伺服器不同
- 先 copy lock file 再
npm ci,讓 Docker layer cache 更有效 - production image 不裝 dev dependencies
CMD是 container 啟動時執行的指令
.dockerignore 很重要
不要把不該進 image 的東西包進去。
node_modules
.env
.env.*
key
coverage
README.md特別注意:
- Discord Bot Token
- OAuth client secret
- Google Service Account JSON
.env
這些都不應該進 Docker image。
docker run 部署
docker build -t discord-bot .
docker run -d \
--name discord-bot \
--restart unless-stopped \
--env-file .env \
discord-bot如果有 service account key:
docker run -d \
--name discord-bot \
--restart unless-stopped \
--env-file .env \
-v ./key:/app/key:ro \
discord-bot--restart unless-stopped 很適合 Bot,因為 process 掛掉時 Docker 會自動重啟,除非你手動停止 container。
docker compose 版本
services:
bot:
build: .
container_name: discord-bot
restart: unless-stopped
env_file:
- .env
volumes:
- ./key:/app/key:ro啟動:
docker compose up -d --build看 log:
docker logs -f discord-bot停止:
docker compose downBot 程式內也要處理錯誤
可以攔截未預期錯誤並讓 process exit:
process.on("unhandledRejection", (reason) => {
console.error("Unhandled Rejection:", reason);
process.exit(1);
});
process.on("uncaughtException", (error) => {
console.error("Uncaught Exception:", error);
process.exit(1);
});讓 process exit,再交給 Docker restart policy 重啟,通常比讓程式留在不確定狀態更安全。
常見追問
為什麼不要把 token 寫進 image?
image 可能被推到 registry、被別人拉取或留在 build cache。機密應該透過環境變數、secret manager 或 volume 注入。
volume 是什麼?
volume 可以把 host 上的檔案或資料夾掛進 container。像 service account key 就可以用 read-only volume:
-v ./key:/app/key:rocontainer 掛掉怎麼辦?
用 restart: unless-stopped 或 --restart unless-stopped,並搭配 log 監控。
時區要注意嗎?
如果 Bot 有排程,container 預設時區可能不是台灣時間。可以設定:
ENV TZ=Asia/Taipei面試回答模板
我會用 Dockerfile 固定 Node 版本,先 copy package lock 後
npm ci --omit=dev,再 copy source code,最後用CMD ["node", "index.js"]啟動 Bot。token 和 secret 不會包進 image,而是透過.env、環境變數或 secret manager 注入;如果有 key file,會用 read-only volume mount。container 會設定--restart unless-stopped,讓 Bot crash 後自動重啟,部署後用docker logs或監控工具查看狀態。