무브라더

Docker 파일 분석 본문

Programming/Docker & k8s

Docker 파일 분석

동스다
반응형
SMALL

회사에서 도커로 이미지를 빌드하고 그 이미지를 도커허브에 올린 후 누구나(권한을 부여할시) 도커허브에 올린 이미지를 통해

k8s 에서 실행시킬 수 있도록 작업하기를 원해서 관련 내용 공부를 하며 작업을 진행했었다. 

 

처음엔 막막하고 어려웠는데 공부도 하고 찾아가면서 작업을 진행하다보니 예상치 못하게 재밌었고 나중에 많은 도움이 될 거 같아

공부 했던 내용을 다시 상기하고 기록하고 싶어서 포스팅을 하려고 한다.

 

Docker 파일

# build stage
FROM node:14-alpine as build-stage
# ARG ENV
WORKDIR /app
COPY package*.json ./
# COPY yarn.lock ./
RUN yarn install
COPY . .
RUN yarn run build-dev

# production stage
FROM nginx:stable-alpine as production-stage

RUN apk add --no-cache tzdata && apk add vim

ENV LANG ko_KR.UTF-8
ENV LANGUAGE ko_KR:en
ENV LC_ALL ko_KR.UTF-8
# Set Timezone
ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

## COPY nginx config
COPY custom-nginx.conf /etc/nginx/
RUN cat /etc/nginx/custom-nginx.conf > /etc/nginx/conf.d/default.conf

## log
RUN mkdir /logs
RUN chmod 777 /logs

COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

 

FROM node:14-alpine as build-stage
  • FROM : 베이스이미지 , 간단하게 말해 OS라고 생각하면됨
  • Alpine은 매우 작은 Linux 배포판인 Alpine Linux 를 기반으로 하는 기본 이미지
  • node:14-alpine 의 의미는 노드 12에 설치된 알파인 기반 이미지를 의미
  • node:alpine 사용 시 최신 버전의 Alpine을 사용할 수 있다.
  • build-stage는 이미지 빌드 단계에서 생성된 이미지의 이름이며, 이 이미지는 다른 이미지 빌드 단계에서 사용
  • as키워드를 사용하여 현재 단계에 대한 이름을 정의하고 다음 단계에서 해당 이름을 참조할 수 있다

FROM node:14-alpine as build-stage 구문은 node:14-alpine이라는 베이스 이미지에서 새 이미지를 빌드하기 시작하는 것을 의미. 이 단계에서 생성된 이미지는 build-stage라는 이름으로 지정됨. 이후에 다른 Dockerfile 단계에서 build-stage 이미지를 참조하여 해당 이미지를 기반으로 새로운 이미지를 생성할 수 있음.

 

WORKDIR /app
  • WORKDIR지시자는 도커 파일에서 리눅스 명령어의 cd와 유사하게 뒤에 오는 모든 지시자(RUN, CMD, COPY , ADD 등)에 대한 작업 디렉토리를 설정한다.
  • WORKDIR /app는 Dockerfile에서 사용되는 명령어로, 컨테이너 내부에서 작업 디렉토리를 설정하는 역할을 한다.
  • 원래 최상위 파일이나 폴더에 있던 이름과 COPY해오는 파일이나 폴더의 이름이 같은게 있다면, 기존에 파일을 덮어쓰게되어 문제가 생길 수 있으며, 최상위 폴더에 모두 있을 경우 가독성 또한 좋지 않다.
  • /app 은 컨테이너 내부에서 작업할 디렉토리를 의미. 즉, WORKDIR /app 명령어를 사용하면 이후의 명령어들은 모두 /app디렉토리 내에서 실행
  • 예를 들어, COPY명령어로 로컬 파일을 컨테이너 내부의 /app디렉토리로 복사하려면, WORKDIR /app 로 작업 디렉토리를 /app으로 설정한 후, COPY 명령어에서 소스 경로를 로컬 파일 경로에서 /app 으로 변경해야 한다.

