結論
Dockerのマルチステージビルドを利用すると楽に実現できる
効果
- イメージサイズの削減
- 環境の分離
- アプリケーションのビルドと実行がそれぞれ異なる環境で行われる
差分
マルチステージビルド導入前
package.json
{
...
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "nodemon"
},
...
"dependencies": {
"express": "^4.18.2",
"typescript": "^5.1.6",
"@types/express": "^4.17.17"
},
"devDependencies": {
"nodemon": "^3.0.1",
"ts-node-dev": "^2.0.0"
}
}
dockerfile.production
FROM node:18.16.1
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
#### トランスパイル
RUN npm run build
#### 成果物の実行
CMD ["npm", "run", "start"]
マルチステージビルド導入後
package.json
{
...
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "nodemon"
},
...
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"@types/express": "^4.17.17",
"nodemon": "^3.0.1",
"ts-node-dev": "^2.0.0",
"typescript": "^5.1.6"
}
}
dockerfile.production
## ビルドステージ
FROM node:18.16.1 AS build-stage
WORKDIR /app
COPY package*.json ./
#### このステージではトランスパイルが必要なのでtypescript関連のパッケージは含まれる
RUN npm install
COPY . .
#### トランスパイル
RUN npm run build
## ランタイムステージ
FROM node:18.16.1 AS production-stage
WORKDIR /app
COPY package*.json ./
#### トランスパイル後の成果物だけビルドステージからコピーする
COPY --from=build-stage /app/dist /app/dist
#### トランスパイル不要の状況を作り出せたのでexpressのインストールだけでいい
RUN npm install --production
EXPOSE 3000
#### 成果物の実行
CMD ["npm", "run", "start"]