SoShin_
소신
SoShin_
전체 방문자
오늘
어제
  • 분류 전체보기
    • Study
      • HTML | CSS
      • JavaScript
      • Django
      • Python
      • Flask
      • Git
      • Project
      • 이것저것
      • 코딩테스트
      • NestJS
    • Review
      • Book
      • Movie & Drama

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Django allauth
  • Django
  • 영화리뷰
  • 유저기능
  • JavaScript
  • 영화추천
  • allauth
  • MongoDB
  • 위도경도
  • openpyxl
  • Django 유효성 검증
  • 장고 유저기능
  • flask orm
  • Python
  • 자바스크립트
  • FLASK
  • 문제풀이
  • js
  • orm
  • 코딩테스트
  • 파이썬
  • KakaoAPI
  • 장고 allauth
  • SQLAlchemy
  • 플라스크
  • 장고
  • node.js
  • db
  • 장고 제네릭뷰
  • SQLite

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
SoShin_

소신

[Docker] Docker , Dockerfile Tutorial
Study/이것저것

[Docker] Docker , Dockerfile Tutorial

2022. 4. 14. 15:04
반응형

🎇Docker를 이용하여 express를 background 에서 실행해보기

목표 : 기존 터미널에서 실행하던 express 서버를 docker image를 만들어 컨테이너를 생성 한 후 background에서 실행시키기!

1. 🚲 Docker image 만들기

docker image를 만들기 위한 Dockerfile 을 프로젝트의 root 폴더에 생성해줍니다.
Dockerfile 포멧
하나의 Dockerfile은 기본적으로 다음과 같은 구조를 가진 여러 개의 명령문으로 구성되어 있습니다.

#주석(Comment)
명령어(INSTRUCTION) 인자(arguments)

각 명령문은 명령어로 시작하고 여러 개의 인자가 따라올 수 있으며, 해당 명령문에 대한 주석도 달 수 있습니다.
인자와 구분이 쉽도록 명령어는 모두 영문 대문자로 써주는 것이 관례입니다.

FROM node:16
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --silent
COPY . .
ARG port
EXPOSE ${port}
ENTRYPOINT ["node"]
CMD ["index.js" ]

생성한 Dockerfile 안에 위의 내용을 작성해줍니다.

✔ 이때 파일 이름을 Dockerfile이 아니라 다른 이름으로 해도 괜찮지만, 그렇게 할 시 설정할 때 추가적으로 바꾼 이름으로 설정을 추가해줘야 하므로 편하게 default 이름인 Dockerfile로 생성하였습니다.

이때 위의 작성한 내용들이 의미하는 바를 하나씩 정리해보겠습니다.


FROM 명령어