WORKDIR /app은 Dockerfile에서 작업 디렉토리를 설정하는 중요한 명령어 중 하나이며, 이후의 명령어들이 /app 디렉토리 내에서 실행되도록 한다.

 

COPY package*.json ./
  • Docker클라이언트의 현재 디렉토리에서 파일을 추가한다.
  • WORKDIR를 별도로 지정했다면 로컬에 있는 파일들이 도커 컨테이너로 복사될때 WORKDIR 에 정의한 디렉토리로 복사된다.
  • 로컬 파일 시스템에 있는 package.json 파일을 Docker 이미지 내부로 복사하는 역할을 한다
  • package*.json은 현재 디렉토리에서 package.json으로 시작하는 모든 파일을 매칭하며, ./ 은 현재 Dockerfile이 있는 디렉토리를 나타낸다.

COPY package*.json ./명령어는 Dockerfile이 있는 디렉토리에서 package.json으로 시작하는 파일을 모두 Docker 이미지 내부의 현재 작업 디렉토리에 복사한다.

이 명령어를 사용하면, Node.js 애플리케이션을 Docker 이미지로 패키징할 때 package.json 파일과 yarn.lock파일 등의 의존성 파일을 Docker 이미지 내부로 복사하여 yarn install 명령어에서 이를 활용할 수 있도록 한다.

따라서, COPY package*.json ./은 Node.js 애플리케이션을 Docker 이미지로 패키징할 때 필요한 명령어 중 하나이며, package.json과 같은 의존성 파일을 Docker 이미지 내부로 복사하여 이후의 명령어에서 활용할 수 있도록 한다.

 

✔ COPY . . 의 의미 ✔

  • Dockerfile에서 사용되는 명령어로, 현재 Dockerfile이 있는 디렉토리의 모든 파일을 Docker 이미지 내부의 현재 작업 디렉토리로 복사하는 역할을 한다.
  • 첫 번째 .은 현재 로컬 파일 시스템에서 Dockerfile이 있는 디렉토리를 나타내고, 두 번째 . 은 Docker 이미지 내부의 현재 작업 디렉토리를 나타낸다.
  • 이 명령어를 사용하면, Node.js 애플리케이션을 Docker 이미지로 패키징할 때 필요한 파일들을 Docker 이미지 내부로 복사하여 애플리케이션 실행에 필요한 파일들을 모두 포함시킬 수 있다.
  • 따라서, COPY . .은 Node.js 애플리케이션을 Docker 이미지로 패키징할 때 필요한 명령어 중 하나이며, 현재 Dockerfile이 있는 디렉토리의 모든 파일을 Docker 이미지 내부로 복사하여 이후의 명령어에서 활용할 수 있도록 한다.

RUN yarn install
  • 도커 이미지가 생성되기 전에 수행할 쉘 명령어이다.
  • Dockerfile에서 사용되는 명령어로, 컨테이너 내부에서 Node.js 애플리케이션을 실행하기 위해 필요한 의존성 패키지를 설치하는 역할을 한다.
  • yarn은 Node.js 패키지 매니저 중 하나로, yarn install 명령어는 package.json 파일에 명시된 의존성 패키지를 설치하고, 이를 node_modules ****디렉토리에 저장한다.

RUN yarn install명령어를 Dockerfile에서 사용하면, Docker 이미지를 빌드할 때 의존성 패키지를 미리 설치하여 컨테이너를 실행할 때 불필요한 다운로드와 설치 시간을 줄일 수 있다.

따라서, RUN yarn install은 Node.js 애플리케이션을 Docker 이미지로 패키징할 때 필요한 명령어 중 하나이며, 의존성 패키지를 미리 설치하여 컨테이너 내부에서 빠르고 안정적인 애플리케이션 실행을 가능하게 한다.

 

