Dockerize Nuxt專案紀錄
前一陣子為了將原本的nuxt專案改到AWS ECS上發佈,花了一點時間把原本的專案dockerize了,以下紀錄過程中需要注意的地方。本篇不會介紹docker是什麼喔,對於docker是什麼不太清楚的可以參考Docker官網
第一步就是將原本的專案製作成image,因為之後會將image上傳到AWS的ECR上儲存,並且用ECS FARGATE來把容器跑起來,所以就沒有使用docker-compose而直接使用docker build來製作image。在專案的根目錄新增Dockerfile檔案,內容如下
FROM node:12.18.0-alpineRUN apk add --no-cache openssh-client git
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh/
RUN echo "${SSH_PRIVATE_KEY}" >> /root/.ssh/id_rsa
RUN chmod 0600 /root/.ssh/id_rsa
RUN touch /root/.ssh/known_hosts
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hostsWORKDIR /app/
COPY package.json yarn.lock* ./
RUN yarn install && yarn cache clean
COPY . /app/
RUN yarn buildFROM node:12.18.0-alpine
ENV NODE_ENV=production
WORKDIR /usr/src/
COPY --from=0 /app/ /usr/src/
ENV HOST=0.0.0.0
EXPOSE 3333
CMD ["node", "/usr/src/server/index.js"]
簡單的說明Dockerfile裡面的指令意義
FROM node:12.18.0-alpine
代表image使用的環境,node版本選擇12.18而alpine是製作容器常使用的OS,優點是檔案大小相當小,可以有效地縮小image檔案的大小,而且要安裝package也有很方便的指令apk add來安裝,如果沒有其他特別需求建議可以用alpine即可。
RUN apk add --no-cache openssh-client git
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh/
RUN echo "${SSH_PRIVATE_KEY}" >> /root/.ssh/id_rsa
RUN chmod 0600 /root/.ssh/id_rsa
RUN touch /root/.ssh/known_hosts
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
這一段是因為專案內有package是抓私有的git repository,之後在yarn install的時候如果沒有SSH key就沒有辦法安裝,所以我們利用ARG這個參數,在執行docker build指令的時候將key傳進來這樣才能夠正常的把專案所需的package抓進來。另外一種狀況是當你的專案內容不是從本機複製進image,而是需要把專案直接從私有的repository抓回來的話,也會需要處理ssh key的問題。
WORKDIR /app/
會將工作資料夾設定到/app/上,如果image內沒有/app/資料夾寫了這行就會替你建立起來,不需要先寫RUN mkdir /app/
COPY package.json yarn.lock* ./
RUN yarn install && yarn cache clean
COPY . /app/
RUN yarn build
這一行指令就是將本機專案資料夾裡的package.json和yarn.lock複製到image內的工作資料夾,並且在image裡執行yarn install把專案所需要的package給裝起來,接著再將專案內容複製進/app資料夾,然後才執行yarn build將我們的nuxt專案build起來。專案build完之後,因為這一份image裡面存有剛剛丟進來的ssh key,所以當然不能夠直接使用,所以會使用multi-stage的方法製作最終的image
FROM node:12.18.0-alpine
ENV NODE_ENV=production
WORKDIR /usr/src/
COPY --from=0 /app/ /usr/src/
ENV HOST=0.0.0.0
EXPOSE 3333
CMD ["node", "/usr/src/server/index.js"]
最後一樣使用node:12.18.0-alpine作為image的基礎,然後將之前存放的在stage 1 的/app資料夾複製到最終這一個stage 2 image裡面,並且將環境和對外連接的port設定好,最後將專案啟動。
接著在專案資料夾內執行
docker build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" -t project_name .
就會依據Dockerfile一步一步的將image建立起來,這裏的 — build-arg就是上述為了將ssh key傳進去容器內使用的。
另外需要建立.dockerignore檔案,把不需要複製的檔案設定好,基本上可以複製.gitignore即可。
因為是選擇使用ECS的FARGATE來啟動容器,就不需要另外安裝nginx來做伺服器代理,直接透過loadbalancer來處理流量即可,如果是要在EC2上面使用docker來佈建,就會建議改用docker-compose來處理容器的建立。
發佈到ECS的時候要注意的是因為ECS對於docker-compose的支援不高,使用了VPC連線之後各個container就沒辦法透過docker network來溝通,所以如果需要像是redis或者資料庫的話就要特別的留意溝通的問題。