반응형
  • nodejs 애플리케이션 컨테이너 만들기 : hellojs
  • 우분투 기반의 웹 서버 컨테이너 만들기
  • 만들어놓은 컨테이너 배포하기

 

nodejs  애플리케이션 컨테이너 만들기 : hellojs

우선, 아래의 명령어를 사용해서 해당 경로에 디렉토리를 만들어주자.

mkdir 폴더이름

hellojs 폴더가 생성되었다. 

hellojs라는 디렉토리로 경로를 설정했다.

 

cat > hello.js

cat명령어를 이용해서 hello.js 소스코드를 만들어 주도록 하겠다. 

const http = require('http');
const os = require('os');
console.log("Test server starting...");

var handler = function(request, response) {
	console.log("Received request from " + request.connection.remoteAddress);
    response.writeHead(200);
    response.end("Container Hostname: " + os.hostname() + "\n");
};

var www = http.createServer(handler);
www.listen(8080);

아래와 같이 파일이 잘 생성 되었다.

이 nodejs는 웹서버를 운영해주는 애플리케이션이고, 

const http = require('http');
const os = require('os');

부분을통해 웹서비스와 OS서비스 이렇게 2가지를 지원해주고 있다. 
그리고 이 hello.js가 실행될 때,  

console.log("Test server starting...");

를 통해 화면에다가 로그메시지를 출력한다.(스탠다드 아웃풋) 

var www = http.createServer(handler);
www.listen(8080);

그리고 80(8080)포트를 listen하며 client connection을 대기하고 있는다. 

그러다가 client사용자가 80번 포트로 들어오게 되면 

var handler = function(request, response) {
	console.log("Received request from " + request.connection.remoteAddress);
    response.writeHead(200);
    response.end("Container Hostname: " + os.hostname() + "\n");
};

response와 request를 핸들링해주게 되는데, 

먼저, console 로그 메시지를 먼저 출력하게 된다. 그리고 그와 함께 200번 상태코드를 보내게 된다. 
웹서비스에서 200번 상태코드는 "극히 정상적인 서비스 입니다."라는 뜻을 가지고 있다. 

그리고 Cotainer Hostname을 찾아오는 함수를 통해 컨테이너 호스트가 누구입니다. 라는 메시지를 주게 된다. 

결국, hsllo.js라는 어플리케이션이 하는 일은 client사용자가 8080번 포트로 접속을하면 호스트네임을 전달해주는 컨테이너이다.(200번 상태코드와 함께, 그리고 로그메시지를 남겨주게 된다.)

container hostname은 당연히 컨테이너 이름이다.

hello.js는 그냥은 절대 실행되지 않는다.

hello.js 소스코드를 해석해서 실행해주는 인터프리터가 필요하다. 즉 이것을 동작시킬 운영환경이 필요하다. 
운영환경으로는 Node라고하는 애플리케이션 플랫폼을 사용 할 것이다. 이것 조차도 컨테이너이다. 

 

이번에는 dockerhub.com의 Explore탭에서 node를 검색해보자.

nodejs자체도 하나의 컨테이너이다.
이것을 우리는 base image로 쓸 것이다. 왜냐하면 hello.js소스코드가 nodejs기반으로 동작해야하기 때문이다. 

여러가지 버전이 있는 것을 확인 할 수 있다. 일단은 여기까지 확인하고 다시 터미널로 가보자.

터미널에서

ls

ls라는 리눅스 명령어를 이용해서 현재 디렉토리에 있는 파일을 확인해보면, hello.js파일을 확인할 수 있다. 

이제 이것을 가지고 컨테이너를 빌드하려면  도커파일을 만들어야 한다.

 

도커 파일 만들기

vi명령어를 이용해서 dockerfile이라는 이름의 파일을 생성해준다.

vi dockerfile  #dockerfile이라는 이름의 파일을 생성하는 vi 명령어