FROM nginx:stable-alpine as production-stage
  • Dockerfile 명령어 중 하나로, 프로덕션 환경에서 사용될 Docker 컨테이너의 기본 이미지를 지정
  • 기본 이미지는 "nginx:stable-alpine"이며, 경량화된 Alpine Linux 배포판 기반의 Nginx 웹 서버의 안정적인 버전
  • as production-stage 부분은 명명된 빌드 스테이지를 정의하는 데 사용되며, Docker의 멀티 스테이지 빌드를 가능하게 하며 이것은 빌드 환경과 최종 프로덕션 환경을 분리하여 더 작고 효율적인 이미지를 만드는데 유용하다.

즉 안정적인 Alpine 기반 Nginx 웹 서버를 기반 이미지로 사용하는 Docker 컨테이너를 지정하며, 동시에 빌드 스테이지의 이름을 "production-stage"로 설정한다.

 

** Nginx 웹 서버란?

  • Nginx는 오픈 소스로 개발된 고성능 웹 서버 소프트웨어
  • 기본적으로 정적 콘텐츠를 처리하며, 동적 콘텐츠를 처리하기 위해 다양한 백엔드 서버와 연동 가능
  • 다양한 기능과 모듈을 제공하며, 프록시, 부하 분산, SSL 인증서 지원, URL 리다이렉션, 보안 기능 등 다양한 웹 서버 기능을 제공
  • 가벼우면서도 처리 속도가 빠르고 안정성이 높아 많은 사용자들이 선호하는 웹 서버 중 하나
  • 또한 Reverse Proxy 서버로 사용될 수도 있음, Reverse Proxy는 클라이언트의 요청을 받아서 백엔드 서버로 전달하는 역할을 수행, 이는 보안성을 높이거나, 부하 분산을 위한 클러스터링 등의 목적으로 사용
  • Nginx는 대규모 웹 서비스에서 많이 사용되며, Facebook, Netflix, Dropbox, GitHub 등 많은 인터넷 기업들이 사용하고 있음
RUN apk add --no-cache tzdata && apk add vim
  • Docker 이미지 내부에서 실행되며, Alpine 리눅스 배포판에서 "apk" 패키지 매니저를 사용하여 "tzdata" 패키지와 "vim" 패키지를 설치
  • tzdata 패키지는 타임존 데이터를 포함하며, 이를 설치하여 시스템의 시간대를 설정 할 수 있음
  • vim 패키지는 Vim 텍스트 에디터를 설치
  • --no-cache 옵션은 apk 패키지 매니저가 인덱스를 캐시하지 않도록 함, 이 옵션을 사용하면 이미지 크기를 줄일 수 있음

이 명령어는 Dockerfile에서 이미지 빌드 과정에서 사용되며, 이미지를 생성하는 데 필요한 의존성 패키지를 설치하는 역할을 한다. 따라서, 이 명령어를 사용하여 필요한 패키지를 미리 설치해 두면, 나중에 이미지를 실행할 때 패키지를 추가로 설치할 필요가 없어지므로, 이미지 실행 시간을 단축시킬 수 있다.

 

** —no-cache ?

  • apk 패키지 매니저에서 사용되는 옵션 중 하나
  • 이 옵션을 사용하면 apk 패키지 매니저가 패키지 인덱스를 캐시하지 않고, 항상 최신 버전의 패키지 인덱스를 다운로드하여 사용

