이미지와 컨테이너

김장군·2022년 12월 5일
0

Docker

목록 보기
4/6

이미지는 코드와 코드를 돌리기 위한 여러 툴을 가지고 있습니다.

컨테이너는 이미지로 만들어진 인스턴스라 보시면 됩니다.

정리하자면 이미지는 클래스, 컨테이너는 인스턴스와 매치가 됩니다.


이미지를 가져오는 방법을 알아보겠습니다.

Docker Hub에 많은 이미지들이 있어요.

예를 들어 Node.JS 이미지는 아래 커맨드로 가져올 수 있습니다.

docker pull node

run 커맨드를 쓰면 Docker Hub에서 이미지의 newest 버전을 다운로드한 다음 컨테이너를 돌리게 됩니다.

docker run node

docker run node 입력해 보시면 아무 일도 없이 끝나요. 뭐가 어떻게 됐는지 알고 싶죠?

docker ps -a

-a, all 옵션을 준 ps 커맨드로 node 컨테이너가 어떻게 되어 있는지 볼 수 있어요.


docker run -it node

run 뒤에 it 옵션을 더하면 호스트에 interactive 세션이 만들어집니다.

이렇게 되면 컨테이너와 그 바깥에서 커뮤니케이션을 할 수가 있죠.

위 커맨드를 돌려 보시면 node 셸로 들어간다는 걸 알 수가 있습니다.


이제 우리만의 이미지를 만들어 봅시다.

Dockerfile을 만들어 주세요.

FROM

  • 다른 이미지를 가져옵니다.
  • 이를 베이스로 하여 customizing 할 수 있을 겁니다.

WORKDIR

  • Dockerfile 커맨드들을 어디에서 돌릴지 정해 줍니다.
  • 컨테이너의 루트 path 말고 다른 path를 정해 주시는 게 좋습니다.

COPY

  • 이미지에 첫 번째 인자로 주어진 파일들을 복사합니다.
  • 첫 번째 인자: 호스트 OS에서 컨테이너에 필요한 디렉터리 또는 파일들을 정합니다.
  • 두 번째 인자: 게스트 OS의 어디에 둘 것인지를 정합니다.
  • Dockerfile의 path를 베이스로 하는 상대경로를 써 주시면 됩니다.
  • 두 번째 인자에서는 /에는 파일을 두지 마시고 디렉터리를 하나 만들어서 쓰시는 게 좋아요. WORKDIR처럼요.

RUN

  • 이미지를 빌드할 때 이 커맨드를 돌립니다.

EXPOSE

  • 컨테이너의 어떤 포트를 열어 둘 것인지 정합니다.
  • 진짜로 포트를 여는 것은 아니며..! 그냥 docs 같은 느낌으로 쓰입니다.
  • 진짜로 컨테이너 포트를 열어 두고 싶다면 컨테이너를 만들 때 -p 옵션을 줘야 합니다.

CMD

  • 컨테이너가 주어진 커맨드를 돌립니다.
  • 예를 들어 노드 서버를 띄우고 싶은데 이러한 것들은 이미지가 아닌 컨테이너에서 해야 합니다.
  • 인자를 리스트 타입으로 입력하셔야 합니다.

이미지의 아키텍처

이미지는 레이어 베이스입니다.

이게 무슨 말이냐면 이미지를 빌드하거나 다시 빌드할 때

Dockerfile에 있는 코드 라인을 하나씩 보면서

새로운 코드 라인 또는 처음으로 바뀐 라인을 찾았으면 거기서부터

그 밑의 모든 라인들을 Docker가 (다시) 보게 됩니다.

코드 라인 하나하나를 레이어라 부르며, 그래서 이미지를 레이어 베이스 아키텍처로 되어 있다 합니다.

또한 한 번 빌드된 레이어들은 모두 캐시에 담깁니다.

Dockerfile을 바꾸지 않고 이미지를 다시 빌드하면

빌드가 정말 빠르게 이루어지는 것을 볼 수 있는데,

이것이 레이어들이 캐시에 담겨 있기 때문입니다.

어떤 이미지로 컨테이너를 돌리게 되면 컨테이너 레이어가 이미지 레이어 맨 위에 올라갑니다.

스택을 생각하시면 됩니다.

Dockerfile의 첫 번째 라인이 첫 번째 이미지 레이어가 되어 스택에 쌓이는 모습이요.


Attached, Detached 컨테이너

이미지가 바뀌지 않았다면 새 컨테이너를 만들지 않아도 됩니다.

Exited status인 컨테이너를 재시작할 수 있거든요.

docker start 컨테이너_ID 또는 이름

다만 run 커맨드와 start 커맨드의 결과가 같은 것은 아닙니다.

run 커맨드는 컨테이너를 foreground에서, start 커맨드는 컨테이너를 background에서 돌립니다.

Foreground에서 돌아가는 컨테이너를 attached 컨테이너,

background에서 돌아가는 컨테이너를 detached 컨테이너라 합니다.

하지만 이것은 그냥 커맨드마다 디폴트 세팅이 그렇게 되어 있는 것뿐이고요,

여러분이 바라는 세팅으로 돌릴 수 있습니다.

run 커맨드에 -d 옵션을 붙이거나 start 커맨드에 -a 옵션을 붙이면 됩니다.

docker attach 커맨드도 있는데 이것은 돌아가고 있는 detached 컨테이너랑 터미널을 이어 줍니다.

아니면 그냥 로그만 가져오면 된다! 할 때 docker logs 커맨드가 있습니다.

이거는 리얼타임으로 가져오는 건 아니고 컨테이너에서 프린트된 로그들을 모두 보여 줍니다.

아니면 docker logs에 -f, follow 옵션을 줘서 tracking할 수도 있고요.


