새소식

ML Development/Docker | k8s - 2022.07.11

[QWIKLABS] GCP에서 Docker 사용하기

  • -

Docker 간단하게 실행해보기


Cloud Shell 기본 명령어

gcloud auth list -> active 계정 이름 확인
gcloud config list project -> 프로젝트 ID 확인

Docker 파일 실행해보기

  • hello-world라는 container 실행
docker run hello-world
  • 코드 실행 과정
    1. 도커 daemon이 hello-world라는 image를 로컬에서 확인
    2. image가 없다면 Docker Hub라는 public registry에서 다운로드하여 사용
  • 현재 사용 가능한 도커 images 확인
    • 사용 가능하려면 도커 이미지가 built 돼야 함
docker images
  • 현재 실행 중인 container 확인 하기
docker ps
  • 현재는 안 쓰고 기존에 사용했던 containers까지 확인하기
docker ps -a

->
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
a2eaebdcdd00   hello-world   "/hello"   9 minutes ago   Exited (0) 9 minutes ago             amazing_heyrovsky
  • 이때, docker run 실행 시 container의 이름은 임의로 할당
    • docker run --name container-name hello-world 사용하면 이름 할당 가능

 

Docker Image 구성하기


Dockerfile 만들기

  • FROM node:lts : base parent image로 lts(long term support) 선택
  • WORKDIR /app : container 작업 폴더 선택
  • ADD . /app : container의 컨텐츠 설정
  • EXPOSE 80 : 80 포트 개방
  • CMD ["node", "app.js"] : container가 실행 될 때 node를 통해 app.js 실행
cat > Dockerfile <<EOF
# Use an official Node runtime as the parent image
FROM node:lts
# Set the working directory in the container to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Make the container's port 80 available to the outside world
EXPOSE 80
# Run app.js using node when the container launches
CMD ["node", "app.js"]
EOF

Node application 생성

  • 80 포트 개방한 HTTP 서버
  • 서버 응답 요청에 Hello World를 반환함
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

Image Build

  • . : 현재 위치 정보
  • -t : 이름 및 태그 지정
    • -t node-app:0.1
      • node-app : 이름
      • 0.1 : 태그(버전 정보)
docker build -t node-app:0.1 .
  • 설정한 Dockerfile과 Node Application 정보가 반영됨
Step 2/5 : WORKDIR /app
 ---> Running in b4507deeca58
Removing intermediate container b4507deeca58
 ---> c336ae1a770e
Step 3/5 : ADD . /app
 ---> e7b43644db9e
Step 4/5 : EXPOSE 80
 ---> Running in 2d040b7fc3c3
Removing intermediate container 2d040b7fc3c3
 ---> e460aff02083
Step 5/5 : CMD ["node", "app.js"]
 ---> Running in 409a5c51726d
Removing intermediate container 409a5c51726d
 ---> fb0551fb9752
Successfully built fb0551fb9752
Successfully tagged node-app:0.1

 

Run 이해하기


  • --name : container 이름 지정
  • -p : 포트 포워딩
    • 도커의 80 포트에 접근할 포트(4000)
    • http://localhost:4000 에 생성된 서버로 접근 가능
    • session이 실행 중인 경우만 사용 가능 → background 실행하려면 별도의 옵션 필요
docker run -p 4000:80 --name my-app node-app:0.1
  • localhost:4000 서버와 통신하기
curl <http://localhost:4000>


Hello World # app.js에서 설정한 res가 출력 됨
  • container 사용 중지 및 삭제
docker stop my-app && docker rm my-app
  • -d : background 실행
docker run -p 4000:80 --name my-app -d node-app:0.1
docker ps
  • 로그 확인
docker logs container_id

 

Image 변경 하기


  • 생성한 app.js와 Dockerfile을 변경해 image를 변경 가능
  • 변경 후 다시 build 해서 node-app:0.2를 생성
docker build -t node-app:0.2 .
  • Step 2에서 처럼 변경 사항이 없는 경우 cache를 활용하여 실행 시간을 단축 시킴
Step 1/5 : FROM node:lts
 ---> e6b2a509415b
Step 2/5 : WORKDIR /app
 ---> Using cache
 ---> f6abaccb9891
Step 3/5 : ADD . /app
 ---> dfd51c48a448
Step 4/5 : EXPOSE 80
 ---> Running in 06db9ad462de
Removing intermediate container 06db9ad462de
 ---> c342b8fabeaa
Step 5/5 : CMD ["node", "app.js"]
 ---> Running in 7ec7d519578a
Removing intermediate container 7ec7d519578a
 ---> cd70c2529b93
Successfully built cd70c2529b93
Successfully tagged node-app:0.2

 

Debug


log

  • -f : log를 계속 출력
  • docker logs -f container_id

exec

  • 실행 중인 container를 session에서 접근하기
    • -it : pseudo-tty(커맨드) 할당 → 디버그 가능
docker exec -it container_id bash

inspect

  • docker inspect container_id
    • JSON 형식으로 반환
[
    {
        "Id": "xxxxxxxxxxxx....",
        "Created": "2017-08-07T22:57:49.261726726Z",
        "Path": "node",
        "Args": [
            "app.js"
        ],
...
  • --format : JSON에서 특정 필드 선택해 반환 가능
    • IPAddress만 반환
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_id

 

Publish


  • GCR에 image push 후 pull 하기
  • 이때, format은 다음과 같이 설정해야 함
    • [hostname]/[project-id]/[image]:[tag]
      •  project-id는 gcloud config list project 를 통해서 확인 가능
  • container publish 진행
docker tag node-app:0.2 gcr.io/project-id/node-app:0.2
  • docker images
    • gcr.io/[project-id]/node-app 가 추가 됨
REPOSITORY                      TAG         IMAGE ID          CREATED
node-app                        0.2         76b3beef845e      22 hours ago
gcr.io/[project-id]/node-app    0.2         76b3beef845e      22 hours ago
node-app                        0.1         f166cd2a9f10      26 hours ago
node                            lts         5a767079e3df      7 days ago
hello-world                     latest      1815c82652c0      7 weeks ago
  • push image
    • GCP의 Container Registry에 저장 됨!
docker push gcr.io/[project-id]/node-app:0.2

  • pull 기능을 확인하기 위해서 모든 기존 container를 실행 중단하고 삭제하기
docker stop $(docker ps -q) # 중지
docker rm $(docker ps -aq) # 삭제
  • image도 삭제하기
    • node:lts 와 child의 image를 삭제해야 함
    • rmi : image 삭제
docker rmi node-app:0.2 gcr.io/[project-id]/node-app node-app:0.1
docker rmi node:lts
docker rmi $(docker images -aq) # remove remaining images
docker images # 실행 결과 아무 image도 없음
  • Container Registry에 저장된 이미지 pull하여 실행해보기
docker pull gcr.io/[project-id]/node-app:0.2 # pull
docker run -p 4000:80 -d gcr.io/[project-id]/node-app:0.2
  • curl로 확인
curl <http://localhost:4000>
Hello World!
Contents

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

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