새소식

반응형
Programming

프론트엔드 개발자도 알면 좋은 Docker

  • -
반응형

도커 (Docker)

도커는 컨테이너 기반오픈소스 가상화 플랫폼입니다. 도커는 2013년 3월 산타클라라에서 열린 Pycon Conference에서 Solomon Hykes가 발표한 The future of Linux Containers라는 세션에서 처음 세상에 알려지게 되었고, 고(go)언어로 개발되고 있습니다.

컨테이너 기반이라고 했는데 무엇일까요?

컨테이너 (Container)

컨테이너

오늘날 컨테이너라고 하면 주로 선박 운송용 컨테이너를 지칭합니다. 선박 운송시 모든 선적물은 거대한 상자모양의 컨테이너를 통해 패키징 된 후 화물선에 선적됩니다. 컨테이너는 국제적으로 표준화, 규격화 된 크기를 가지고 있습니다. 그래서 컨테이너와 관련된 보관, 운송과 관련된 장비, 제도, 프로세스 등은 모두 국제 표준에 맞게 설계되어집니다.

 

이러한 표준화를 통해 해상 운송업자는 컨테이너 안에 어떤 물건이 담겨저 있는지 전혀 알 필요가 없고, 그저 컨테이너 단위로 선적하여 운송하고 하역하고 보관하면 됩니다. 만약 표준화가 되어 있지 않다면 제각기 다른 물건의 크기, 모양 등에 맞춰 서로 다른 운송장비, 보관방법, 프로세스 등이 필요하게 될것입니다.

도커 컨테이너

도커의 컨테이너도 이와 같은 컨셉을 가지고 있습니다. 도커는 서비스를 운용하는데 필요한 실행환경, 라이브러리, 소프트웨어, 시스템 도구, 코드 등을 컨테이너라는 표준화된 단위로 추상화합니다. 이렇게 만들어진 컨테이너는 컴퓨팅 환경에 상관없이 서비스가 실행될 수 있도록 해줍니다.

 

실제 컨테이너의 특성처럼 서비스 관리자는 도커라이징(Dockerizing)된 컨테이너가 어떤 런타임을 필요로 하는지, 어떤 라이브러리와 코드를 필요로 하는지 전혀 알 필요가 없고, 그저 컨테이너를 어딘가에서 가져와서 서비스를 운영한 컴퓨팅 환경에서 실행하기만 하면 됩니다. 실행된 서비스는 컴퓨팅 환경과 독립된 가상의 환경에서 실행되며, 일관된 결과를 보장합니다.

 

도커 이미지(Docker Image)

도커 이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로 상태값을 가지지 않고 변하지 않습니다(Immutable).

컨테이너를 생성하기 위해 필요한 설계도라고 할 수 있습니다. 컨테이너는 이미지를 실행한 상태라고 볼 수 있고, 추가되거나 변하는 값은 컨테이너에 저장됩니다. 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라고 이미지는 변하지 않고 그대로 남아 있습니다.

 

쉽게 설명하면 도커가 찍어놓은(빌드한) 사진(Image)을 인화(실행)하면 컨테이너가 나오는 것입니다. 사진은 여러번 인화 할 수 있고, 똑같은 사진이 인화 되는 것처럼 다른 서버에서 도커가 이미지를 사용해 컨테이너를 만들면 똑같은 환경을 구축 할 수 있습니다.

 

도커 이미지는 도커 파일(Docker File)로 만들 수 있습니다. 도커 파일은 도커가 어떻게 이미지를 만들지 이해하도록 적은 파일 입니다. 도커 파일에 Image를 어떻게 빌드할지 적어놓으면 도커가 그것을 읽고 이미지를 생성하게 됩니다(Dockerizing).

 

Docker로 애플리케이션 배포하기

일단 Homebrew를 사용해서 Docker를 설치 해줍니다.

--cask 옵션을 사용해서 설치를 해주면 Docker Desktop on Mac을 설치하고 docker-compose, docker-machine도 같이 설치해주어 편하게 사용할수 있게 됩니다.

참고: Docker - Mac에 Homebrew로 docker 설치

// 설치
brew install --cask docker

// 버전확인
docker --version
docker-compose --version

Dockerfile

도커파일은 컨테이너 이미지는 만드는데 사용되는 단순한 텍스트 기반 지침 스크립트입니다. 이미지를 생성하기 위한 컨테이너에 설치해야하는 패키지, 추가해야하는 소스코드, 실행해야 하는 명령어와 셸 스크립트등 을 Dockerfile에 기록해줍니다. 도커는 Dockerfile을 읽어 컨테이너에서 작업을 수행한 뒤 이미지로 만들어냅니다.

Dockerfile 작성

root위치에 Dockerfile이라는 이름을 파일을 만들어줍니다. 만약 VsCode를 사용하신다면 Docker extension을 설치하여 자동완성 기능을 사용할 수도 있습니다. Docker 파일은 한 줄이 하나의 명령어가 됩니다(Layer 형식). 명령어는 소문자로 표기해도 상관없지만 일반적으로 대문자로 표기합니다.

 

간단한 예시파일을 통해 명령어들을 살펴보겠습니다. (아래 예시들은 next.js, yarn 환경입니다.)

FROM node:16

WORKDIR /app

COPY . .

RUN yarn install
RUN yarn build

EXPOSE 3000

CMD ["yarn", "start"]

Dockerfile 기본 명령어

FROM

FROM <image>:<tag>
FROM node:16

