- Docker 허브의 공개 이미지를 기반으로 컨테이너를 실행하기
- 컨테이너 이미지를 직접 만들어 Google 아티팩트 레지스트리에 푸시하기
- 실행 중인 컨테이너를 디버깅하는 방법
- Google 아티팩트 레지스트리에서 가져온 이미지를 기준으로 컨테이너를 실행하기.
Docker에 대한 중요한 개념 두가지만 알고 넘어가자!
Image (이미지) : 도커 이미지는 소스 코드, 라이브러리, 종속성, 도구 및 응용 프로그램을 실행하는데 필요한 기타 파일을 포함하는 불변(변경 불가) 파일이다.
Container (컨테이너) : 컨테이너를 생성하면 쓰기 가능한 레이어가 immutable image(불변 이미지) 위에 추가된다. 즉, 컨테이너는 수정이 가능하다.
컨테이너를 생성하는 이미지 베이스는 별도로 존재하며 변경할 수 없다.
1. cloud shell 실행
Google 클라우드에서 shell을 실행시킨다. 연결이 완료되면 이미 인증된 상태로 연결이 실행되며 다음과 같이 해당 세션의
PROJECT_ID가 자동으로 설정된다.
Your Cloud Platform project in this session is set to YOUR_PROJECT_ID
밑에서 gcloud란 Google Cloud를 위한 command-line tool이다. 쉘이 시작될때 먼저 설치돼서 실행된다.
- (Optional) 다음과 같은 커맨드로 활성화된 account list를 얻을 수 있다:
gcloud auth list
Output:
ACTIVE: *
ACCOUNT: student-01-xxxxxxxxxxxx@qwiklabs.net
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (Optional) 프로젝트 ID 또한 다음과 같은 커맨드로 얻을 수 있다:
gcloud config list project
Output:
[core]
project = <project_ID>
Example output:
[core]
project = qwiklabs-gcp-44776a13dea667a6
Task 1. Hello world
- 쉘에서 무작정 Docker를 이용해 hello-world를 실행시켜보자
docker run hello-world
(Command Output)
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
9db2ca6ccae0: Pull complete
Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
로컬에 hello-world가 존재하지 않기 때문에 당연히 실행이 안되겠지.. 했는데
로컬에 없으면 Docker Hub라는 public registry에서 이미지를 pull하고, 그 이미지에 컨테이너를 생성하고 컨테이너를 실행시킨다!
다시 hello-world를 run 해보면..
docker run hello-world
(Command Output)
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
...
이미 첫번째 과정에서 나의 로컬에 이미지와 컨테이너가 생성되었기 때문에 문제없이 잘 돌아간다.
- 실행중인 컨테이너 보기
docker ps
- 모든 컨테이너 보기(실행이 끝난 것 까지)
docker ps -a
(Command Output)
CONTAINER ID IMAGE COMMAND ... NAMES
6027ecba1c39 hello-world "/hello" ... elated_knuth
358d709b8341 hello-world "/hello" ... epic_lewin
Task 2. 이미지 빌드하기
- 디렉토리 만들고 test디렉토리로 이동
mkdir test && cd test
- DockerFile 생성
cat > Dockerfile <<EOF
FROM node:lts
WORKDIR /app
ADD . /app
EXPOSE 80
CMD ["node", "app.js"]
EOF
한 줄 씩 뜯어보자.
cat 명령어는 파일의 내용을 출력하는 명령어입니다. > 기호는 리다이렉션 연산자로, 표준 출력을 파일로 저장하는 역할을 합니다.
즉, cat > Dockerfile은 현재 터미널에서 작성한 내용을 Dockerfile이라는 이름의 파일로 저장하겠다는 의미입니다.
그리고 <<EOF는 히어도클(Heredoc)라는 문법을 사용한 것으로, EOF라는 단어가 나올 때까지 터미널에서 입력한 내용을 파일에 씁니다. 따라서 cat > Dockerfile <<EOF는 현재 터미널에서 입력한 내용을 Dockerfile이라는 파일에 쓰고자 함을 나타내는 것입니다.
- FROM node:lts: 공식 Node runtime 이미지를 부모 이미지로 사용합니다. 부모 이미지는 Docker 이미지를 구성하는 기본 레이어가 됩니다.
- WORKDIR /app: 컨테이너 내부의 작업 디렉토리를 /app로 설정합니다. 이 디렉토리가 작업 디렉토리가 되며, 이후 명령어들은 이 디렉토리에서 실행됩니다.
- ADD . /app: 현재 디렉토리의 모든 파일과 폴더를 컨테이너 내부의 /app 디렉토리로 복사합니다.
- EXPOSE 80: 컨테이너의 80번 포트를 외부로 공개합니다. 이를 통해 외부에서 컨테이너의 애플리케이션에 접근할 수 있습니다.
- CMD ["node", "app.js"]: 컨테이너가 시작될 때 실행될 명령어를 지정합니다. 이 경우 node app.js 명령어를 실행하여 Node.js 애플리케이션을 실행합니다.
- node application생성하기:
cat > app.js <<EOF
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();
});
EOF
80번 포트를 listen하는 HTTP서버이다
이제 이미지를 만들어 보자
- "."을 붙이는 것은 이 DockerFile이 있는 위치에서 커맨드를 실행하겠다는 의미이다
docker build -t node-app:0.1 .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM node:lts
6: Pulling from library/node
...
...
...
Step 5 : CMD node app.js
---> Running in b677acd1edd9
---> f166cd2a9f10
Removing intermediate container b677acd1edd9
Successfully built f166cd2a9f10
-t 는 name:tag의 양식으로 이미지의 이름을 생성하겠다는 것.
- 내가 만든 이미지가 잘 생성되었나 확인해보자
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node-app 0.1 f166cd2a9f10 25 seconds ago 656.2 MB
node lts 5a767079e3df 15 hours ago 656.2 MB
hello-world latest 1815c82652c0 6 days ago 1.84 kB
여기서 node-app의 베이스 이미지는 lts 태그의 node이다. node-app을 먼저 삭제해야면 node를 삭제할 수 있다.
Task 3. Run
- 실행시켜보자
docker run -p 4000:80 --name my-app node-app:0.1
(Command Output)
Server running at http://0.0.0.0:80/
--name은 내가 만든 컨테이너에 이름을 붙일 수 있다.
-p 는 호스트 포트:컨테이너 포트
포트 맵핑을 꼭 해줘야 통신이 가능하다.
- 새로운 터미널을 열어 서버를 테스트해보자
curl http://localhost:4000
(Command Output)
Hello World
만약 컨테이너를 백그라운드에서 실행시키고 싶으면 -d flag를 이용해 보자.
- my-app을 정지하고 삭제
docker stop my-app && docker rm my-app
- -d flag사용
docker run -p 4000:80 --name my-app -d node-app:0.1
docker ps
(Command Output)
CONTAINER ID IMAGE COMMAND CREATED ... NAMES
xxxxxxxxxxxx node-app:0.1 "node app.js" 16 seconds ago ... my-app
my-app을 수정해보자
- test 디렉토리로 이동
cd test
- vi를 이용해 출력문을 Welcome to Cloud로 바꿔주었다
....
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Welcome to Cloud\n');
});
....
- 이미지의 태그를 0.2로 바꾸어 수정한다
docker build -t node-app:0.2 .
- 4000번 포트는 이미 0.1이 쓰고 있으니 8080포트로 run한다
docker run -p 8080:80 --name my-app-2 -d node-app:0.2
docker ps
(Command Output)
CONTAINER ID IMAGE COMMAND CREATED
xxxxxxxxxxxx node-app:0.2 "node app.js" 53 seconds ago ...
xxxxxxxxxxxx node-app:0.1 "node app.js" About an hour ago ...
- 컨테이너를 테스트해보자
curl http://localhost:8080
(Command Output)
Welcome to Cloud
- 0.1 컨테이너 테스트
curl http://localhost:4000
(Command Output)
Hello World
Task 4. 디버그
- -f 옵션을 이용해서 실행중인 컨테이너의 로그를 받아볼 수 있다
docker logs -f [container_id]
(Command Output)
Server running at http://0.0.0.0:80/
- 새로운 터미널에서 아래와 같은 커맨드를 입력해 컨테이너를 종료시킬 수 있다
docker exec -it [container_id] bash
(Command Output)
root@xxxxxxxxxxxx:/app#
- 디랙토리 안의 목록들을 보자
ls
(Command Output)
Dockerfile app.js
- Bash 세션을 끝낸다
exit
- 아래와 같은 커맨드로 컨테이너의 세부 정보를 볼 수 있다.
docker inspect [container_id]
(Command Output)
[
{
"Id": "xxxxxxxxxxxx....",
"Created": "2017-08-07T22:57:49.261726726Z",
"Path": "node",
"Args": [
"app.js"
],
...
Task 5. 배포
Google Cloud 상단의 검색창을 이용해서 Artifact Registry > Repositories 에 진입한다.
Create Repository를 Docker 포멧으로 진행한다. Region은 us-central1으로 설정했다.
- 이미지를 푸시하거나 끌어오기 전에 Google 클라우드 CLI를 사용하여 아티팩트 레지스트리에 대한 요청을 인증하도록 도커를 구성해야 한다.
gcloud auth configure-docker us-central1-docker.pkg.dev
- 이후 Y를 눌러줌
이제 아티팩트 레지스트리에 접근할 수 있다
Push
- 프로젝트 아이디를 세팅하고 test디렉토리로 이동한다
export PROJECT_ID=$(gcloud config get-value project)
cd ~/test
- 0.2를 run한다
docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/node-app:0.2 .
- 이미지들을 체크해본다
docker images
(Command Output)
REPOSITORY TAG IMAGE ID CREATED
node-app 0.2 76b3beef845e 22 hours
us-central1-....node-app:0.2 0.2 76b3beef845e 22 hours
node-app 0.1 f166cd2a9f10 26 hours
node lts 5a767079e3df 7 days
hello-world latest 1815c82652c0 7 weeks
- 이미지를 아티팩트 디렉토리에 push한다
docker push us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/node-app:0.2
Command output (yours may differ):
The push refers to a repository [us-central1-docker.pkg.dev/[project-id]/my-repository/node-app:0.2]
057029400a4a: Pushed
342f14cb7e2b: Pushed
903087566d45: Pushed
99dac0782a63: Pushed
e6695624484e: Pushed
da59b99bbd3b: Pushed
5616a6292c16: Pushed
f3ed6cb59ab0: Pushed
654f45ecb7e3: Pushed
2c40c66f7667: Pushed
0.2: digest: sha256:25b8ebd7820515609517ec38dbca9086e1abef3750c0d2aff7f341407c743c46 size: 2419
- 이후 네비게이션에서 앞서 생성했던 아티팩트 디렉토리에 들어가보면 node-app이 push된 것을 확인할 수 있다
Test
- 모든 컨테이너 정지 및 삭제(로컬에서)
docker stop $(docker ps -q)
docker rm $(docker ps -aq)
노드 이미지를 지우기 전에 자식을 먼저 지우는 것을 잊지 말자!
- 모든 도커 이미지 삭제
docker rmi us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/node-app:0.2
docker rmi node:lts
docker rmi -f $(docker images -aq) # remove remaining images
docker images
텅텅 비었다
REPOSITORY TAG IMAGE ID CREATED SIZE
- 이미지 pull하기
docker pull us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/node-app:0.2
docker run -p 4000:80 -d us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/node-app:0.2
curl http://localhost:4000
(Command Output)
Welcome to Cloud
출처 : Google Kubernetes Study Jam
저작권 문제 시 바로 삭제하겠습니다.
'클라우드 > Kubernetes in Google' 카테고리의 다른 글
쿠버네티스 2주차) Lab#2 : Orchestrating the Cloud with Kubernetes (0) | 2023.04.29 |
---|---|
쿠버네티스 2주차) Lab#2 : Kubernetes Engine: Qwik Start (0) | 2023.04.29 |