( 패키지 인덱스는 패키지 매니저가 사용하는 메타데이터로, 설치하려는 패키지의 정보와 패키지가 어디에 위치하는지 등을 담고있다. 패키지 인덱스를 캐시한다는 것은 패키지 매니저가 인덱스를 한번 다운로드를 하고 캐시해 두면, 이후에 패키지를 설치할 때 매번 인덱스를 다시 다운로드하지 않아도 된다는 의미다. 대부분의 패키지 매니저는 이와 같은 방식으로 패키지 인덱스를 관리한다)

  • 그러나, 패키지 인덱스가 캐시되면 패키지 매니저가 최신 버전의 패키지를 사용하지 않을 수 있다. 따라서 --no-cache 옵션을 사용하여 항상 최신 버전의 패키지 인덱스를 사용하도록 설정할 수 있다.
  • 이 옵션을 사용하면 패키지 인덱스를 다운로드해야 하기 때문에, 패키지 설치 속도가 느려질 수 있지만, 항상 최신 버전의 패키지를 사용할 수 있기 때문에 보안상 이점이 있다. 또한, Docker 이미지 크기를 줄일 수 있어 이미지 빌드 시간을 단축시킬 수도 있다.

** Vim 텍스트에디터란

  • 터미널에서 사용하는 텍스트 에디터 중 하나
  • Vim은 다양한 기능을 제공하는데 예를 들어 검색 기능, 복사/붙여넣기 기능, 키 매핑 등이 있다.
  • 또한 다양한 플러그인을 사용하여 Vim의 기능을 확장할 수 있다.

 

ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  • $TZ 환경 변수에 저장된 값을 읽어와서 시간대를 설정한다. $TZ환경 변수는 이미지를 빌드할 때 --build-arg 플래그로 전달되는 값으로, Dockerfile 내에서 $TZ 환경 변수를 사용하면 빌드할 때 전달한 시간대 값이 설정된다.
  • 다음으로 /usr/share/zoneinfo/$TZ 파일을 /etc/localtime파일로 심볼릭 링크를 걸어서 시간대 설정을 한다. 이를 통해 호스트 컴퓨터의 시간대를 쉽게 컨테이너 내부로 가져올 수 있다.
  • 마지막으로, $TZ값을 /etc/timezone 파일에 저장한다. 이를 통해 컨테이너 내부의 시간대 설정이 영구적으로 유지되도록 한다.

ENV TZ=Asia/Seoul은 TZ라는 이름의 환경 변수를 "Asia/Seoul"로 설정하는 역할

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone은 "/usr/share/zoneinfo/Asia/Seoul" 시간대의 심볼릭 링크를 "/etc/localtime"에 생성하고, "/etc/timezone"에 "Asia/Seoul"을 기록

 

ln -snf ?

  • ln 은 link의 약어로 파일이나 디렉토리를 다른 이름으로 링크하는 명령어다.
  • -s 옵션은 symbolic link를 생성하도록 한다. 즉 링크된 파일이나 디렉토리를 가리키는 심볼릭 링크를 생성한다.
  • -n 옵션은 이미 링크된 대상이 있을 경우, 새로운 링크를 생성하지 않도록 한다.
  • -f 옵션은 강제로 링크를 생성하도록 한다.

→ 따라서 ln -snf 명령어는 강제로 이미 존재하는 심볼릭 링크를 생성하도록 하는것을 의미한다.

 

Symbolic Link

파일 시스템에서 사용되는 개념으로, 하나의 파일이나 디렉토리를 다른 경로에서도 참조할 수 있도록 해주는 링크

  • 심볼릭 링크는 원본 파일이나 디렉토리에 대한 참조를 담고 있는 작은 파일이 생성되는데 다른 경로에서도 마치 원본 파일인 것처럼 사용할 수 있음. 즉 원본 파일이나 디렉토리의 변경 사항이 심볼릭 링크에도 반영됨
  • 심볼릭 링크는 하드 링크(Hard Link)와 대조되는데 하드 링크는 원본 파일과 완전히 동일한 새로운 파일을 생성하는 것이며, 원본 파일이나 하드 링크 중 어느 하나를 삭제하더라도 나머지 파일은 남아있다. 반면 심볼릭 링크는 원본 파일에 대한 참조만을 담고 있기 때문에 원본 파일이 삭제되면 심볼릭 링크도 더 이상 유효하지 않게 된다.

 