vi 명령어를 실행하면 터미널이 이렇게 vi에디터로 도커파일을 작성 할 수 있게 된다. 
i 를 눌러서 도커파일을 작성 해보자.

도커파일의 소스코드를 작성했다.도커명령어는 대소문자를 구분할 필요는 없지만, 가독성을 위해 보통 대문자로 표현한다.

 FROM node:12

내가 만든 hello.js를 해석해서 실행해 줄 수 있도록 운영환경을 제공해 줄 컨테이너를 base image로 집어 넣는 것이다. 

COPY hello.js /

그리고 현재디렉토리에 있는 hello.js라는 파일을 컨테이너의 최상위 디렉토리로 복사해 줄 것이다.  (COPY대신에 ADD해도 된다)

CMD ["node", "/hello.js"]

CMD명령으로 커맨드를 실행 해 줄 것인데, "node"라는 명령을 가지고 루트에 있는 "/hello.js"를 동작시키도록, 컨테이너를 Run하게 되면, CMD에 있는 명령이 자동으로 실행되도록 해주었다. 

이외에도 도커파일에 간단하게 코멘트도 집어넣을 수 있고, 레이블을 이용해서 이 프로그램에 대한 정보를 집어 넣을 수도 있다. 나중에 살펴보도록 하겠다. 

지금은, 가장 간단하게 base image, source code, container가 러닝될때, 실행할 커맨드 까지만 집어넣어서 도커파일을 저장하도록 하겠다. 

도커파일을 다 작성했으면 esc를 누르고 커맨드 입력창에

:wq

를 입력해서 저장하자.

파일을 살펴보자. 

소스코드는 hello.js가 있다.

그리고 소스코드를 dockerfile에서 보면,

node12라고하는 버전을(node 12버전의 컨테이너이미지를) base로 넣고, 현재디렉토리에 있는 hello.js파일을 컨테이너의 최상위 디렉토리로 복사하고, 그리고나서 컨테이너를 러닝할 때 동작하도록 하는 도커파일이다.

 

컨테이너 이미지 빌드하기

docker build -t 원하는이름:태그 . # 태그는 생략가능하며 생략하면 자동적으로 latest이다. 
#그리고 마지막에 .은 현재 디렉토리에 있는 파일을 기준으로 작업해라 라는  (도커 호스트의 작업 디렉토리를 알려줌)
# 만약 hello.js라는 파일이 현재 디렉토리에 있는 것이 아니라 tmp디렉토리에 있다면 . 대신 /tmp를 쓴다.

해당 명령어를 사용해서  빌드하면, 도커파일이 탑다운 방식으로 해석되면서 실행된다. 

도커 파일을 통해 도커 컨테이너 빌드를 했다.

도커 파일의 라인 1개당 이미지가 1개씩 생성되어 총 3개의 이미지가 생성되었다. 

도커 컨테이너이미지가 잘 만들어 졌는지 확인해보자.

docker images
docker image ls

위에서 만든 hellojs latest가 있는 것을 확인 할 수 있다. 

이것을 실행하면 8080포트를 가지고 서비스되는 컨테이너가 실행된다. 

여기까지하면 위에 제시한 3가지 항목 중 첫번째인

  • nodejs 애플리케이션 컨테이너 만들기 : hellojs 

를 완료하게 된다.


 

우분투 기반의 웹 서버 컨테이너 만들기

 

먼저, 기존에 존재하는 웹서버 도커파일을 보며 생각해보면 좋다.

웹서버 도커파일 중 하나인 httpd의 도커파일이다.

https://github.com/docker-library/httpd/blob/a7acc047c8970e0502f4c6b577775f840f1f99b6/2.4/Dockerfile

 

GitHub - docker-library/httpd: Docker Official Image packaging for Apache HTTP Server

Docker Official Image packaging for Apache HTTP Server - GitHub - docker-library/httpd: Docker Official Image packaging for Apache HTTP Server

