[docker] dockerfile

bunny.log·2023년 6월 30일
0

도커파일(Dockerfile)이란 ?

도커 이미지를 만들기 위한 설정 파일이며, 컨테이너가 어떻게 행동해야 하는지에 대해 설정 들을 정의해 주는 곳 입니다.

<도커 파일 만드는 순서>

  1. 베이스 이미지를 명시해준다.
  2. 추가적으로 필요한 파일을 다운 받기 위한 몇가지 명령어를 명시해 준다. (파일 스냅샷에 해당)
  3. 컨테이너 시작시 실행 될 명령어를 명시해준다. (시작시 실행 될 명령어에 해당)

이미지 구성

이미지는 아래와 같이 구성되어 있으며 레이어 중 가장 근본이 되는 이미지가 Base 이미지 이다. 이미지 안에 어떠한 추가적인 요소를 넣을 경우 레이어가 추가 되도록 구성 되어 있다.

# 베이스 이미지를 명시해준다.
FROM baseImage

# 추가적으로 필요한 파일들을 다운로드 받는다.
RUN 다운로드할 command

# 컨테이너 시작시 실행 될 명령어를 명시해준다.
CMD [ “excitable”]

#FROM RUN CMD 등은 [도커 서버]에게 무엇을 하라고 알려주는 것입니다.


FROM
이미지 생성시 기반이 되는 이미지 레이어입니다.
<이미지 이름>:<태그> 형식으로 작성하며 태그를 안붙이면 자동적으로 가장 최신것으로 다운 받습니다.

RUN
도커이미지가 생성되기 전에 수행할 쉘 명령어

CMD
컨테이너가 시작되었을 때 실행할 실행 파일 또는 쉘 스크립트입니다.
해당 명령어는 DockerFile내에서 1회만 사용 가능 합니다.

#마지막으로 시작시 실행 할 명령어를 명시해줬었던게 Dockerfile입니다.
#예로 CMD ["node", "server.js"]

도커 파일에 입력된 것들이 도커 클라이언트에 전달되어서 도커 서버가 인식하게 하여야 합니다. 그렇게 하기 위해서는 docker build ./ 또는 docker build . 를 사용하며

해당 디렉토리 내에서 dockerfile이라는 파일을 찾아서 도커 클라이언트에 전달 시켜 줍니다.

(Docker build 뒤에 ./ 와 . 는 둘다 현재 디렉토리를 가르킵니다.)

#npm이 들어있는 베이스 이미지를 명시해준다.
FROM node:10

#이미지안에서 어플리케이션 소스코드를 갖고 있을 디렉토리를 생성
WORKDIR /usr/src/app

#도커컨테이너 현재 디렉토리 ./ 안에  package*.json을 복사 해준다.
COPY package*.json ./


RUN npm Install

##로컬 디렉터리 파일 전체 복사
COPY ./ ./

EXPOSE 8080

#노드 웹 서버를 작동시키려면 node + [엔트리 파일 이름]을 입력해야 한다.
CMD [“node”, “server.js”]

번외) npm install 원리

dockerfile이 들어있는 경로에서 아래와 같이 명령어를 입력하여 빌드를 해줍니다.

베이스 이미지에서 다른 종속성이나 새로운 커맨드를 추가 할때는 임시 컨테이너를 만든 후 그 컨테이너를 토대로 새로운 이미지가 만들어지며 이전 임시 컨테이너는 지워 집니다.

이미지로 임시 컨테이너를 만들고 임시컨테이너에 새로운 명령어나 새로운 파일 스냅샷을 추가하며 변경된 임시컨테이너를 토대로(dockerfile) 새로운 이미지가 생성되는 과정입니다.

도커 컨테이너 빌드하고 실행

Docker build -t dockerId/hello:latest .

# -t 나의 도커 아이디 / 저장소/프로젝트 이름 : 버전 

Docker run -it dockerId/hello

#Docker build -t 도커허브아이디/프로젝트이름 ./(도커파일이 있는 현재 로컬 경로)
명령어를 해주면 도커이미지가 생성된다.

#Docker run -p 49160:8080 도커허브아이디/프로젝트이름:버전 
#도커 컨테이너 실행 hocalhost:8080으로 접속하면 실행된 컨테이너를 확인 할 수 있다.

#-d
detached 모드로서 앱을 백그라운드에서 실행 시킨다. 그래서 앱에서 나오는 output을 표출하지 않는다.