베이스 이미지를 지정합니다. 반드지 지정해야 하며 어떤 이미지도 베이스 이미지가 될 수 있습니다. tag는 가능하면 lastest보다 구체적인 버전을 지정하는 것이 좋습니다.

 

WORKDIR

WORKDIR <path>
WORKDIR /app

RUN, CMD, ADD, COPY등이 이루어질 기본 디렉토리를 설정합니다. 각 명령어의 현재 디렉토리는 한 줄 한 줄 마다 초기화 되기 때문에 RUN cd /parh 를 하더라고 다음 줄에서는 위치가 초기화 됩니다. 같은 디렉토리에서 작업하기위해 WORKDIR을 사용합니다.

 

COPY

COPY <src>... <dest>
COPY . .

파일이나 디렉토리를 이미지로 복사합니다. 일반적으로 소스를 복사하는데 사용합니다. target 디렉토리가 없다면 자동으로 생성합니다.

 

RUN

RUN <command>
RUN ["executable". "param1", "param2"]
RUN yarn install

명령어를 그대로 실행합니다. 내부적으로 /bin/sh -c 위에 명령어를 실행하는 방식입니다.

 

EXPOSE

EXPOSE <port> [<port>...]
EXPOSE 3000

도커 컨테이너가 실행되었을 때 요청을 기다리고 있는(Listen) 포트를 지정합니다. 여러개의 포트를 지정할 수 있습니다.

 

CMD

CMD ["executable", "param1", "param2"]
CMD command param1 param2
CMD ["yarn", "start"]

도커 컨테이너가 실행되었을때 실행되는 명령어를 정의합니다. 빌드할 때는 실행되지 않으며 여러개의 CMD 가 존재할 경우 가장 마지막 CMD만 실행됩니다. 한꺼번에 여러 개의 프로그램을 실행하고 싶은 경우 run.sh 파일을 작성하여 데몬을 실행하거나 별도의 프로그램을 사용해야 합니다.

 

이미지 생성(Dockerfile 빌드)

docker build <option> .
docker build -t <태그명> .

-t : 생성될 이미지의 이름을 설정합니다.

. : build 명령어 끝에는 Dockerfile이 저장된 경로를 입력합니다.

 

이미지로 컨테이너 실행

docker run <옵션> <이미지명:태그> <명령어> <인자>
docker run -d --name <컨테이너명> -p <호스트포트>:<컨테이너포트> <이미지명:태그> 
docker run -d --name dockerContainer -p 3000:3000 nextjs-docker

-d : 컨테이너를 백그라운드에서 실행합니다(Detached Mode).

--name <컨테이너명> : 컨테이너의 이름을 설정 합니다.

-p <호스트포트>:<컨테이너포트> : 호스트포트와 컨테이너 내부의 포트를 바인드 합니다(포트포워딩).

(컨테이너는 호스트 환경과 격리된 파일 시스템과 네트워크를 가지기 때문에 호스트에서 컨테이너로 접근 가능하도록 포트포워딩을 시켜줘야 합니다.)

참고: 프론트엔드 개발자를 위한 Docker로 React 개발 및 배포하기

 

Docker Multi stage

Docker Multi stage란? 컨테이너 이미지를 만들면서 빌드 등에는 필요하지만 최종 컨테이너 이미지에는 필요없는 환경을 제거할 수 있도록 단계를 나누어서 기반 이미지는 만드는 방법입니다. 하나의 Dockerfile안에 여러개의 FROM 이미지를 정의하여 최종 생성될 이미지의 크기를 줄일수 있습니다. (17.05 버전 이상)

 

Multi state 방식이 나오기 전에는 하나의 Dockerfile이 아닌 두 가지의 Dockerfile을 유지 하는 builder-patten이나 여러 명령어를 실행하는데 분리하지 않고 && \ 를 통해 하나의 Layer에서 처리 하는 방식등을 사용하였다고 합니다.

 

간단한 예제를 통해 살펴보겠습니다.

FROM node:16-alpine AS builder
WORKDIR /app

COPY . .
RUN yarn install
RUN yarn build

FROM node:16-alpine AS runner
WORKDIR /app

COPY --from=builder /app ./

EXPOSE 3000
CMD ["yarn", "start"]

일반적인 Dockerfile과 다르게 2개의 FROM을 통해 2개의 이미지가 명시되어 있습니다. 두번째 FROM아래에서 사용된 COPY 명령어는첫 번째 FROM에서 사용된 이미지의 최종 상태에 존재하는 /app 의 파일을 복사해서 사용합니다.

COPY --from의 역할

COPY instruction에서 --from옵션을 사용하면 이전 스테이지에서 Build를 통해 생성된 결과만을 복사할 수 있습니다.

AS <Alias-Name>의 역할

특정 빌드 스테이지의 별칭(alias)을 정할 수 있습니다. FROM instruction 레이어에서 사용 가능하고, COPY--from=<name>옵션으로 참조합니다.

 

Reference

도커(Docker)란 무엇이고, 왜 사용하나요?

이론과 실습을 통해 이해하는 Docker 기초

초보를 위한 도커 안내서 - 도커란 무엇인가?

Docker - Mac에 Homebrew로 docker 설치

[Docker] 도커 입문하기 4 -도커 이미지만들기

[Docker] Dockerfile로 이미지 생성하기

초보를 위한 도커 안내서 -이미지 만들고 배포하기

[Docker] Dockerfile로 이미지 빌드하고 컨테이너 띄워보기

Docker Multi Stage란?

[Docker] 멀티 스테이지 빌드로 이미지 크기 줄이기

https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.