Notice
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
01-09 20:47
Today
Total
관리 메뉴

그날그날 공부기록

Docker 기본 명령어 맛보기 본문

Docker&Kubernetes/Docker

Docker 기본 명령어 맛보기

given_dragon 2022. 7. 4. 12:49

쿠버네티스를 공부하기 전 도커를 간단하게 다루어 보았다.

로컬 환경이 아닌 GCP의 CE로 가상 머신을 만들어 진행하였다. 그래서 배포 역시 docker hub를 사용하지 않고 gcr을 사용한다.

 

도커는 애플리케이션을 개발, 배송, 및 실행하기 위한 개방형 플랫폼이다.

도커의 컨테이너화 기능을 통해 어디서든 도커만 설치되어 있다면 이미지를 업로드/다운로드하여서 실행할 수 있다.

이미지를 만들고, run명령어를 통해 이미지를 컨테이너화 하여 실행한다.

docker run hello-world

hello-world는 “Hello from Docker!”라는 문장을 반환하는 간단한 컨테이너이다.

명령어를 실행시키면 docker daemon은 해당 이미지를 로컬에서 검색하고, 없다면 Docker Hub라는 공용 저장소에서 이미지를 저장하고, 실행시킨다.

→ docker images 명령어를 통해 저장된 이미지들을 볼 수 있다.

docker ps

ps 명령어로 현재 실행중인 컨테이너를 확인할 수 있다.

실행이 종료된 컨테이너까지 확인하고 싶다면 -a 옵션을 추가하면 확인할 수 있다.

해당 명령어를 실행하면 도커에서 생성한 UUID와 실행에 대한 정보들이 표시된다.

컨테이너의 이름은 무작위로 생성되지만 다음 명령어로 이름을 지정할 수 있다.

docker run --name ${container-name} hello-world

빌드

이미 생성된 도커 이미지를 사용할 수도 있지만 직접 이미지를 생성할 수 있다.

다음과 같이 Dockerfile이라는 파일을 생성하였다.

# 노드를 사용한 예제이다. 부모 이미지로 노드의 lts버전을 사용한다.
FROM node:lts
# 컨테이너의 작업 디렉토리를 /app으로 설정한다.
WORKDIR /app
# 현재 디렉토리의 내용을 디렉토리의 /app으로 복사한다.  . -> /app
ADD . /app
# 컨테이너의 80번 포트를 외부와 연결할 수 있도록 개방한다.
EXPOSE 80
# 컨테이너가 실행될 때 노드를 사용하여 app.js를 실행한다.
CMD ["node", "app.js"]

다음과 같은 app.js라는 node 애플리케이션도 생성한다.

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();
});

두 파일을 모두 생성했다면 빌드 명령어를 입력한다.

docker build -t ${이미지명:이미지태그} ${빌드 콘텍스트}

docker build -t node-app:0.1 .

빌드 콘텍스트는 주로 현재 디렉터리(’ . ‘)를 사용하지만 필요시 다른 디렉터리를 지정할 수 있다.

-t 옵션으로 도커 이미지 이름을 지정할 수 있다.

-f ${Dockerfile 위치} 옵션을 사용해 다른 위치의 Dockerfile 사용이 가능하다.


실행

다음 명령어를 사용하여 빌드한 이미지를 실행한다.

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

—name 옵션은 컨테이너의 이름을 지정하는 데 사용된다.

-p는 호스트의 4000번 포트를 컨테이너의 포트 80번과 매핑한다.

이후 http://localhost:4000에 접속을 해보면 Hello World가 출력되는 것을 확인할 수 있다.

-d 옵션을 추가하면 컨테이너를 백그라운드에서 실행할 수 있다.

실행 전에 해당 컨테이너를 멈추고 삭제해야 한다.(같은 포트, 같은 이름 사용할 예정)

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

각각 적어주어도 무방

모든 컨테이너를 정지, 종료하려면 다음과 같이 입력한다.

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

컨테이너가 삭제된 후 -d옵션을 주어 다시 실행한다.

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

백그라운드에서 실행하였기 때문에 서버의 로그가 보이지 않는다.

