Dockerfile 기초 문법 이해 | FROM, RUN, CMD, ENTRYPOINT, COPY, ADD, ENV, WORKDIR, EXPOSE

mj·2024년 12월 11일
0

kbt

목록 보기
14/18
post-thumbnail

💡 Dockerfile 기초 문법 이해

  • FROM, RUN, CMD, ENTRYPOINT 등의 기본 명령어
  • COPY, ADD 차이점
  • ENV, WORKDIR, EXPOSE 등 기본 설정
  • Dockerfile을 통한 이미지 빌드 실습



🐳 기본 명령어


FROM

Docker이미지를 생성할때 기반이 되는 이미지를 지정.

모든 Dockerfile은 FROM으로 시작해야 한다.

# Node.js 14버전을 기반으로 이미지를 생성한다.
FROM node:14

RUN

이미지를 빌드하는 동안 실행될 명령어를 작성

주로 패키지 설치, 환경 설정 등에 사용

# 리눅스 패키지 매니저로 curl설치하기
RUN apt-get update && apt-get install -y curl

CMD

컨테이너가 실행될 때 기본으로 실행되는 명령을 지정

마지막에 선언된 단 하나만 유효.

# 컨테이너가 실행될 때 자동으로 node app.js 실행
CMD ["node", "app.js"]
  • CMD 오버라이드 (덮어쓰기 문제)
    node app.js 가 아닌 echo “Hello”가 실행된다.
    ```bash
    docker run my-node-image echo "Hello"
    ```

ENTRYPOINT

컨테이너가 실행될 때 반드시 실행되어야 할 주 명령을 지정

마지막에 선언된 단 하나만 유효.

CMD로부터 인자를 전달받아 사용 가능.

# 실행결과 : python3 app.py
ENTRYPOINT ["python3"]
CMD ["app.py"]



🐳 COPY, ADD 차이점


COPY

호스트(로컬 시스템)의 파일이나 디렉토리를 컨테이너로 복사

  • 로컬 시스템에서만 작동하며, URL이나 다른 원격 소스에서 직접 파일을 복사할 수 없다.
# 현재 디렉토리의 index.html을 컨테이너 내부의 Nginx 디렉토리로 복사
COPY index.html /usr/share/nginx/html/

ADD

COPY 와 유사하지만 몇가지 추가 기능을 제공한다.

  • URL을 통해 파일 다운로드 가능
  • 압축파일이면 압축을 해제한 상태로 파일을 복사

차이점

COPYADD
기능단순 기능추가 기능 제공
원격 소스 처리로컬 파일에만 사용가능원격 URL에서 파일 다운로드 가능
자동 압축 해제X압축된 파일을 자동으로 압축해제
  • COPY : 단순하고 명확한 작업에 적합
  • ADD : 부가적인 기능이 있어 다소 불투명
    • 부가 동작이 자동으로 수행되기 때문에 개발자가 명령어의 결과를 명확히 예상하기 어렵다.
    • 예) 실수로 압축파일을 의도치 않게 해제하거나 url이 잘못 동작하거나…



🐳 ENV, WORKDIR, EXPOSE 등 기본 설정


ENV

환경 변수를 설정

  • 환경 변수와 docker run을 함께 사용하는 경우, 환경변수 덮어쓰기가 가능
    # 기본 환경 변수 설정
    ENV APP_MODE=production
    docker run -e APP_MODE=development my-app

WORKDIR

컨테이너 내에서 작업 디렉토리를 지정

후속 명령어들이 이 디렉토리 내에서 실행되도록 할 수 있다.

# 컨테이너의 /app에서 명령어가 실행되도록 한다.
WORKDIR /app
  • 여러 번 사용 가능, 이를 통해 디렉토리 구조를 변경하면서 작업할 수 있다.
  • 절대경로 사용 예시
    /app/src
    # 베이스 이미지
    FROM node:14
    
    # 첫 번째 작업 디렉토리 설정
    WORKDIR /app
    
    # /app 디렉토리에서 파일 복사
    COPY . .
    
    # 절대 경로로 하위 디렉토리 설정
    WORKDIR /src
    
    # /src 디렉토리에서 의존성 설치
    RUN npm install
  • 이전 경로에 상대적으로 설정
    /app/app/src
    # 베이스 이미지
    FROM node:14
    
    # 첫 번째 작업 디렉토리 설정
    WORKDIR /app
    
    # /app 디렉토리에서 파일 복사
    COPY . .
    
    # 상대 경로로 하위 디렉토리 설정
    WORKDIR src
    
    # /app/src 디렉토리에서 의존성 설치
    RUN npm install
  • 상대경로로 경로 변경
    # 베이스 이미지
    FROM node:14
    
    # 첫 번째 작업 디렉토리 설정
    WORKDIR /app
    
    # /app 디렉토리에서 파일 복사
    COPY . .
    
    # 상위 디렉토리로 이동
    WORKDIR ..
    
    # / 디렉토리로 이동된 상태에서 실행
    RUN ls
    

