昨天先用 docker run
玩了一圈,今天真的把我的 TS + Express + Prisma 專案打包進容器。
目標很明確:用 node:18-alpine
當基底,寫 Dockerfile、加 .dockerignore,然後在容器中 npm install
、npm run dev
跑起來。
FROM
:基底映像(今天用 node:18-alpine
,小又夠用)COPY
:把檔案丟進映像RUN
:在建置階段執行指令(例如安裝套件)CMD
:容器啟動後要執行什麼(例如 npm run dev
)ts-todo-api/
├─ src/
│ └─ index.ts
├─ prisma/
│ └─ schema.prisma
├─ package.json
├─ tsconfig.json
└─ .env # 若有(ex: DATABASE_URL)
之前 Day 25 你應該已經有
npm run dev
(用 ts-node-dev 或 nodemon)。
.dockerignore
(超重要)避免把不需要的東西塞進映像,影響建置速度與大小:
node_modules
dist
.git
Dockerfile
docker-compose*.yml
.env
npm-debug.log
pnpm-lock.yaml
yarn.lock
.prisma
dev.db
之後會用 Compose 把 DB 變成獨立容器;現在先避免把本機檔案黏進 image。
在專案根目錄新增 Dockerfile
:
# 1. 基底映像:輕量的 Node.js
FROM node:18-alpine
# 2. 建置內的工作目錄
WORKDIR /app
# 3. 先複製相依檔、安裝(利用快取)
COPY package*.json ./
RUN npm ci
# 4. 再複製其他原始碼
COPY . .
# 5. 設定環境(開發模式)
ENV NODE_ENV=development
# 6. 對外開放的埠(Express 預設 3000)
EXPOSE 3000
# 7. 啟動命令:先做 Prisma 需要的 generate(如果有用),再跑 dev
# 你也可以改成 `npm run dev`(看你專案 script)
CMD ["sh", "-c", "npx prisma generate || true && npm run dev"]
為什麼這樣寫?
COPY package*.json
再 RUN npm ci
:善用快取,程式碼變了但依賴沒變時,建置會快很多。CMD
用 sh -c
:我順手加了 npx prisma generate
以防你用到 Prisma。|| true
讓沒有 Prisma 也不會中斷。EXPOSE 3000
:只是文件化標示,實際暴露要用 -p
或 Compose。若你用
ts-node-dev
,在 WSL/Docker 上若檔案變動偵測不到,可加環境變數:ENV CHOKIDAR_USEPOLLING=true
(視你的 watcher 而定)
# 建置映像
docker build -t ts-todo-api:dev .
# 啟動容器(把主機 3000 映射到容器 3000)
docker run --name ts-todo -p 3000:3000 --rm ts-todo-api:dev
打開 http://localhost:3000
(或 /todos
),看到熟悉的回應就成功了 🎉
想看日誌:
docker logs -f ts-todo
想進容器:docker exec -it ts-todo sh
如果你想要邊改碼邊自動重啟(Hot Reload),可以把原始碼用 Volume 掛進去,並確保你的 npm run dev
會 watch 檔案:
docker run --name ts-todo \
-p 3000:3000 \
-v "$PWD:/app" \
-v /app/node_modules \
--env CHOKIDAR_USEPOLLING=true \
--rm ts-todo-api:dev
說明:
-v "$PWD:/app"
:把本機專案掛進容器(即時看到變動)-v /app/node_modules
:避免把本機空的 node_modules 覆蓋容器內的(這是常見坑)CHOKIDAR_USEPOLLING=true
:有些 watcher 在容器內需要 polling 才偵測到變動容器起來了但瀏覽器連不到
docker run -p 3000:3000
有沒有加app.listen(3000)
就會綁 0.0.0.0(OK)建置很慢、image 很大
.dockerignore
COPY package*.json
再 npm ci
,利用快取Prisma 找不到 Client
npx prisma generate
改碼沒反應
-v "$PWD:/app"
CHOKIDAR_USEPOLLING=true
(依你的工具而定)今天是第一次把自己的 TS API「打包進貨櫃」:
FROM/COPY/RUN/CMD
的最小組合node:18-alpine
開到最小可用的 Node 環境.dockerignore
真的超重要,建置速度差很多npm install
+ npm run dev
順利跑起來,看到 http://localhost:3000
的瞬間滿滿成就感 ✨