tech.junha.kr

노트/Docker

DockerFile Syntax

작성 수정

1. FROM

  • Dockerfile의 기본 이미지(base image)를 지정
  • Docker 이미지 빌드는 항상 FROM으로 시작되며, 이 명령어를 통해 컨테이너가 어느 환경을 기반으로 할지를 정해
  • 형식: FROM <이미지 이름>:<태그>
# Node.js 18 버전이 포함된 경량 Alpine Linux를 기반으로 이미지를 빌드한다는4 의미

FROM node:18-alpine

2. RUN

  • 이미지가 빌드될 때 실행할 명령어 지정
  • 패키지 설치, 파일 복사, 소스 코드 빌드 등 작업 수행
  • 각 RUN 명령은 새로운 레이어를 생성하며, 이미지 빌드 단계에서만 실행돼.
  • 이는 Docker의 이미지 캐싱 및 레이어 기반 구조 때문인데, Docker는 이미지의 각 명령어(RUN, COPY, ADD 등)를 실행할 때마다 해당 명령의 결과를 캐시하여 레이어를 생성해.
  • 이 레이어는 다음 단계로 전달되어 이미지가 단계적으로 쌓이게 되지.
# 하나의 레이어 생성
RUN apt-get update

# 또 다른 레이어 생성
RUN apt-get install -y curl
  • 각 RUN 명령어는 그 자체로 캐시될 수 있는 하나의 레이어가 되고, Docker는 이를 재사용하거나 빌드 중단 시 다시 사용할 수 있어.
  • 만약 이미 해당 레이어가 변경되지 않았으면 Docker는 이 단계를 다시 실행하지 않고 캐시된 레이어를 사용하지.

3. CMD

  • 컨테이너가 실행될 때 수행할 명령을 지정해.
  • CMD는 기본적으로 하나의 컨테이너에 하나만 있어야함.
CMD ["node", "app.js"]

Docker CMD 명령어

CMD ["sh", "-c", "pm2-runtime start /app/ecosystem.config.js && nginx -g 'daemon off;'"]
  • "sh", "-c"

    • 쉘을 열어 여러 명령을 실행
    • 쉘의 고급 기능(명령 체이닝 등)을 사용할 수 있도록 함
    • 이걸 사용하면 pm2와 nginx를 한 번에 실행할 수 있는 거야.
  • && 연산자

    • 첫번째 명령이 성공하면 두 번째 명령이 실행되게끔 쉘에서 처리하고 있어.
  • nginx -g 'daemon off;' 명령어

    • 도커 컨테이너는 모든 프로세스가 백그라운드로 돌게 되면 포그라운드에서 실행 중인 메인 프로세스가 없기 때문에 컨테이너가 더 이상 할 일이 없다고 간주하고 종료한다.
    • Nginx를 포그라운드에서 실행시켜야 컨테이너가 계속 살아있는 상태로 유지된다.
  • RUN vs CMD의 주요 차이는 실행 시점

    • RUN
      • 이미지를 빌드할 때 실행됨
      • 이미지에 새로운 레이어를 만듦
      • 주로 패키지 설치, 파일 생성 등 이미지 구성에 사용
    RUN npm install
    RUN mkdir /app/data
    
    • CMD
      • 컨테이너가 시작될 때 실행됨
      • 컨테이너의 기본 실행 명령어를 지정
      • 한 Dockerfile에서 마지막 CMD만 적용됨
    CMD ["npm", "start"]
    
    • 실제 예시
    # 빌드 시점에 실행
    RUN npm install
    RUN npm build
    
    # 컨테이너 시작 시점에 실행
    CMD ["npm", "run", "prod"]
    

    또한 docker run 명령어로 override 가능 여부도 다릅니다:

    • RUN: override 불가능 (이미 이미지에 포함됨)
    • CMD: override 가능 (컨테이너 실행 시 다른 명령어 지정 가능)

    # 4. 빌드 시점의 작업들 (RUN)

    RUN npm install RUN npm run build

    # 5. 마지막으로 실행할 명령어 (CMD)

    CMD ["npm", "run", "prod"]

    Override는 "덮어쓰기" 또는 "재정의"라는 의미입니다.

    CMD의 경우 override 예시:

    dockerfile
    Copy
    # Dockerfile
    CMD ["npm", "run", "prod"]
    
    

    이렇게 정의되어 있어도:

    bash
    Copy
    # 다른 명령어로 덮어쓰기 가능
    docker run junha-today:latest npm run dev
    docker run junha-today:latest /bin/bash
    

    이렇게 실행하면 Dockerfile의 CMD 명령어 대신 새로 지정한 명령어가 실행됩니다.

    반면 RUN은:

    dockerfile
    Copy
    RUN npm install
    
    

    이미 이미지 빌드 때 실행되어 이미지의 일부가 되었기 때문에, 나중에 컨테이너 실행 시점에서는 바꿀 수 없습니다.

4. WORKDIR

  • 기능: 작업 디렉토리를 설정하는 명령어로, 이후 명령어들이 실행될 기본 디렉토리를 정의해. 여러 WORKDIR 명령어가 있을 경우, 각각이 누적되면서 경로를 설정해 줘.

  • 형식: WORKDIR <경로>

  • 예시: 이후 명령들은 /app 디렉토리에서 실행되게 돼.

    WORKDIR /app
    

