Dockerfile

EBAB!·2023년 7월 13일
0

Docker

목록 보기
4/15
# [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

우선 FROM으로 이미지를 불러와서 베이스이미지 레이어를 올려놓습니다. 이 때 도커는 사용자의 이미지 레포지토리에서 node:14라는 이미지가 있는지 확인하고 없다면 docker hub에 공식적으로 제공하는 이미지들을 살피게 되고, 있다면 가져오게 됩니다.

node:14라는 이미지를 빌드한 적이 없기때문에 docker hub에서 가져오게 됩니다.

WORKDIR /app

WORKDIR은 말그대로 작업할 폴더를 설정합니다. 도커 내부의 위치를 의미하며 내부에 /app이란 폴더가 없다면 생성합니다.

COPY package.json .

COPY [현재 터미널에서 위치] [컨테이너 내의 위치] 를 통해 현재 파일을 컨테이너로 복사합니다. 앞의 위치가 파일 주소라면 파일을 복사하고 폴더라면 폴더를 복사합니다. 위에서 작업 위치를 /app으로 했으므로, 여기에서 ./app이 됩니다.

RUN npm install

도커 컨테이너 내부 작업위치에 해당 명령어를 실행합니다. package.json을 카피했으니 이를 바탕으로 설치를 한다는 의미가 됩니다.

COPY . .

위와 같이 모든 파일을 컨테이너로 복사합니다.
package.json을 복사하는 것과 분리하는 이유가 중요합니다.

package.json 분리
우리가 개발을 하면 간단한 코드 수정은 많이 하지만 패키지 설치 및 삭제를 자주하지 않습니다.
만약 우리가 조금이든 많이든 코드를 수정한다면 이전의 이미지를 새롭게 rebuilding 해야합니다.
실제로 docker는 dockerfile을 보면서 수정된 부분부터만 새롭게 rebuilding을 합니다. 중요한 부분은 수정된 부분부터 마지막까지 rebuilding한다는 점입니다.
따라서 수정이 잘 일어나지 않고 용량이 큰 패키지 부분을 앞서 설치한 뒤 뒤의 코드 파일을 받아오면, 코드 수정시 해당 파일만 수정이 일어나므로 rebuilding 시간을 크게 줄일 수 있습니다.

정리하면, 이미지의 모든 명령은 캐시 가능한 레이어를 생성하고, 레이어는 이미지 재구축 및 공유를 도와주는 역할을 합니다.

ARG DEFAULT_PORT=80

컨테이너를 생성할 시 인수를 설정합니다. 이렇게 선언된 인수는 컨테이너 내부에서 고유하게 저장되고 Dockerfile에서도 다음 줄부터 곧바로 사용이 가능합니다.

ENV PORT $DEFAULT_PORT

포트 번호를 환경변수로 지정하고 동적으로 할당합니다. 나중에 컨테이너 실행 시 옵션으로 포트번호가 바뀔 수 있기 때문에 환경 변수는 PORT로 지정한 뒤 디폴트를 두는 방식을 사용합니다.

인수나 환경변수를 사용할 때는 앞에$표시를 붙여 알려줍니다.

EXPOSE $PORT

docker container는 프로세스지만 하나의 독립된 공간이라 했습니다. 따라서 컨테이너와 통신하기위한 명확한 포트를 열어두어야 docker container와의 통신이 가능합니다. 이를 위해 열어두는 포트를 설정합니다.

중요한 점은 이 명령어는 사실 아무것도 안합니다. 오직 문서화의 목적으로만 작성되기 때문에 반드시 컨테이너 실행 시 포트 설정을 해주어야 합니다.

CMD ["node","app.mjs"]

node app.mjs 명령어를 실행합니다.
RUN과의 차이점은, RUN은 컨테이너 환경을 구성하는데 필요한 명령어입니다. 이미지는 결국 컨테이너의 템플릿이니 컨테이너 환경을 구성하기 위한 명령어들이 실행되어야 합니다.
그래서 컨테이너를 생성하기 위해 RUN이 실행이 되는 것이고, CMD는 컨테이너가 실행된 후 컨테이너에서 실행되는 명령어입니다.

자주 사용되는 명령어 간단 정리

  1. FROM [image]:[tag]:

    • 설명: 기반이 되는 이미지를 지정합니다.
    • 예시:
      FROM ubuntu:latest
  2. RUN [명령어]:

    • 설명: 컨테이너 내에서 실행할 명령어를 지정합니다.
    • 예시:
      RUN apt-get update && apt-get install -y \
          package1 \
          package2
  3. COPY/ADD [src] [dest] :

    • 설명: 호스트 시스템의 파일이나 디렉토리를 컨테이너 내부로 복사합니다.
    • 예시:
      COPY app.py /app/app.py
    • 일반적으로는 COPY를 쓰는 것이 정확하고, 소스가 url 원격 파일이라던가 압축 파일이라면 ADD를 사용합니다.
      • ADD는 압축파일을 복사할 때 압출해제를 하면서 복사를 합니다.
  4. WORKDIR [dir address in container]:

    • 설명: 명령어를 실행할 작업 디렉토리를 설정합니다.
    • 예시:
      WORKDIR /app
  5. EXPOSE [port number]:

    • 설명: 컨테이너가 실행될 때 오픈할 포트를 지정합니다.
    • 예시:
      EXPOSE 8080
  6. CMD [명령어]:

    • 설명: 컨테이너가 시작될 때 실행할 명령어를 지정합니다.
    • 예시:
      CMD ["python", "app.py"]
    • 띄어쓰기 대신 배열에 띄어쓰기마다 문자열을 담는 형태로 작성
  7. ENTRYPOINT:

    • 설명: 컨테이너가 시작될 때 실행할 명령어를 지정합니다.
    • 예시:
      ENTRYPOINT ["python", "app.py"]
    • 이미지를 컨테이너로 실행 시, CMD는 추가 인수가 전달될 때 무시되지만 ENTRYPOINT는 항상 실행됩니다. 따라서 반드시 실행되어야 할 명령어를 ENTRYPOINT로 지정하는 것이 좋습니다.
  8. ENV [key=value]:

    • 설명: 환경 변수를 설정합니다.
    • 예시:
      ENV DB_HOST=localhost \
          DB_PORT=5432
  9. VOLUME [path_in_container]:

    • 설명: 호스트와 컨테이너 간의 데이터 공유를 위한 마운트 포인트를 지정합니다.
    • 예시:
      VOLUME /data
    • 호스트와 공유하는 다양한 옵션이 있지만 뒤에서 자세히 다루겠습니다.
  10. USER [username]:

    • 설명: 컨테이너에서 실행할 사용자를 지정합니다.
    • 예시:
      USER appuser
  11. LABEL [key=value]:

    • 설명: 이미지에 메타데이터 라벨을 추가합니다.
    • 예시:
      LABEL maintainer="yourname@example.com"
  12. ARG [key=value]:

    • 설명: 빌드 시에만 사용되는 변수를 정의합니다.
    • 예시:
      ARG version=latest
profile
공부!

0개의 댓글