github.com

해당 파일을 훑어보면 대략적인 구조를 파악할 수 있다.

 

우선은 base image로 우분투를 만들어야하지 않을까? 

우선은, 아까전에 hello.js를 작업했던 폴더를 빠져나간 뒤, 새로운 폴더를 만들어준다. 이름은 webserver로 해주겠다.
그리고 해당 디렉토리로 이동한다.

 

도커파일을 작성할건데, 이번에는 vi보다 더 기능이 향상된 vim에디터를 이용해보자.

vim 원하는도커파일이름

이번에도 도커파일이름을 dockerfile이라고 명시해주었다. 

i를 눌러서 도커파일을 작성해보자.

FROM ubuntu:18.04

우분투 18.04 버전을 base이미지로 만들었다.  

LABEL maintainer="Mingyo Kim <mgkim.developer@gmail.com>"

LABEL을 통해 key value타입으로  엔지니어의 정보를 넣어줄 수 있다.

# install apache

#(주석)을 통해 코멘트를 넣어 줄 수 있다.

RUN apt-get update
RUN ape-get install -y apache2

컨테이너가 빌드 될 때 내부에서 실행할 명령어 RUN으로 
우분투니까 apt-get update 해주고, 
apt-get install -y apache2 를 통해 apache2라고 하는 이름의 패키지를 설치해준다.

그런데 이렇게 실행하면, RUN명령어별로 1개의 레이어로 총2개의 레이어, 즉, 도커파일기준으로는 FROM과 LABEL을 포함하여 총 4개가 된다.

그런데 리눅스 커맨드에는 앰퍼센트(&)기호가 있다. 이것을 이용하면 여러개의 명령을 한 라인에서 실행할 수 있도록 지원 해준다. 

RUN apt-get update && apt-get install -y apache2

앞에있는 apt-get update 커맨드가 성공하면 앰퍼퍼센트 뒤에 있는 커맨드 실행해라는 조건 연산자(&&)이다.
리눅스 쉘에서 지원되는 조건연산자(&&)인데, 우분투이기 떄문에 이러한 조건 연산자를 쓸 수 있다. 왜냐하면 그 안에 Bash shell이 들어있기 떄문이다.

그래서 위와 명령어를 한라인에 모아주고, 가독성이 좋도록 아래와같이 작성해준다.

RUN apt-get update \
   && apt-get install -y apache2

\(백슬래쉬) 를 하고 엔터를 하면 라인의 연속을 나타낸다.
따라서 백슬래쉬를 사용하고 엔터를해서 들여쓰기를해주면 가독성을 좋게 작성할 수 있다. 

웹서버 설치는 끝냈다.

그런데, 나만의 웹서버니까 웹서버설치로만 끝내지말고 아래와 같이 진행해보자.

RUN echo "TEST WEB"> /var/www/html/index.html

아파치 웹서버를 설치하게 되면, var디렉토리 안에 www디렉토리 안에 html안에서 index.html을 찾아서 client에게 서비스해주게 된다. 따라서 RUN echo 명령을 통해 내가 서비스 하고싶은 TEST WEB 이라는 이름의 웹페이지를 하나 만들어서 저장시켰다.

만약, 미리 만들어준 페이지가 있다면 RUN 대신 COPY명령을 이용해서 사용해도 된다. 

EXPOSE 80

이 컨테이너가 서비스하는 포트는 80번이라고 작성했다.

CMD ["/usr/sbin/apache2ctl", "-DFOREGROUND"]

CMD orENTRYPOINT 를 이용해서 명령어를 작성하는데,

이 컨테이너를 러닝할때, /usr/sbin/apache2ctl을 실행하는데, -DFOREGROUND 라고하는 Argument를 넣어서 실행해줘 라는 뜻이다.

이제 이 도커파일을 가지고 컨테이너 이미지로 빌드해보자. 