Interactive 컨테이너

컨테이너에서 돌릴 애플리케이션에서 유저와 인터랙션을 할 수 있습니다.

docker run 커맨드에 -i, interactive 옵션을 주면 됩니다.

이 옵션을 주면 컨테이너와 인터랙션을 할 수 있습니다.

Attached 컨테이너든, detached 컨테이너든 상관없습니다.

여기에 -t, tty 옵션을 같이 주는 게 좋은데요, 인터랙션할 터미널을 만든다고 생각하시면 됩니다.

docker start 커맨드라면 -a, -i 옵션을 줘야 합니다. -ai로 줄일 수 있습니다.


이미지와 컨테이너 지우기

안 쓰는 컨테이너를 docker rm 커맨드로 지울 수 있습니다.

docker rm $1, $2, $n, ...

아니면 docker run 커맨드로 컨테이너를 돌릴 때 --rm 옵션을 넣어 주시면

컨테이너가 할 일을 끝냈을 때 알아서 없어집니다.

아, 이미지 리스트를 뽑고 싶을 때는 docker images 커맨드를 씁니다.

그리고 이미지를 지울 땐 docker rmi 커맨드를 씁니다.

다만 이미지를 지울 때는 이 이미지를 쓰고 있는 컨테이너가 없어야 합니다.

쓰지 않고 있는 이미지를 한 번에 지울 수 있는 docker image prune 커맨드도 있답니다.


이미지에는 코드와 애플리케이션 환경이 들어가 있죠.

만들어진 컨테이너의 사이즈는 그렇게 크지 않습니다.

이미지 위에 올라간 하나의 레이어일 뿐이거든요.


docker image inspect

docker image inspect 커맨드로 이미지를 디테일하게 살펴볼 수 있습니다.

중요하게 볼만한 것으로는..

  • 이미지의 full ID
  • 만들어진 날짜
  • 만들어질 컨테이너 구성(ExposedPorts, Env, Cmd에 있는 ENTRYPOINT 등)
  • DockerVersion
  • OS
  • RootFS에 있는 레이어

정도가 있습니다.

RootFS에 있는 레이어에는 Dockerfile에서 만들어진 레이어 말고도 여러 다른 레이어들이 있습니다.

예를 들면 FROM으로 가져오는 이미지 레이어들도 있어요.


컨테이너로, 또는 밖으로 파일 또는 폴더 복사

돌아가고 있는 컨테이너에 어떤 파일을 주거나, 컨테이너로부터 어떤 파일을 받을 수 있습니다.

docker cp 커맨드를 쓰세요, 파일 또는 폴더를 컨테이너 안이나 바깥으로 복사할 수 있습니다.


컨테이너, 이미지 이름 정하기

docker run --name 이름 컨테이너_ID

컨테이너는 위 커맨드와 같이 이름만 주면 끝입니다.

이미지에는 이름뿐만 아니라 태그가 있습니다, name:tag 꼴입니다.

예를 들면 node:14 또는 node:12처럼요.

이렇게 보시니 태그가 어떤 느낌인지 아시겠죠?

이미지의 이름은 이미지 그룹 같은 느낌이에요. node처럼요.

태그는 이미지 그룹 안에서 이 이미지의 버전 같이 쓰일 수 있습니다.

docker build -t or --tag name:tag

이미지 공유

이미지 공유를 위한 두 가지 방법을 알려 드릴게요.

  1. Dockerfile을 공유하세요.
    • Dockerfile과 디렉터리, 코드 파일들을 함께 공유해야 할 겁니다.
    • 이미지를 빌드해야 하죠.
  2. 이미지를 공유하세요.
    • 이미지를 받으면 바로 컨테이너를 돌릴 수 있습니다.
    • 빌드를 하지 않아도 됩니다.

이미지를 공유하기 위해 Docker Hub 또는 private registry를 쓰세요.

Docker Hub는 official Docker image registry입니다.

이미지 process, save, deploy 등에 쓰일 수 있는 여러 서비스들을 가지고 있습니다.

하지만 웬만하면 private registry를 많이 쓰게 될 거예요.

docker push IMAGE_NAME

docker pull IMAGE_NAME

Docker Hub에서 리포지터리 만들어 보시면 알겠지만 그냥 이미지입니다.

로컬에게 이미지가 Docker에서 만들어졌음을 알게 하려면,

이미지 이름을 여러분의 Docker 아이디/이미지 이름으로 바꿔 주시면 됩니다.

이를 위해 docker tag 커맨드를 써서 이름을 바꿔 봅시다.

커맨드 이름이 tag이긴 하지만 이름도 바꿀 수 있습니다, 심지어 태그를 안 줘도 돼요.

그리고 docker tag는 이름을 바꾼다기보다는 새 이름을 가진 똑같은 이미지를 복제하는 것입니다.

그리고 퍼블릭 리포지터리라고 하더라도 push 하는 것은 리밋이 걸려 있습니다.

이를 위해 docker login 커맨드로 로그인을 해야 합니다.

Push 하려고 하는 이미지의 Docker 아이디와 로그인한 이미지가 같아야 하죠.

데이터를 가져올 때는 로그인하지 않아도 되고요.

Priviate registry를 쓸 때는 push, pull 키워드와 IMAGE_NAME 사이에 registry에 대한 어드레스가 있어야 합니다.

그냥 쓰면 Docker Hub에 push, pull 하는 거예요.

docker run 커맨드로 정해 준 이미지가 로컬에 없으면 registry에서 이미지를 찾습니다.

로컬에 이미지가 있다면 바로 돌리고 (업데이트 체크 안 함),

그렇지 않다면 registry에서 이미지를 찾는데 recently 버전을 씁니다.

profile
Make impacts!

0개의 댓글