삽질의 현장/- Docker&Kubernetes

[GCP Study Jam] GCP를 활용한 Docker 사용해보기

shovelman 2019. 1. 13. 18:52

GCP를 활용한 Kubernetes 학습을 진행하며 정리하는 글입니다 (Google Cloud Study Jam 참여 중).

* 공통적으로 실습에서 사용되는 실제 PROJECT ID 는 PROJECT_ID로 대체합니다.

Gcloud

gcloud 는 gcp 를 위한 커멘드 라인 도구로, cloud shell에 사전 설치 되어 있습니다. (탭 완성 지원)

(계정을 활성화 하게 되면 계정 정보 및 프로젝트 ID를 얻을 수 있는데, Docker 이미지를 Google Container Registry 에 올리게 될 때 사용했습니다.)

Hellow World

'hello-world'라는 이름의 컨테이너를 실행해보겠습니다.

$ docker run hello-world

docker 데몬은 hello-world라는 이미지를 검색합니다. 로컬 환경에서 찾지 못할 경우 Docker Hub라고 하는 공통 저장소로부터 이미지를 받아와서 컨테이너를 생성하고 실행하게 됩니다.

Docker Hub에서 가져온 컨테이너 이미지는 'docker images' 라는 명령어를 통해 확인이 가능합니다.

$ docker images
REPOSITORY     TAG      IMAGE ID       CREATED       SIZE
hello-world    latest   1815c82652c0   6 days ago    1.84 kB

실행 중인 컨테이너를 보기 위해서는 'docker ps'라는 명령을 실행합니다.

$ docker ps -a

Build

Node 어플리케이션 기반의 Docker 이미지를 빌드 해보겠습니다.

$ mkdir test && cd test
$ cat > Dockerfile <<EOF
# 기본 상위 이미지를 지정합니다. 해당 예제는 node 6버전의 공식 Docker 이미지를 지정했습니다.
FROM node:6

# 컨테이너가 있는 디렉토리를 설정합니다.
WORKDIR /app

# 현재 디렉토리의 내용('.')을 컨테이너에 추가합니다.
ADD . /app

# 해당 포트에서 연결을 허용합니다.
EXPOSE 80

# node 명령을 실행하여 응용 프로그램을 시작합니다.
CMD ["node", "app.js"]
EOF

실행 시킬 응용 프로그램(app.js) 코드입니다.

const http = require('http');

const hostname = '0.0.0.0';
const port = 80;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
      res.setHeader('Content-Type', 'text/plain');
        res.end('Hello World\\n');
});

server.listen(port, hostname, () => {
    console.log('Server running at http://%s:%s/', hostname, port);
});

process.on('SIGINT', function() {
    console.log('Caught interrupt signal and will exit');
    process.exit();
});

현재 위치 기준으로 빌드 합니다.

'-t'을 통해 이미지의 이름 및 태그를 지정합니다.

$ docker build -t node-app:0.1 .

이미지의 이름은 'node-app'이고, 태그 이름은 '0.1' 입니다. Docker 이미지를 생성할 때 태그를 사용하는 것이 좋다고 합니다. 태그를 지정하지 않게 되면 태그의 기본값이 최신이기 때문에 이전 이미지와 구별하기가 어려워지기 때문입니다.

Run

방금 생성한 이미지를 기반으로 컨테이너를 실행합니다.

$ docker run -p 4000:80 --name my-app node-app:0.1

'--name' 플래그는 컨테이너의 이름을 지정할 수 있게 합니다. '-p' 플래그는 Docker가 4000번인 호스트 포트를 80 포트에 매핑하도록 지정한 것입니다. 포트 매핑을 하지 않는 다면 localhost에서 컨테이너에 연결할 수 없습니다.

컨테이너를 실행 중지 및 제거하기 위해서는 아래의 명령어를 사용합니다.

$ docker stop my-app && docker rm my-app

'-d' 옵션을 주게 되면 backgroud로 컨테이너가 실행하게 됩니다.

$ docker run -p 4000:80 --name my-app -d node-app:0.1

어플리케이션을 수정해보겠습니다.

const http = require('http');

const hostname = '0.0.0.0';
const port = 80;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
      res.setHeader('Content-Type', 'text/plain');
-       res.end('Hello World\\n');
+       res.end('Welcome to Cloud\\n');
});

server.listen(port, hostname, () => {
    console.log('Server running at http://%s:%s/', hostname, port);
});

process.on('SIGINT', function() {
    console.log('Caught interrupt signal and will exit');
    process.exit();
});

태그 명을 '0.2'로 지정하고 새로운 빌드를 수행합니다.

$ docker build -t node-app:0.2 .

신규 생성된 이미지로 새로운 컨테이너를 생성해보겠습니다.

$ docker run -p 8080:80 --name my-app-2 -d node-app:0.2
docker ps

실행 중인 컨테이너에 각각 접근 시 각각 자신의 응답값을 반환하고 있습니다.

$ curl <http://localhost:8080>
Welcome to Cloud

$ curl <http://localhost:4000>
Hello World

Debug

컨테이너 ID를 알고 있다면 로그 확인이 가능합니다. (컨테이너가 실행 중이라면 '-f' 옵션을 주게 되면 확인이 가능합니다.)

$ docker log -f CONTAINER_ID

실시간으로 Bash 스크립트도 실행이 가능합니다.

$ docker exec -it CONTAINER_ID bash

메타 데이터도 확인이 가능합니다.

$ docker inspect CONTAINER_ID

Publish

Google Container Registry(gcr)에 이미지를 Push할 수 있습니다. 어떤 환경에서든지 Push한 이미지를 받아 컨테이너를 실행시킬 수 있습니다. 이미지를 업로드하기 위해서는 host명과 프로젝트ID, 이미지 이름, 태그 이름이 필요합니다.

$ gcloud config list project //project id

저장소에 올리기 위한 포멧은 '[hostname]/[project_id]/[image]:[tag]' 입니다.

태그를 새로 생성하고 gcr에 push 하겠습니다.

$ docker tag node-app:0.2 gcr.io/ROJECT_ID/node-app:0.2
$ gcloud docker -- push gcr.io/PROJECT_ID/node-app:0.2

실제 http://gcr.io/[project-id]/node-app 에 접근해보면 Push된 이미지를 확인할 수 있습니다.

로컬 환경에서 테스트를 진행하기 위해 기존 실행 및 생성된 정보들을 지우겠습니다.

$ docker stop $(docker ps -q)
$ docker rm $(docker ps -aq)

$ docker rmi node-app:0.2 gcr.io/[project-id]/node-app node-app:0.1
$ docker rmi node:6
$ docker rmi $(docker images -aq) # remove remaining images
$ docker images

환경을 말끔히 정리했으니, 이미지를 새로 받아보겠습니다.

$ gcloud docker -- pull gcr.io/[project-id]/node-app:0.2
$ docker run -p 4000:80 -d gcr.io/[project-id]/node-app:0.2
$ curl <http://localhost:4000>

학습 내용 출처 : https://run.qwiklabs.com/focuses/1029?parent=catalog