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를 포그라운드에서 실행시켜야 컨테이너가 계속 살아있는 상태로 유지된다.
-
RUNvsCMD의 주요 차이는 실행 시점RUN- 이미지를 빌드할 때 실행됨
- 이미지에 새로운 레이어를 만듦
- 주로 패키지 설치, 파일 생성 등 이미지 구성에 사용
RUN npm install RUN mkdir /app/dataCMD- 컨테이너가 시작될 때 실행됨
- 컨테이너의 기본 실행 명령어를 지정
- 한 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는 빌드 타임 변수로, 빌드 도중에만 유효