Day2 Dockerfile
1. Dockerfile
0) 사전준비
앞서 첫날에는 MSA, Docker에 관해서 알아보았다. 오늘은 그 중에서 프로젝트 안에 있는 Dockerfile을 공부했다.
프로젝트 예시는 앞으로 "eShop on Dapr"라는 것을 사용할 예정이다.
1) Dockerfile 명령어
명령어를 알아보기 이전에, Dockerfile을 바탕으로 Docker image가 만들어 진다는 사실을 알았다.
그 방법을 먼저 간단히 살펴보자.
docker build -f /path/to/a/Dockerfile -t testImage:1.0
docker build란 명령어로 image를 간단히 생성히 가능하다.
뒤의 내용들은 옵션이며 내용은 아래와 같다.
- ' -f ' : docker build 시 참조할 파일의 이름이 Dockerfile이 아니거나, 위치가 현재의 위치에 존재하지 않을 경우 직접 build할 파일을 지정할 수 있다.
- ' -t ' : build로 생기는 image의 이름을 정할 수 있다. 정하지 않으면 임의의 숫자값으로 나오기 때문에 사용을 추천하는 옵션이다.
- FROM : 베이스 이미지 (image layer 하나로 취급).
어느 이미지에서 시작할 건지를 정해주는 명령어.
- RUN : 새로운 image layer를 생성하고, 필요한 패키지들을 설치할 때 사용함.
표현식은 2가지 방법이 존재한다.
- Shell form (default /bin/sh -c on LINUX, cmd /S /C on Windows)
RUN apt-get update -yq \ && apt-get install curl gnupg -yq \ && curl -sL https://deb.nodesource.com/setup_10.x | bash \ && apt-get install nodejs -yq
- exec form
RUN ["/bin/bash", "-c", "echo hello"]
- CMD and ENTRYPOINT : 둘 다 image를 바탕으로 생성된 container에서 명령어를 실행한다.
CMD ["dotnet", "WebSPA.dll"]
ENTRYPOINT ["dotnet", "WebSPA.dll"]
둘의 차이점은 아래와 같다.
- CMD = 추가적인 명령어에 따라서 명령어를 수정해서 실행한다.
docker run --name <container-name> <image-name> > This is a test docker run --name <container-name> <image-name> echo "Hello" > Hello
- ENTRYPOINT = 추가 명령어 존재와 상관없이 무조건 실행
docker run --name <container-name> <image-name> > Hello world docker run --name <container-name> <image-name> ME > Hello ME
- HEALTHCHEACK : container의 프로세스 상태를 체크할 수 있다.
명령 옵션들은 아래와 같다.
옵션 | 설명 | 기본값 |
---|---|---|
--interval=Duration | 헬스 체크 간격 | 30s |
--timeout=Duration | 타임 아웃 | 30s |
--retries=N | 타임아웃횟수 | 3 |
상태값은 아래와 같다.
EXIT Code | 설명 |
---|---|
0: success | 컨테이너 정상 |
1: unhealthy | 컨테이너 작동 불량 |
2: starting | 위의 exit code를 사용하지 않음 |
container의 상태는 아래와 같이 확인가능하다.
docker container inspect [container name]
위의 옵션들을 적용한 예시이다.
HEALTHCHECK --interval=10s --timeout=3s CMD curl -f http://127.0.0.1/ || exit 1
( 10초마다 위 주소를 체크 하는데, 3초 이상이 걸리거나, 3번의 재시도가 실패하면 unhealthy 상태로 변경해라 )
- COPY and ADD : 둘 다 host OS의 파일이나 디렉토리를 container 안의 지정한 경로로 복사한다.
둘의 차이는 아래와 같다.
COPY <src>... <destination>
COPY ["<src>",... "<destination>"]
ADD <src>... <destination>
ADD ["<src>",... "<destination>"]
- COPY = container 안으로 정확히 복사만 가능하다.
- ADD = container 안으로 복사를 하면서 tar 파일처럼 압축된 파일을 해제하거나 하는 기능이 들어있다.
보통 COPY가 투명하게 과정이 보이기 때문에 default로 사용한다.
( COPY는 오직 container 안의 local file들을 단순히 COPY하는 것 밖에 못한다. Docker client로 부터 적혀진 디렉토리에 파일을 추가한다. )
( 반면 ADD는 remote URL을 지원하거나, local-only tar 파일을 추출하는 것 같은 직관적이지 않은 부가기능을 제공한다. )
- ENV and ARG : 둘 다 변수를 설정하는 명령어.
둘의 차이는 아래와 같다.
- ENV = Dockerfile & container 안에서 변수로 사용가능
- ARG = Dockerfile에서만 변수로 사용가능
- WORKDIR : 명령을 실행하기 위한 디렉토리 지정.
- 작업 디렉토리를 지정하면 이후에는 이 지정된 값을 기준으로 동작함.
- 즉 terminal의 cd 명령어와 비슷하다.
- LABEL : image version, 작성자, 코멘트 처럼 image의 metadata를 입력할 때 사용
LABEL title="webserver"
LABEL version="2.0"
- EXPOSE : container가 대기할 네트워크 port를 알려줌.
( 보통 평균적으로 많이 쓰는 port를 사용, Apache: 80, MongoDB: 27017 )
하지만 이 명령 자체가 port를 실행하여 listening 상태로 올려주지는 않기 때문에 실제로 port를 열기 위해서는 container run -p 로 컨테이너를 실행할때 옵션으로 실행시켜 줘야 함
dockerfile을 작성하는 사람과 container를 실행할 사람 사이에서 공개port를 알려주기 위한 구문
- VOLUME : container를 삭제하면 안의 모든 데이터가 유실되기 때문에 보존할 데이터는 VOLUME을 사용해서 host OS에 저장하고, container 간의 데이터 공유 가능
FROM centos:7
VOLUME ["/var/log/", "/data/"]
/var/log 의 데이터와, /data/ 의 데이터는 host OS의 /var/lib/docker/volumes/ 에 저장된다.
2) eShop on Dapr's Dockerfiles
eShop on Dapr의 Dockerfile 중에서 2가지를 위에서 공부한 내용을 바탕으로 읽어보자.
// src/Services/Basket/Basekt.API/Dockerfile
ARG NET_IMAGE=5.0-buster-slim // NET_IMAGE라는 dockerfile에서만 쓸 수 있는 변수 설정
FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base // 시작할 image를 정하고 이름을 base로 설정
WORKDIR /app // app에서 시작하고
EXPOSE 80 // 80 port로 진행
FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build // image 를 build라고 명명
WORKDIR /src // 디렉토리 변경
// <src>를 <destination>에 COPY 함 (1번만 진행)
COPY ["src/ApiGateways/Aggregators/Web.Shopping.HttpAggregator/Web.Shopping.HttpAggregator.csproj", "src/ApiGateways/Aggregators/Web.Shopping.HttpAggregator/"]
COPY ["src/BuildingBlocks/EventBus/EventBus/EventBus.csproj", "src/BuildingBlocks/EventBus/EventBus/"]
COPY ["src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj", "src/BuildingBlocks/EventBus/IntegrationEventLogEF/"]
COPY ["src/BuildingBlocks/WebHost/WebHost.Customization/WebHost.Customization.csproj", "src/BuildingBlocks/WebHost/WebHost.Customization/"]
COPY ["src/Services/Basket/Basket.API/Basket.API.csproj", "src/Services/Basket/Basket.API/"]
COPY ["src/Services/Catalog/Catalog.API/Catalog.API.csproj", "src/Services/Catalog/Catalog.API/"]
COPY ["src/Services/Identity/Identity.API/Identity.API.csproj", "src/Services/Identity/Identity.API/"]
COPY ["src/Services/Ordering/Ordering.API/Ordering.API.csproj", "src/Services/Ordering/Ordering.API/"]
COPY ["src/Services/Payment/Payment.API/Payment.API.csproj", "src/Services/Payment/Payment.API/"]
COPY ["src/Web/WebSPA/WebSPA.csproj", "src/Web/WebSPA/"]
COPY ["src/Web/WebStatus/WebStatus.csproj", "src/Web/WebStatus/"]
COPY ["docker-compose.dcproj", "./"]
COPY ["NuGet.config", "./"]
COPY ["eShopOnDapr.sln", "./"]
RUN dotnet restore "eShopOnDapr.sln" // 이 명령어를 실행함 (eShopOnDapr.sln에 있는 종속성 및 모든 도구 복원)
COPY . . // 현재까지 진행된 모든 자료를 현재 디렉토리에 복사
WORKDIR "/src/src/Services/Basket/Basket.API" // 작업경로 변경
FROM build AS publish // 위에 정의한 build를 publish로 재정의
RUN dotnet publish --no-restore "Basket.API.csproj" -c Release -o /app/publish // 뒤의 명령어를 실행함 (복원을 실행하지 않고, Basket.API.csproj 를 Release 구성으로 /app/publish 에 출력)
FROM base AS final // 위에서 정의한 base image를 final로 재정의
WORKDIR /app // 작업경로 변경
COPY --from=publish /app/publish . // publish로 부터 /app/publish 의 내용을 현재 경로에 복사
ENTRYPOINT ["dotnet", "Basket.API.dll"] // dotnet Basket.API.dll 실행
// src/Web/WebSPA/Dockerfile
ARG NODE_IMAGE=15.12.0-alpine3.12 // Node_IMAGE란 dockerfile 변수
ARG NET_IMAGE=5.0-buster-slim // NET_IMAGE란 dockerfile 변수
FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base // 해당 이미지를 불러오고 base라고 명명
WORKDIR /app // 디렉토리 /app으로 변경
EXPOSE 80 // 80 port를 사용함을 명시
RUN apt-get update -yq \
&& apt-get install curl gnupg -yq \
&& curl -sL https://deb.nodesource.com/setup_10.x | bash \
&& apt-get install nodejs -yq // node js를 설치함
FROM node:${NODE_IMAGE} as node-build // node base image를 불러옴
WORKDIR /web // 디렉토리 변경
COPY src/Web/WebSPA/package.json .
COPY src/Web/WebSPA/package-lock.json .
COPY src/Web/WebSPA . // 각각의 파일들을 현재의 위치에 복사
RUN npm i npm@6.14.11 -g && npm update && npm install && npm run build:prod // npm을 글로벌로 설치하고 npm 사용된 library 들을 설치하고 build 함
FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build // base image를 불러오고 이름을 build라고 함
RUN apt-get update -yq \
&& apt-get install curl gnupg -yq \
&& curl -sL https://deb.nodesource.com/setup_10.x | bash \
&& apt-get install nodejs -yq // node js를 설치한다.
WORKDIR /src // 디렉토리 변경
COPY ["src/ApiGateways/Aggregators/Web.Shopping.HttpAggregator/Web.Shopping.HttpAggregator.csproj", "src/ApiGateways/Aggregators/Web.Shopping.HttpAggregator/"]
COPY ["src/BuildingBlocks/EventBus/EventBus/EventBus.csproj", "src/BuildingBlocks/EventBus/EventBus/"]
COPY ["src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj", "src/BuildingBlocks/EventBus/IntegrationEventLogEF/"]
COPY ["src/BuildingBlocks/WebHost/WebHost.Customization/WebHost.Customization.csproj", "src/BuildingBlocks/WebHost/WebHost.Customization/"]
COPY ["src/Services/Basket/Basket.API/Basket.API.csproj", "src/Services/Basket/Basket.API/"]
COPY ["src/Services/Catalog/Catalog.API/Catalog.API.csproj", "src/Services/Catalog/Catalog.API/"]
COPY ["src/Services/Identity/Identity.API/Identity.API.csproj", "src/Services/Identity/Identity.API/"]
COPY ["src/Services/Ordering/Ordering.API/Ordering.API.csproj", "src/Services/Ordering/Ordering.API/"]
COPY ["src/Services/Payment/Payment.API/Payment.API.csproj", "src/Services/Payment/Payment.API/"]
COPY ["src/Web/WebSPA/WebSPA.csproj", "src/Web/WebSPA/"]
COPY ["src/Web/WebStatus/WebStatus.csproj", "src/Web/WebStatus/"]
COPY ["docker-compose.dcproj", "./"]
COPY ["NuGet.config", "./"]
COPY ["eShopOnDapr.sln", "./"] // 해당 디렉토리에 앞의 내용들을 복사
RUN dotnet restore "eShopOnDapr.sln" // 명령어 실행 (eShopOnDapr.sln에 있는 종속성 및 모든 도구 복원)
COPY . . // 모든 내용을 현재 디렉토리에 복사
COPY --from=node-build /web/wwwroot /src/src/Web/WebSPA/wwwroot/ // 위 node-build image layer로 부터 /web/wwwroot 를 /src/src/Web/WebSPA/wwwroot/로 복사
WORKDIR /src/src/Web/WebSPA // 디렉토리 변경
RUN dotnet publish --no-restore -c Release -o /app // 뒤의 명령어를 실행함 (복원을 실행하지 않고, Basket.API.csproj 를 Release 구성으로 /app 에 출력)
FROM build AS publish // build image layer의 이름을 publish로 변경
FROM base AS final // base image layer의 이름을 final로 변경
WORKDIR /app // 디렉토리 변경
COPY --from=publish /app . // publish image layer로 부터 /app 의 내용물을 현재 위치에 복사
ENTRYPOINT ["dotnet", "WebSPA.dll"] // dotnet WebSPA.dll 실행
Author And Source
이 문제에 관하여(Day2 Dockerfile), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@miiunii/Day2-Dockerfile저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)