dockerfile로 만들어지는 컨테이너 순서

왜 따로 working 디렉토리가 있어야 할까?

WORKDIR /usr/src/app

이미지안에서 어플리케이션 소스코드를 갖고 있을 디렉토리를 생성하는 것이다.
그리고 이 디렉토리가 어플리케이션에 working 디렉토리가 된다.

근데 왜 따로 working 디렉토리가 따로 있어야 할까?

  1. workdir을 지정하지 않고 그냥 COPY를 하면 베이스 이미지에 있던 파일들과 COPY명령어로 추가되는 어플리케이션 파일들의 이름이 중복되어 원래 있던 폴더나 파일이 덮어씌어져 버린다.

  2. 그리고 모든 파일이 한 디렉토리에 있으면 파일 관리가 어렵다.

그리하여 모든 어플리케이션을 위한 소스들은 WORK 디렉토리에 따로 만들어 보관하는 것을 권장한다.

WORKDIR을 생성 후 sh 쉘로 생성한 컨테이너에 접속하여 보면 ROOT디렉터리에 node베이스 이미지의 파일들이 보이지 않는데

WORKDIR디렉터리를 설정해주면 컨테이너 접근시 ROOT디렉터리부터 접근하지 않고 WORKDIR 디렉터리부터 접근한다.

WORKDIR에서 cd / 명령어로 루트에 올라가보면 루트 디렉터리 파일들을 확인 할 수 있다.

어플리케이션 소스 변경으로 다시 빌드하는 것에 대한 문제점

[문제점]
어플리케이션의 소스에서 변경된 내용이 있을 경우 기동중인 도커 컨테이너에 반영하기 위해서는
1. 현재 기동중인 도커컨테이너를 중지 시키고
2. 어플리케이션을 다시 도커 컨테이너로 빌드 한 후
3. 다시 도커 컨테이너를 실행 시켜주는 작업을 해야 한다.

어플리케이션 소스 변경으로 인해 재빌드시 효율적으로 하는 법

어플리케이션 빌드시 한번 빌드된 파일들은 캐싱이 되며 재빌드시 변경된 부분이 없을 경우에는 다시 빌드하지 않는다.

그런부분에서 소스코드에 변경이 발생할 경우에는 package.json 파일의 의존성 부분등에 변경 사항이 없을 경우에는 package.json 파일의 종성성들을 NPM INSTALL을 다시 해주는 것은 매우 비효율적이다.

그래서 package.json을 먼저 COPY하여 NPM INSTALL을 해주도록 변경해준다.

빌드 명령어를 치면 아래와 같이 내용을 확인 할 수 있다.

도커파일을 분리해줄 경우

Docker build -f Dockerfile.dev ./

이미지를 빌드 할때 쓰일 도커 파일을 임의로 지정해 준다.

리액트 dockerfile 설치 시

현재 로컬 머신에 node_modules 폴더가 있습니다.
이곳에는 리액트 앱을 실행할 때 필요한 모듈들이 들어있지만
이미지를 빌드 할 때 이미 npm install로 모든 모듈들을 도커 이미지에 다운 받기 때문에
굳이 로컬 머신에 node_modules을 필요로 하지 않는다.
그러기에 node_modules 폴더를 아예 지워주고 빌드하는 것을 추천한다.(폴더에서 삭제)

volum을 -v를 이용하여 리액트 앱에서 소스코드 수정시 바로 반영하기

위 명령어는 너무 길어서 docker compose를 이용하여 관리 하도록 한다.

context 도커 이미지를 구성하기 위한 파일과 폴더들이 있는 위치

로컬 루트에 docker-compose.yml 파일의 내용을 위와 같이 작성 한후 도커 컴포즈 실행 명령어를 쳐주면 어플리케이션 소스코드를 수정시 바로 도커에 반영 되는 것을 확인 할 수 있다.

docker-compose up --build

상단에 builder 스테이지를 명시하고 있다

FORM node:alpine as builder 

아래에서 COPY --form=builder 부분은 위의 builder 스테이지 부분을 복사함을 명시하고 있다.

참고
https://www.inflearn.com/course/lecture?courseSlug=%EB%94%B0%EB%9D%BC%ED%95%98%EB%A9%B0-%EB%B0%B0%EC%9A%B0%EB%8A%94-%EB%8F%84%EC%BB%A4-ci&unitId=52114&tab=curriculum

profile
https://github.com/nam-yeun-hwa

0개의 댓글