# [Dockerfile]
FROM node:14
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
ARG DEFAULT_PORT=80
ENV PORT $DEFAULT_PORT
EXPOSE $DEFAULT_PORT
CMD ["node","app.mjs"]
이전 글에서 간단히 설명했던 부분을 자세히 얘기해보겠습니다.
우선 FROM
으로 이미지를 불러와서 베이스이미지 레이어를 올려놓습니다. 이 때 도커는 사용자의 이미지 레포지토리에서 node:14
라는 이미지가 있는지 확인하고 없다면 docker hub에 공식적으로 제공하는 이미지들을 살피게 되고, 있다면 가져오게 됩니다.
node:14라는 이미지를 빌드한 적이 없기때문에 docker hub에서 가져오게 됩니다.
WORKDIR은 말그대로 작업할 폴더를 설정합니다. 도커 내부의 위치를 의미하며 내부에 /app이란 폴더가 없다면 생성합니다.
COPY [현재 터미널에서 위치] [컨테이너 내의 위치]
를 통해 현재 파일을 컨테이너로 복사합니다. 앞의 위치가 파일 주소라면 파일을 복사하고 폴더라면 폴더를 복사합니다. 위에서 작업 위치를 /app으로 했으므로, 여기에서 .
은 /app
이 됩니다.
도커 컨테이너 내부 작업위치에 해당 명령어를 실행합니다. package.json을 카피했으니 이를 바탕으로 설치를 한다는 의미가 됩니다.
위와 같이 모든 파일을 컨테이너로 복사합니다.
package.json을 복사하는 것과 분리하는 이유가 중요합니다.
package.json 분리
우리가 개발을 하면 간단한 코드 수정은 많이 하지만 패키지 설치 및 삭제를 자주하지 않습니다.
만약 우리가 조금이든 많이든 코드를 수정한다면 이전의 이미지를 새롭게 rebuilding 해야합니다.
실제로 docker는 dockerfile을 보면서 수정된 부분부터만 새롭게 rebuilding을 합니다. 중요한 부분은 수정된 부분부터 마지막까지 rebuilding한다는 점입니다.
따라서 수정이 잘 일어나지 않고 용량이 큰 패키지 부분을 앞서 설치한 뒤 뒤의 코드 파일을 받아오면, 코드 수정시 해당 파일만 수정이 일어나므로 rebuilding 시간을 크게 줄일 수 있습니다.
정리하면, 이미지의 모든 명령은 캐시 가능한 레이어를 생성하고, 레이어는 이미지 재구축 및 공유를 도와주는 역할을 합니다.
컨테이너를 생성할 시 인수를 설정합니다. 이렇게 선언된 인수는 컨테이너 내부에서 고유하게 저장되고 Dockerfile에서도 다음 줄부터 곧바로 사용이 가능합니다.
포트 번호를 환경변수로 지정하고 동적으로 할당합니다. 나중에 컨테이너 실행 시 옵션으로 포트번호가 바뀔 수 있기 때문에 환경 변수는 PORT로 지정한 뒤 디폴트를 두는 방식을 사용합니다.
인수나 환경변수를 사용할 때는 앞에$
표시를 붙여 알려줍니다.
docker container는 프로세스지만 하나의 독립된 공간이라 했습니다. 따라서 컨테이너와 통신하기위한 명확한 포트를 열어두어야 docker container와의 통신이 가능합니다. 이를 위해 열어두는 포트를 설정합니다.
중요한 점은 이 명령어는 사실 아무것도 안합니다. 오직 문서화의 목적으로만 작성되기 때문에 반드시 컨테이너 실행 시 포트 설정을 해주어야 합니다.
node app.mjs
명령어를 실행합니다.
RUN과의 차이점은, RUN은 컨테이너 환경을 구성하는데 필요한 명령어입니다. 이미지는 결국 컨테이너의 템플릿이니 컨테이너 환경을 구성하기 위한 명령어들이 실행되어야 합니다.
그래서 컨테이너를 생성하기 위해 RUN이 실행이 되는 것이고, CMD는 컨테이너가 실행된 후 컨테이너에서 실행되는 명령어입니다.
FROM [image]:[tag]
:
FROM ubuntu:latest
RUN [명령어]
:
RUN apt-get update && apt-get install -y \
package1 \
package2
COPY/ADD [src] [dest]
:
COPY app.py /app/app.py
WORKDIR [dir address in container]
:
WORKDIR /app
EXPOSE [port number]
:
EXPOSE 8080
CMD [명령어]
:
CMD ["python", "app.py"]
ENTRYPOINT
:
ENTRYPOINT ["python", "app.py"]
ENV [key=value]
:
ENV DB_HOST=localhost \
DB_PORT=5432
VOLUME [path_in_container]
:
VOLUME /data
USER [username]
:
USER appuser
LABEL [key=value]
:
LABEL maintainer="yourname@example.com"
ARG [key=value]
:
ARG version=latest