FROM : 어떤 이미지를 사용해서 빌드할 것인지를 정의하는 것 [ 코드를 작성할 때 node의 최신 버전인 16을 사용했기 때문에 node:16으로 설정해주었습니다.

FROM 명령문

FROM <이미지>
FROM <이미지>:<태그>

하나의 Docker Image는 base image부터 시작해서 기존 이미지위에 새로운 이미지를 중첩해서 여러 단계의 이미지 층(layer)을 쌓아가며 만들어집니다.
FROM 명령문은 이 base image를 지정해주기 위해서 사용되는데, 보통 Dockerfile 내에서 최상단에 위치합니다. base image는 일반적으로 Docker Hub와 같은 Docker repository에 올려놓은 잘 알려진 공개 이미지인 경우가 많습니다.

예시 : NodeJS 16를 base 이미지로 사용

FROM node:16

WORKDIR 명령문

  • WORKDIR : 이미지 안에 애플리케이션 코드를 넣기 위한 디렉터리를 생성하는 명령어로 이 디렉터리가 애플리케이션의 작업 디렉터리가 됩니다.WORKDIR 명령문
WORKDIR <이동할 경로>

WORKDIR 명령문은 shell의 cd 명령문처럼 컨테이너 상에서 작업 디텍토리로 전환을 위해서 사용됩니다.
WORKDIR 명령문으로 작업 디렉터리를 전환하면 그 이후에 등장하는 모든 RUN, CMD, ENTRYPOINT, COPY, ADD 명령문은 해당 디렉터리를 기준으로 실행됩니다.

/usr/app으로 작업 디렉터리 전환

WORKDIR /usr/app

COPY, ADD 명령문

  • COPY or ADD : COPY 명령문은 호스트 컴퓨터에 있는 디렉터리나 파일을 Docker image의 파일 시스템으로 복사하기 위해서 사용됩니다.
    절대 경로와 상대 경로를 모두 지원하며, 상대 경로를 사용할 때는 이 전에 등장하는 WORKDIR 명령문으로 작업 디렉터리를 어디로 전환을 해놨는지 고려해야 합니다.
# COPY 명령문
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

ADD 명령문은 좀 더 파워풀한 COPY 명령문이라고 생각할 수 있습니다.
ADD 명령문은 일반 파일 뿐만 아니라 압축 파일이나 네트워크 상의 파일도 사용할 수 있습니다.
이렇게 특수한 파일을 다루는 게 아니라면 COPY 명령문을 사용하는 것이 권장됩니다.

package.json 파일만 복사

COPY package.json ./

이미지를 빌드한 디렉터리의 모든 파일을 컨테이너의 app/ directory로 복사

WORKDIR app/ COPY . .

package.json과 package-lock.json을 모두 복사하기 위해 와일드카드 사용

COPY package*.json ./

RUN 명령문

  • RUN
    RUN 명령문은 마치 shell에서 커맨드를 실행하는 것 처럼 이미지 빌드 과정에서 필요한 커맨드를 실행하기 위해서 사용됩니다. shell을 통해 거의 못하는 작업이 없는 것 처럼 RUN 명령문으로 할 수 있는 작업은 무궁무진하지만 보통 이미지 안에 특정 소트트웨어를 설치하기 위해서 많이 사용됩니다.
    • npm 패키지 설치
  • RUN ["<커맨드>", "<파라미터1>", "<파라미터2>"] RUN <전체 커맨드>
RUN npm install --silent
  • curl 도구 설치
  • RUN apk add curl
  • pip 패키지 설치
  • RUN pip install -r requirements.txt

EXPOSE 명령문

  • EXPOSE
    EXPOSE 명령문은 네트워크 상에서 컨테이너로 들어오는 트래픽(traffic)을
    리스닝(listening)하는 포트와 프로토콜를 지정하기 위해서 사용됩니다. 프로토콜은 TCP와 UDP 중 선택할 수 있는데 지정하지 않으면 TCP가 기본값으로 사용됩니다.
EXPOSE <포트>
EXPOSE <포트>/<프로토콜>

❗ 여기서 주의할 점은 EXPOSE 명령문으로 지정된 포트는
해당 컨테이너의 내부에서만 유효하며, 호스트(host) 컴퓨터에서는 이 포트를 바로 접근을 할 수 있는 것은 아니라는 겁니다.
호스트 컴퓨터로부터 해당 포트로의 접근을 허용하려면, docker run 커맨드를
-p 옵션을 통해 호스트 컴퓨터의 특정 포트를 포워딩(forwarding)시켜줘야 합니다.


ENTRYPOINT 명령문

  • ENTRYPOINT
    : ENTRYPOINT 명령문은 이미지를 컨테이너로 띄울 때 항상 실행되야 하는 커맨드를 지정할 때 사용합니다.
    ENTRYPOINT 명령문은 Docker image를 마치 하나의 실행 파일처럼 사용할 때 유용합니다.
    왜냐하면 컨테이너가 뜰 때 ENTRYPOINT 명령문으로 지정된 커맨드가 실행되고, 이 커맨드로 실행된 프로세스가 죽을 때, 컨테이너로 따라서 종료되기 때문입니다.
ENTRYPOINT ["<커맨드>", "<파라미터1>", "<파라미터2>"]
ENTRYPOINT <전체 커맨드>
  • npm start 스크립트 실행
  • ENTRYPOINT ["npm", "start"]
  • Django 서버 실행
  • ENTRYPOINT ["python", "manage.py", "runserver"]

CMD 명령문

  • CMD
    : CMD 명령문은 해당 이미지를 컨테이너로 띄울 때 디폴트로 실행할 커맨드나, ENTRYPOINT 명령문으로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용합니다.
    CMD 명령문은 많은 경우, ENTRYPOINT 명령문과 함께 사용하게 되는데, ENTRYPOINT 명령문으로는 커맨드를 지정하고, CMD 명령문으로 디폴트 파리미터를 지정해주면 매우 유연하게 이미지를 실행할 수 있게 됩니다.
CMD ["<커맨드>","<파라미터1>","<파라미터2>"]
CMD ["<파라미터1>","<파라미터2>"]
CMD <전체 커맨드>

예를 들어, node 커맨드로 디폴트로는 index.js를 실행하고, docker run커맨드에 인자가 있는 경우, 해당 인자를 실행하고 싶은 경우, 다음과 같이 Dockerfile을 작성합니다.

ENTRYPOINT ["node"]
CMD ["index.js"]

그러면 다음과 같이 docker run 커맨드의 인자 유무에 따라 node 커맨드로 다른 파일이 실행되게 할 수 있습니다.

  • node index.js 실행
  • $ docker run test
  • node main.js 실행
  • $ docker run test main.js

ENV 명령문

ENV

  • ENV 명령문은 환경 변수를 설정하기 위해서 사용합니다.
    ENV 명령문으로 설정된 환경 변수는 이미지 빌드 시에도 사용됨은 물론이고, 해당 컨테이너에서 돌아가는 애플리케이션도 접근할 수 있습니다.
  • ENV <키> <값> ENV <키>=<값>
  • NODE_ENV 환경 변수를 production으로 설정
  • ENV NODE_ENV production

ARG 명령문

  • ARG: ARG 명령문은 docker build 커맨드로 이미지를 빌드 시, --build-arg 옵션을 통해 넘길 수 있는 인자를 정의하기 위해 사용합니다.
  • ARG <이름> ARG <이름>=<기본 값>

예를 들어, Dockerfile에 다음과 같이 ARG 명령문으로 port를 인자로 선언해주면,

ARG port

다음과 같이 docker build 커맨드에 --build-arg 옵션에 port 값을 넘길 수가 있습니다.

$ docker build --build-arg port=8080 .

설정된 인자 값은 다음과 같이 ${인자명} 형태로 읽어서 사용할 수 있습니다.

CMD start.sh -h 127.0.0.1 -p ${port}

2. 🚓 .dockerignore 파일 만들기

Docker image를 빌드할 때 제외 시키고 싶은 파일이 있다면, .dockerignore 파일에 추가해주면 됩니다.

.dockerignore

.git
.md

위처럼 설정을 해주면 Docker는 프로젝트 최상위 디렉터리에 위치하고 있는 markdown 파일들을 무사하게 되므로, RUN과 CMD, COPY와 같은 명령문이 해당 파일을 사용할 수 없게 됩니다.

실사용 : Docker 이미지에 로컬 모듈과 디버깅 로그를 복사하는 것을 막아서 이미지 내에서 설치한 모듈을 덮어쓰지 않게 하기 위해 .dockerignore파일을 만들어 줍니다.

node_modules
npm-debug.log

만든 후 위의 내용을 추가해줍니다.


3. 🛵 Docker 실행해보기

위 처럼 docker 명령어를 통해 실행해 줄 시 아래처럼 로그에 작성했던 명령문들이 실행되며 진행되는 것을 볼 수 있다!


반응형

'Study > 이것저것' 카테고리의 다른 글

[Error] Node 에서 환경 변수를 읽어오지 못하는 오류  (0) 2022.03.16
[ Postman ] 포스트맨 사용해보기!  (0) 2021.12.30
    'Study/이것저것' 카테고리의 다른 글
    • [Error] Node 에서 환경 변수를 읽어오지 못하는 오류
    • [ Postman ] 포스트맨 사용해보기!
    SoShin_
    SoShin_
    직접 쓰는 개발 블로그

    티스토리툴바