目錄

Dockerfile 教學:把自己的程式打包成映像檔

Dockerfile 是一個純文字檔,裡面一行一行寫著「怎麼建立這個映像檔」。Docker 會照著這些步驟執行,產生一個映像檔。

範例專案

建立一個資料夾 hello-node,裡面放兩個檔案。

package.json:

{
  "name": "hello-node",
  "version": "1.0.0",
  "scripts": { "start": "node server.js" }
}

server.js:

const http = require("http");

const server = http.createServer((req, res) => {
  res.end("Hello from Docker!\n");
});

server.listen(3000, () => console.log("Listening on port 3000"));

撰寫 Dockerfile

在同一個資料夾建立名為 Dockerfile 的檔案(沒有副檔名):

# 1. 以官方 Node.js 映像檔為基礎
FROM node:22-alpine

# 2. 設定容器內的工作目錄
WORKDIR /app

# 3. 先複製套件清單並安裝相依套件
COPY package*.json ./
RUN npm install --omit=dev

# 4. 再複製其餘程式碼
COPY . .

# 5. 說明容器會使用的連接埠
EXPOSE 3000

# 6. 容器啟動時執行的指令
CMD ["npm", "start"]

建置與執行

docker build -t hello-node .
docker run -d -p 3000:3000 --name hello hello-node
curl http://localhost:3000

-t hello-node 是映像檔名稱,最後的 . 代表用目前資料夾當作建置內容(build context)。

常用指令說明

指令作用
FROM指定基礎映像檔,Dockerfile 一定從它開始
WORKDIR設定之後指令的工作目錄,不存在會自動建立
COPY把建置內容中的檔案複製進映像檔
RUN建置時執行指令,例如安裝套件
ENV設定環境變數
EXPOSE標示容器使用的連接埠(只是說明,實際對應仍要用 -p)
CMD容器啟動時預設執行的指令,可被 docker run 後面的指令覆蓋
ENTRYPOINT容器的主要執行檔,CMD 會變成它的參數

為什麼先複製 package.json

Dockerfile 的每一行都會產生一層,Docker 會快取這些層。只要某一行和它用到的檔案沒變,重新建置時就直接用快取。

如果一開始就 COPY . .,每次改一行程式碼,npm install 那層的快取就失效,得重新安裝所有套件。先只複製 package*.json 再安裝,只有套件清單改變時才需要重新安裝,建置會快很多。

.dockerignore

建置時,整個資料夾都會被送給 Docker。用 .dockerignore 排除不需要的檔案,可以加快建置,也避免把機密資料打包進去:

node_modules
.git
.env
*.log

小技巧

  • 選擇 alpine 或 slim 版本的基礎映像檔,可以大幅縮小映像檔大小。
  • 固定基礎映像檔的版本,例如 node:22-alpine,不要只寫 node。
  • CMD 使用 JSON 陣列格式(["npm", "start"]),容器才能正確收到停止訊號。

下一步可以試著把你自己的專案寫成 Dockerfile,並用 docker build 建置看看。

更新於 2026年10月12日