docker build -t 원하는이름:태그 혹은 버전 .​

도커파일을 도커 컨테이너 이미지로 빌드했다. 한번 확인해보자.

docker image ls
docker images

webserver라는 이름의 도커 컨테이너 이미지를 확인할 수 있다. 

 

한번 실행해보자.

docker run -d -p 포트번호:포트번호 --name 컨테이너이름지정 도커이미지명:태그

잘 실행되었나 확인해보자.

docker ps		# 또는
docker container ls

컨테이너가 동작 중이다.

직접 확인해보자.

curl localhost:포트번호

curl명령을 통해 텍스트 베이스의 클라이언트 웹브라우져에 접속해보자.

만약, 내가 만든 TEST WEB이라는 웹브라우져가 보이면 성공이다. 

아주 잘 동작하고 있는 컨테이너다.

 

이번에는 컨테이너를 삭제해보자.

docker rm -f 삭제할컨테이너명		# -f 는 실행중인 컨테이너를 삭제하기위한 옵션

실행중인 컨테이너를 삭제했고, 현재 실행중인 컨테이너가 없는 것을 확인했다.

 


 

앞서 만들어둔 hellojs 도커이미지도 컨테이너로 실행해보자.

이 컨테이너는 8080포트로 접속하면 hostname(컨테이너 이름)을 송출해주는 컨테이너다.
확인해보자.

hostname이 잘 출력된다.  (container id의 앞 12글자를 따서 컨테이너 이름으로 쓴다)

테스트를 해서 확인했으니, 동작중인 해당 컨테이너도 삭제해주도록 하겠다. 

실행중인 컨테이너 삭제를 완료했다.

여기서 오해하지 말아야 할 것은, 컨테이너를 제거한 것이지 도커 이미지를 제거한 것이 아니다.

도커 이미지는 잘 저장되어 있다.

 


 

만들어 놓은 컨테이너 배포하기

이제 이 이미지를 나의 dockerhub계정에 업로드 시켜볼 것이다. 누구나 다운로드 받을 수 있도록 말이다.
즉 컨테이너를 배포를 할 것이다.

우선 dockerhub로그인을 하자.

docker login

원래는 dockerhub username과 password를 입력해야하는데, 나는 도커데스크탑에 로그인이 되어있어서 바로 로그인에 성공했다.

내가 현재 가지고 있는 도커 이미지는 아래와 같다.

그런데, 나의 dockerhub계정으로 업로드하려면 이미지의 이름앞에 내 계정이름을 붙여야 한다.

아래의 명령어를 이용해서 만들어둔 도커이미지의 이미지명을 수정해보자.

docker tag 기존의도커이미지명:태그 내계정이름/도커이미지명:태그

수정이 되었는지 확인해보자.

여기서 재밋는 일이 발생했다. 2개의 이미지가 있어야하는데 총 4개의 이미지가 있다.

도커허브 유저이름을 붙힌 이미지로 이미지가 수정되어 2개로 저장되는 것이아니라,

docker image는 image id로 저장되고, 수정한 이름으로 이름만 각각 1개씩 추가로 있는 것이다.

이렇게 수정되는것이 방금전에 앞에서 사용한"tag"명령어다.

 

이제, mgyo/webserver 도커 이미지와, mgyo/hellojs 도커 이미지를  docker hub에 배포 해 줄 것이다.

앞에서 로그인 했기 때문에 바로 아래의 명령어를 수행하자.

docker push 도커허브계정이름/도커이미지이름:태그

도커이미지를 Push로 업로드했다.

성공적으로 업로드 되었다면, dockerhub.com의 내 레포지토리를 확인해보면 도커 이미지를 확인할 수 있다.

이제, 나의 레포지토리에 있는 도커 이미지는 누구든지 다운받아서 사용할 수 있다.
이것을 "컨테이너 배포" 라고 한다.

 

 

반응형