在node.js專案中使用Dockerfile

Docker 化的好處

  • Lightweight and Resource Efficient.
  • Immutable
  • 可攜
  • Scalable and Highly Available.

基本需求

  • 開發區使用 carbon 映像檔;alpine為正式區映像檔
  • 開發期間使用 nodedemon 當作hot reload機制
  • 使用COPY 而非ADD指令

程式架構

node-app
├── Dockerfile
├── package.json
└── src
    └── server.js

建立開發區的 Dockerfile

FROM node:carbon

WORKDIR /app  # 建立APP目錄

# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./   # 複製需要的函數

RUN npm install
# If you are building your code for production
# RUN npm install --only=production

# Bundle app source
COPY src /app

EXPOSE 8080
CMD [ "node", "server.js" ]
  • .dockerignore 避免不必要的檔案被加入Docker中
.git
node_modules
npm-debug
  • 執行Docker
$ cd node-docker
$ docker build -t node-docker-dev .
$ docker run --rm -it -p 8080:8080 node-docker-dev

執行完上述指令之後,就可以透過 http://localhost:8080/ 來看到執行結果,可透過Ctrl + C 退出程式。

開發階段,每次更改程式碼就要重新執行新程式

底下是一般要進入到images中執行程式碼的方式:

docker run --rm -it -p 8080:8080 -v $(pwd):/app node-docker-dev bash
root@id:/app# node src/server.js
  • nodemon是一套node.js下hot reload的工具,可以讓開發者非常方便的修改程式後,nodemon偵測到有程式碼異動,會自動將server reload。

將nodemon放入images中

FROM node:carbon

# Create app directory
WORKDIR /app

# Install nodemon for hot reload
RUN npm install -g nodemon

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install

# Bundle app source
COPY src /app

EXPOSE 8080
CMD [ "nodemon", "server.js" ]

重建上述images之後,我們就可以進入 images 去啟動 nodemon

$ cd node-docker
$ docker build -t node-hot-reload-docker .
$ docker run --rm -it -p 8080:8080 -v $(pwd):/app node-hot-reload-docker bash
root@id:/app# nodemon src/server.js

接下來程式設計師只需要異動app目錄下的任何程式碼,nodemon就會自動重啟server.js。

提供靜態檔案服務

上面的範例是假設你只提供API服務,若有靜態檔案也要一併提供服務,則可以使用下列的方式來提供。

  • Dockerfile
FROM node:carbon

# Create app directory
WORKDIR /app

# Install app dependencies
RUN npm -g install serve
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./

RUN npm install

# Bundle app source
COPY src /app
#Build react/vue/angular bundle static files
RUN npm run build

EXPOSE 8080
# serve dist folder on port 8080
CMD ["serve", "-s", "dist", "-p", "8080"]

建立正式區映像檔

# ---- Base Node ----
FROM node:carbon AS base
# Create app directory
WORKDIR /app

# ---- Dependencies ----
FROM base AS dependencies  
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# install app dependencies including 'devDependencies'
RUN npm install

# ---- Copy Files/Build ----
FROM dependencies AS build  
WORKDIR /app
COPY src /app
# Build react/vue/angular bundle static files
# RUN npm run build

# --- Release with Alpine ----
FROM node:8.9-alpine AS release  
# Create app directory
WORKDIR /app
# optional
# RUN npm -g install serve
COPY --from=dependencies /app/package.json ./
# Install app dependencies
RUN npm install --only=production
COPY --from=build /app ./
#CMD ["serve", "-s", "dist", "-p", "8080"]
CMD ["node", "server.js"]