5. COPY

  • 기능: 호스트 시스템의 파일이나 디렉토리를 이미지의 특정 경로로 복사하는 명령어야. 주로 프로젝트 소스 파일들을 이미지에 복사하는 데 사용해.

  • 형식: COPY <호스트 경로> <컨테이너 경로>

  • 예시: 현재 디렉토리(.)의 모든 파일을 컨테이너의 /app 디렉토리로 복사해.

    COPY . /app
    

6. EXPOSE

  • 컨테이너에서 열어줄 포트를 명시, 문서화 목적으로 주로 사용
  • 실제 포트 열기는 docker run 시 p 옵션을 사용해 실행해야함
  • EXPOSE 3000

4. ENV

  • 기능: 환경 변수를 설정하는 명령어로, 컨테이너 내에서 특정 환경 변수를 정의할 수 있어. 이 환경 변수는 이후 컨테이너 실행 시 사용할 수 있어.
  • 형식: ENV <변수명>=<값>
  • 예시:NODE_ENV라는 환경 변수를 production으로 설정해.
ENV NODE_ENV=production

7. ENTRYPOINT

  • 기능: 컨테이너가 실행될 때 항상 실행될 명령어를 지정해. CMD와 비슷하지만, ENTRYPOINT는 항상 고정된 명령어를 설정하고, 이를 통해 CMD의 매개변수를 받을 수 있어.
  • 형식: ENTRYPOINT ["실행 파일", "옵션"]
  • 예시: 이 명령어는 컨테이너가 실행될 때 npm start를 실행하게 돼.
ENTRYPOINT ["npm", "start"]

8. ARG

  • ARG와 ENV는 Dockerfile에서 환경 변수를 설정하는 방식이다.
  • 각각 빌드 타임과 런타임에서 어떻게 변수가 사용되는지에 따라 구분된다.
docker build --build-arg NODE_ENV=production -t my-image .
ARG NODE_ENV
RUN echo "Building for environment: $NODE_ENV"
  • NODE_ENV 값을 production으로 받아와서 이미지 빌드 중에 사용가능
  • 빌드 타임 변수로만 사용돼. 즉, Docker 이미지가 빌드될 때만 존재하고, 컨테이너가 실행될 때는 사용되지 않아.
  • ARG로 설정한 변수는 Dockerfile에서 RUN 명령어나 다른 빌드 과정에서만 사용할 수 있고, 기본적으로 런타임에는 노출되지 않아.
  • cloudbuild.yaml의 --build-arg로 값을 전달할 수 있어.

예시

# 빌드 타임 변수 선언
ARG NODE_ENV
RUN echo "Building for $NODE_ENV environment" 

이렇게 하면 Dockerfile이 빌드될 때 NODE_ENV 값이 RUN 명령어에서 사용되지만, 컨테이너 실행 시에는 이 변수에 접근할 수 없어.

ENV

  • 빌드 타임과 런타임 둘 다 사용할 수 있는 변수로, Dockerfile에서 설정되면 이미지와 함께 저장돼서 컨테이너가 실행될 때 자동으로 환경 변수로 설정돼.
  • 런타임에 추가 설정 없이, CMD나 ENTRYPOINT 등에서 직접 사용할 수 있어.

예시

ARG NEXTAUTH_SECRET
ENV NEXTAUTH_SECRET=$NEXTAUTH_SECRET

이 경우 NEXTAUTH_SECRET은 컨테이너 실행 시에도 사용할 수 있는 환경 변수로 설정돼서, 컨테이너 내부에서 process.env.NEXTAUTH_SECRET처럼 접근할 수 있어.

요약

  • ARG: 빌드 타임에만 유효, 런타임에는 사용되지 않음.
  • ENV: 빌드와 런타임 둘 다 사용 가능, 컨테이너가 시작될 때 환경 변수로 유지돼.

구분

맞아, 다시 설명하자면 Dockerfile의 ENV 변수는 이미지 빌드 후에도 컨테이너 실행 시 환경 변수로 유지돼.

ARG는 빌드 시점에만 사용되고, 이미지가 빌드된 후에는 사라져. ENV는 빌드 시점에도 사용 가능하고, 컨테이너 실행 시에도 환경 변수로 적용돼서 계속 유지돼.

Dockerfile 예시

ARG NODE_ENV=development
RUN echo "Building with NODE_ENV=$NODE_ENV"

ENV APP_ENV=production
RUN echo "App will run in $APP_ENV mode"
  • NODE_ENV는 빌드 시에만 사용되고, 이후 컨테이너에서는 접근할 수 없어.

  • APP_ENV는 빌드 시에도 사용되며, 컨테이너가 실행될 때에도 환경 변수로 설정돼서 계속 접근 가능해.

  • 컨테이너가 실행될 때도 ENV 변수를 사용할 수 있기 때문에 런타임 환경 변수로도 동작하는 거야.

ARG NODE_ENV는 빌드 타임 변수로, 빌드 도중에만 유효