로그를 보기 위해서는 docker ps 명령어로 컨테이너의 id를 알아낸 후 다음 명령어를 입력한다.

docker logs ${CONTAINER ID}

💡 여기서 컨테이너 id는 꼭 전부 다 입력할 필요는 없다. 일부분만 입력해도 일치하는 부분의 컨테이너가 유일하다면 알아서 인식한다!


노드 애플리케이션의 일부분을 다음과 같이 수정 후 실행해 보았다.

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

app.js를 변경 후 태그를 0.2로 변경하여 새로운 이미지를 생성한다.

docker build -t node-app:0.2 .

빌드시 나오는 로그를 보면 WORKDIR 까지는 기존 캐시 계층을 사용하는 것을 알 수 있다.

app.js를 변경하였기 때문에 ADD부터 변경이 진행된다.

새로운 이미지 역시 백그라운드로 실행한다.

docker run -p 8080:80 --name my-app2 -d node-app:0.2

호스트의 4000 포트는 이미 사용 중이므로 8080을 사용한다.

컨테이너의 80번 포트는 동일한데, 이는 두 개의 컨테이너가 서로 다른 컨테이너이기 때문에 겹치치 않는다.


디버그

실시간으로 컨테이너의 로그를 확인하려면 -f를 추가한다.

docker logs -f ${CONTAINER ID}

실행 중인 컨테이너의 셸을 실행하고 싶다면 docker exec를 사용한다.

-it는 pseudo-tty를 할당하고, 입력을 열린 상태로 유지하여 컨테이너와 상호작용 할 수 있도록 해준다.

docker exec -it ${CONTAINER ID} bash

<aside> 💡 TTY(teletypewriter) 리눅스 디바이스 드라이브 중에서 콘솔이나 터미널을 의미 pseudo terminal은 진짜 터미널이 아닌 유사(가짜) 터미널이다.

</aside>

셸 명령어를 사용할 수 있고 exit으로 종료할 수 있다.

컨테이너의 메타데이터를 확인하려면 docker inspect를 사용한다.

docker inspect ${CONTAINER ID}

컨테이너 id, 생성일 등 관련 정보가 json으로 주르륵 나온다.

-format을 사용하면 json에서 특정한 필드를 가져올 수 있다.

#ip를 가져온다.
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_id]

배포(GCR이용)

위에서 빌드한 이미지를 gcr에 푸시하고, 새로운 환경에서 이미지를 받아 실행할 수 있다.

gcr에서 호스팅 하는 비공개 저장소에 이미지를 푸시하려면 이미지 이름을 다음과 같이 설정해야 한다.

${HOST NAME}/${PROJECT ID}/${IMAGE}:${TAG}

💡 HOST NAME: gcr.io PROJECT ID: 현재 프로젝트 id IMAGE: 배포하려는 이미지 이름 TAG: 아무 문자열이나 가능. 없다면 default로 latest가 붙는다.

우선 프로젝트 id를 알기 위해 다음 명령어를 입력한다.

gcloud config list project

생성했던 node-app:0.2의 이미지/태그명을 변경한다.

docker tag node-app:0.2 gcr.io/${PROJECT ID}/node-app:0.2

docker image 명령어로 확인하여 이미지/태그명이 잘 변경되었다면 gcr에 이미지를 푸시한다.

docker push gcr.io/${PROJECT ID}/node-app:0.2

웹에서 이미지가 잘 올라갔는지 확인한다.

Container Registry로 들어가 확인하거나 http://gcr.io/${PROJECT ID}/node-app로 방문할 수 있다.

새 가상 머신을 실행하거나 현재 가상 머신의 모든 컨테이너/이미지를 삭제한다.

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

node:lts이미지를 삭제하기 위해서는 자식 이미지를 먼저 삭제해야 한다.

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) # 남아있는 모든 이미지를 지운다.
docker images

이미지를 다운받고, 실행한다.

docker pull gcr.io/${PROJECT ID}/node-app:0.2
docker run -p 4000:80 -d gcr.io/${PROJECT ID}/node-app:0.2

 

Comments