CI/CDでdocker buildする際にnpmのライブラリインストールをキャッシュを活用することでスキップしたい。

デプロイ用イメージのFROMに指定するイメージをECR登録

ビルドした最終成果物をNginxイメージに追加してECSにデプロイするため、NginxのDockerfile(ファイル名をDockerfile-ecr-cache-nginxとする)を用意する。

FROM nginx:1.29.0
RUN rm /usr/share/nginx/html/*
RUN cat << EOF > /etc/nginx/conf.d/default.conf
server {
    listen 80;
    server_name localhost;
    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
        add_header Pragma "no-cache";
        add_header Expires 0;
    }
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}
EOF

AWSのCodeBuildを利用することを前提にするため、Docker HubのRate Limitを気にしなくて済むように、これをECRに保存する。

repo=nginx
docker image build . -f Dockerfile-ecr-cache-nginx -t ${repo}
aws_account_id=自身のid
region=ap-northeast-1
ecr=${aws_account_id}.dkr.ecr.${region}.amazonaws.com
aws ecr get-login-password --region ${region} | docker login --username AWS --password-stdin ${ecr}
docker tag ${repo}:latest ${ecr}/${repo}:lastest
docker push ${ecr}/${repo}:latest

ビルド用イメージのECR登録

ビルドに使うイメージを作成する。npm ciを実施することで、node_modulesを生成する。

FROM node:24
WORKDIR /app
COPY ./package.json /app/
COPY ./package-lock.json /app/
RUN npm ci --omit=dev

repo=buildnodeとして、同様にECRに保存する。

デプロイ用イメージのためのDockerfile

デプロイ用Dockerfileではnpm install --frozen-lockfileすることで、ビルド用イメージのnode_modulesを利用することができる。ここでnpm ciするとnode_modulesを消してからインストールが実行されてしまうので、npm ciではなくnpm installしている。

# ${ecr}は要置き換え
FROM ${ecr}/buildnode:latest AS build
WORKDIR /app
COPY . .
RUN npm install --omit=dev --prefer-offline --frozen-lockfile
RUN npx nuxt generate

FROM ${ecr}/nginx:latest
COPY --from=build /app/.output/public/ /usr/share/nginx/html/
EXPOSE 80

CI/CDパイプラインがこのDockerfileをビルドし、できあがったイメージをECRに保存、ECSデプロイを行う。