EXPOSE

컨테이너에서 외부에 노출할 포트를 지정

EXPOSE 3000
  • EXPOSE는 컨테이너 내부 포트를 열어놓는 것일 뿐, 실제로 외부와 포트를 연결하는 건 아니다. 외부와 연결하려면 docker run 명령어에서 -p 옵션을 사용해야 한다.
    FROM ubuntu:20.04
    EXPOSE 80
    docker run -p 8080:80 my_image
    컨테이너의 80번 포트를 호스트의 8080번 포트와 연결 이제 브라우저에서 localhost:8080으로 접속하면, 컨테이너 내부에서 실행 중인 웹 서버에 접근할 수 있다.



🐳 Dockerfile을 통한 이미지 빌드 실습


# 베이스 이미지 
FROM node:14

# 작업 디렉토리 지정 
WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]
docker build -t express-deepdive .
docker run -p 3000:3000 express-deepdive


ENV 실습

# Ubuntu 20.04를 베이스 이미지로 사용
FROM ubuntu:20.04

# 환경 변수 설정
ENV MY_APP_NAME=express-deepdive
ENV MY_APP_VERSION=1.0

# 환경 변수 값을 확인하기 위해 작업 디렉토리를 설정
WORKDIR /app

# 단순한 쉘 스크립트 실행
# CMD echo "App Name: $MY_APP_NAME, Version: $MY_APP_VERSION"
CMD ["bash", "-c", "echo \"App Name: $MY_APP_NAME, Version: $MY_APP_VERSION\""]


ADD 실습


출처: https://malwareanalysis.tistory.com/233

파일 복사하지 않고 다운로드

FROM busybox:1.34.1

RUN mkdir test
ADD https://google.com/index.html /test/
docker build -t local:add .
docker run --rm -it local:add /bin/sh
/ # cd test
/test # ls



Q&A


❓ RUN과 CMD의 차이

패키지 설치를 RUN명령어를 통해 이미지 빌드시점에 하는 이유

CMD나 ENTRYPOINT는 주로 컨테이너가 실행될 때 실행될 명령어를 지정하는 데 사용됩니다. 패키지 설치는 일반적으로 한 번만 실행되면 되는 작업이므로, 컨테이너 실행 시점이 아니라 빌드 시점에 처리하는 것이 더 적합합니다.

  • 빠른 실행, 불필요한 리소스 소모 방지 RUN 명령어로 이미 패키지가 설치되어 있기 때문에 컨테이너 실행 시점에 매번 패키지를 설치할 필요가 없습니다. 만약 CMD나 ENTRYPOINT에서 패키지를 설치한다면, 컨테이너가 시작될 때마다 설치 작업이 발생하여 불필요한 리소스를 소모하게 됩니다.
  • 레이어 캐시 활용 도커는 이미지를 빌드할 때 캐시를 활용합니다. 만약 패키지 설치가 RUN 명령어로 이루어지면, 이전에 동일한 명령어를 사용한 빌드를 캐시로 재사용할 수 있어 빌드 속도가 빨라집니다. 반면, CMD에서 설치 작업을 하면 매번 새로 설치해야 하므로 캐시를 활용할 수 없습니다.
  • 패키지 중복 설치 방지 매번 컨테이너를 실행할 때마다 설치를 시도할 수 있기 때문에, 설치가 실패하거나 중복 설치가 발생할 가능성도 있습니다.
  • 네트워크 의존성 낮추기 실행 시점에 패키지를 설치하면, 네트워크에 의존하게 됩니다. 만약 네트워크가 불안정하거나 패키지 서버가 다운되면 컨테이너 실행이 실패할 수 있습니다.



참고)

https://malwareanalysis.tistory.com/233

profile
일단 할 수 있는걸 하자.

0개의 댓글