COPY custom-nginx.conf /etc/nginx/
RUN cat /etc/nginx/custom-nginx.conf > /etc/nginx/conf.d/default.conf

이 코드는 custom-nginx.conf 파일을 Docker 이미지 내부의 /etc/nginx/ 디렉토리에 복사하고, 이후 cat명령어를 사용하여 custom-nginx.conf파일의 내용을 /etc/nginx/conf.d/default.conf 파일에 덮어쓰는 역할을 한다.

 

**** ‘cat [옵션] 파일명’ 명령어**

cat명령어는 파일의 내용을 터미널에 출력하는 역할을 하기 때문에, 특정 파일의 내용을 확인하거나 파일을 이어붙이는 등의 용도로 사용됨

ex) cat example.txt명령어는 example.txt 파일의 내용을 터미널에 출력

cat file1.txt file2.txt > combined.txt명령어는 file1.txt와 file2.txt ****파일의 내용을 이어붙여서 combined.txt ****파일에 저장

 

RUN mkdir /logs
RUN chmod 777 /logs

/logs 디렉토리를 생성하고, 이 디렉토리의 권한을 chmod 명령어를 사용하여 777 으로 변경하는 역할

  • mkdir명령어는 디렉토리를 생성하는 명령어다.
  • chmod명령어는 파일이나 디렉토리의 권한을 변경하는 명령어다.
  • chmod 777은 해당 디렉토리나 파일에 대한 모든 권한을 부여하는 것으로, 다음과 같은 의미를 갖는다.
    • 7: 해당 파일의 소유자(user)에 대한 권한을 rwx (읽기, 쓰기, 실행) 로 부여
    • 7: 해당 파일의 그룹(group)에 대한 권한을 rwx (읽기, 쓰기, 실행) 로 부여
    • 7: 다른 사용자(other)에 대한 권한을 rwx ****(읽기, 쓰기, 실행) 로 부여

/logs디렉토리를 생성하고, 이 디렉토리의 권한을 모든 사용자에게 부여하는 것으로, 이후에 이 디렉토리를 사용하는 애플리케이션이나 서비스에서 로그 파일을 쓰고 읽을 수 있도록 하는 것

 

COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

build-stage단계에서 생성한 /app/dist 디렉토리의 파일을 nginx서버의 /usr/share/nginx/html 디렉토리로 복사하고, 이후에 nginx서버를 실행하여 포트 80 으로 노출하는 역할을 한다.

  • COPY 명령어는 호스트 머신에서 Docker 이미지로 파일을 복사하는 명령어. 위의 코드에서는 build-stage 단계에서 생성한 /app/dist 디렉토리의 파일을 **nginx** 서버의 /usr/share/nginx/html 디렉토리로 복사하는 역할을 한다.
  • EXPOSE 명령어는 Docker 컨테이너가 사용할 포트를 지정하는 명령어. 위의 코드에서는 nginx 서버가 사용하는 기본 포트인 80을 노출하는 역할을 한다.
  • CMD 명령어는 컨테이너가 실행될 때 실행할 명령어를 지정하는 명령어입니다. 위의 코드에서는 nginx 서버를 실행하고, g 옵션으로 설정 파일 내에서 사용할 전역 지시문을 지정하고, daemon off;로 백그라운드에서 실행되지 않도록 설정하는 명령어를 실행합니다.

⇒ 즉, 위의 코드는 nginx서버를 실행하고, build-stage 단계에서 생성한 /app/dist 디렉토리의 파일을 nginx서버의 /usr/share/nginx/html디렉토리로 복사하여 서비스를 제공하는 역할을 한다. 이후에 docker build명령어를 사용하여 Docker 이미지를 빌드하고, docker run명령어를 사용하여 컨테이너를 실행하면 nginx서버가 실행되고, http://localhost와 같은 URL을 사용하여 웹 페이지를 확인 할 수 있다.

반응형
LIST
Comments