[#3] 커스텀 Docker 이미지 만들어보기

Written by 코드팩토리 JC

1월 15, 2024

코드팩토리 Docker 부터 Kubernetes 까지

소개

이번 회에선 Docker 커스텀 이미지를 제작하는 방법에 대해 알아보도록 하겠습니다.

Docker 부터 Kubernetes까지 GitHub 레포지토리

https://github.com/serendipity1004/medium-docker-to-kubernetes 에 접속하셔서 횟수 이름으로 브란치를 변경하시면 해당 횟수의 코드를 chekcout 하실 수 있습니다. 예) 3회 -> #3 브란치

더 진행하기전 필수지식

  1. Javascript 언어와 nodeJS 프레임워크 그리고
  2. express 서버에 대한 기본적인 지식
  3. REST API에 대한 기본적인 지식 nodeJS가 설치된 컴퓨터 (https://nodejs.org/en/에서 환경에 맞는 v10 이상의 버전을 설치하시면 됩니다)

이번 회에선 위 두 가지를 어느 정도 알고 계신다는 가정하에 진행하게 되겠습니다.

프로젝트 구조 갖추기

앞으로 프로젝트를 진행하실 폴더를 생성하시고 좋아하시는 IDE에서 실행을 해주세요. 저 같은 경우 대부분 IntelliJ IDEA를 사용합니다. 추가적으로 IDE에서 Dockerfile 문법 체크를 지원하면 플러그인도 같이 설치해주시면 프로젝트 진행하시는데 유리합니다.

npm init -y
npm i --save express
ShellScript

설치가 완료되시면 아래 코드를 server.js에 붙여넣기 해주면 됩니다.

const express = require('express');
const app = express();
const port = process.env.PORT;

app.get('/', (req, res) => {
    res.json({
        success: true
    });
});

app.listen(port, () => {
    console.log(`server is listening at localhost:${process.env.PORT}`);
});
JavaScript

굉장히 간단한 서버 코드입니다. 익스프레스 서버를 저희가 환경 변수에 지정한 포트에 실행하여 루트 URL에 GET 요청이 있을 시 {success:true}라는 JSON을 리턴해주는 코드입니다. 아래 커맨드를 이용해 서버를 실행해보도록 하겠습니다.

PORT=3000 node server.js
JavaScript

제대로 실행되셨다면 http://localhost:3000에 접속하셔서 {success:true}라는 JSON 응답을 받으실 수 있을 겁니다. Ctrl + C를 실행해서 서버를 꺼주세요.

도커이미지 세팅하기

루트 폴더에 Dockerfile이라는 파일을 생성하고 아래 코드를 붙여 넣어주세요.

FROM node:10-alpine

WORKDIR /app/usr

# Copy dependencies first for effective caching
COPY package*.json ./

RUN npm install

COPY . .

CMD ["npm", "run", "start"]
Dockerfile
  1. FROM node:10-alpine{.dockerfile}

Docker 베이스 이미지를 node라는 이미지에 10-alpine 태그가 붙은 이미지로 사용하라는 뜻입니다. Docker 태그에 대해서는 나중에 더 배워보도록 하겠습니다. 해당 이미지에 대한 설명은 https://hub.docker.com/_/node/ 이곳에서 볼 수 있습니다.

  1. WORKDIR /app/usr

Docker 컨테이너 내부에서 작업 디렉터리를 /app/usr로 지정합니다. 이후 커맨드는 /app/usr 폴더를 기본 폴더로 사용하게 됩니다.

  1. COPY package*.json ./

로컬 디렉터리의 package.json 및 와일드카드에 해당되는 모든 패키징 파일을 (package-lock.json 포함) Docker 컨테이너의 현 위치 (./)로 복사합니다. 위에서 WORKDIR /app/usr를 적용시켰기 때문에 현재 위치는 /app/usr가 됩니다.

  1. RUN npm install

npm install을 실행하여 nodeJS 패키지들을 설치합니다.

  1. COPY . .

로컬의 현재 위치 파일들을 컨테이너 내부의 현 위치로 복사합니다.

  1. CMD [“node”, “server.js”]

마지막으로 node server.js라는 명령어를 실행해 컨테이너 내부에서 server.js를 실행합니다.

3번과 5번 스텝을 왜 통합하지 않는지 의아해하시는 분도 분명 계실 겁니다. 그 이유는 Docker는 라인별로 캐싱을 하기 때문에 디펜던시가 변경돼서 package.json만 변경이 되었을 경우 3번째와 4번째 라인만 실행이 되고 5번째 라인은 저장된 캐시에서 그대로 불러오게 됩니다. 훨씬 더 효율적이여지게 되죠.

완료되셨으면 루트 폴더에. dockerignore 파일을 생성하여 아래 코드를 붙여 넣습니다.

node_modules
ShellScript

.dockerignore 파일은. gitignore 파일과 비슷한 역할을 합니다. Docker 컨테이너를 생성할 때. dockerignore 파일에 있는 모든 사항들은 무시하게 되죠. nodeJS 모듈들은 환경에 따라 디펜던시 버전이 달라질 수 있기 대문에 컨테이너 내부적으로 설치를 하고 로컬 환경에서 따로 옮겨오진 않겠습니다.

이제 환경 변수 설정을 위해 루트 폴더에 .env 파일을 생성하겠습니다. 생성 후 아래 코드를 붙여 넣어주세요.

PORT=3000
ShellScript

좀 전에 server.js를 실행할 때 포트를 커맨드 라인에서 PORT 환경 변수 지정을 해주었는데 Docker 컨테이너 실행 시에는 파일로 여러 환경 변수를 동시에 설정해주도록 하겠습니다.

이제 Docker 파일을 생성할 준비가 됐습니다. 아래 커맨드를 실행하여 이미지를 빌드 해주세요.

docker build -t "nodejs-docker" .
ShellScript

-t 플래그는 태그를 지정하는 플래그입니다. 컨테이너 실행 시 태그를 기반으로 이미지를 지정하게 됩니다. 맨 끝에 ‘.’을 꼭 포함해주시기 바랍니다. 현 위치에서 Docker 컨테이너를 빌드 하라는 뜻입니다.

아래와 같은 응답이 오셨다면 성공입니다.

docker build
docker build

응답을 잘 보시면 저희가 작성한 코드를 한 줄 줄 읽어내려가면서 컨테이너가 생성되는 걸 보실 수 있습니다.

그럼 저희가 빌드 한 컨테이너를 실행해보겠습니다.

docker run --env-file .env -p 4000:3000 nodejs-docker
ShellScript

빌드 한 nodejs-docker 이미지를 실행하는 커맨드입니다. — env-file 플래그를 사용해 저희가 생성한 환경 변수 파일을 지정해주었고 -p 플래그로 컨테이너 내부의 3000번 포트를 4000번 포트로 매핑해주었습니다. 이전에 로컬에서 실행한 3000번 포트의 express 서버가 아니라는 걸 확실히 보여드리기 위해 포트를 변경해보았습니다.

http://localhost:4000을 접속해보시면 {success:true}응답이 오는 것을 확인하실 수 있을 겁니다.

이로써 Docker 이미지를 생성하는 기본기에 대해 배워보았습니다. 다음 시간에는 이미지들을 docker hub에 업로드하여 공유하고 퍼블릭 레포지토리에서 이미지를 풀해오는 방법에 대해 알아보도록 하겠습니다.

관련 포스트

플러터에서의 Immutable Programming: copyWith 함수 마스터하기!

플러터에서의 Immutable Programming: copyWith 함수 마스터하기!

서론 불변 프로그래밍: 현대 개발의 핵심 현대 소프트웨어 개발에서 불변 프로그래밍(Immutable Programming)의 중요성은 간과할 수 없는 요소입니다. 플러터(Flutter)에서도 마찬가지로 불변 프로그래밍 개념이 매우 중요하며, copyWith 함수는 이러한 불변성을 유지하는 데 핵심적인 역할을 합니다. 이 글에서는 플러터를 배우기 시작하는 개발자들에게 불변 프로그래밍의 중요성을 강조하고, copyWith 함수의 역할과 사용 방법에 대해 설명 해보겠습니다!...

ChatGPT가 이야기하는 2024년 개발자 로드맵

ChatGPT가 이야기하는 2024년 개발자 로드맵

서론 개발자의 여정을 시작하며 안녕하세요, 미래의 개발자 여러분! 오늘부터 시작하는 여러분의 개발 여정에 함께할 수 있어서 기쁩니다. 2023년은 기술이 매우 빠르게 변화하는 해였으며, 이러한 변화 속에서 개발자가 되기 위한 길은 더욱 다채롭고 흥미로워졌습니다. 이 로드맵은 초보자인 여러분이 개발의 세계에 첫발을 내딛는 데 필요한 기초부터 시작해, 점차 심화 단계로 나아가는 길을 안내해 드릴 것입니다. 백엔드 개발 이 글은 단순히 기술을 배우는 것 이상의 의미를 가집니다....

Flutter Freezed 플러그인! Entity Code Generation은 이거 하나로 끝!

Flutter Freezed 플러그인! Entity Code Generation은 이거 하나로 끝!

https://youtu.be/i5p6wXLAX7I 서론 Flutter 는 Code Generation 기능이 상당히 많이 활성화되어 있어요. 흔히들 많이 사용하는 json_serializable 라이브러리도 있고 retrofit 및 chopper 라이브러리도 있습니다. 오늘 알려드릴 freezed 또한 데이터 클래스에 편의 기능들을 제공해주는 code generation 라이브러리입니다. Freezed vs Json Serializable Code Generation 이라는...