개요

이전 포스팅에서 이미지, 컨테이너에 대한 개념과 생성하는 방법을 살펴봤습니다. 이번 포스팅에선 좀 더 실용적으로 이미지와 컨테이너를 관리하는 방법에 대해 살펴보겠습니다(도커 명령어를 이용해 실습한다고 보면 됩니다).

도커에서 사용하는 모든 명령어는 --help 옵션을 통해 사용 가능한 옵션을 조회할 수 있습니다. 모든 명령어의 모든 옵션을 외울 수 없겠지만, 위 명령어를 통해 도움을 받고 자주 사용되는 옵션을 기억해두면 좋습니다.

지금부터 살펴볼 내용은 크게 다음과 같습니다.

  • Images
    • tag (named)
      • -t, docker tag _
    • list
      • docker images
    • analyze
      • docker image inspect
    • remove
      • docker rmi, docker prune
  • Containers
    • name
      • --name
    • configured in detail
      • --help
    • list
      • docker ps
    • remove
      • docker rm

Stopping & Restarting Container

먼저 두 가지 명령어를 살펴보겠습니다.
docker psdocker ps -a 입니다.


각각의 명령어에 대한 사진입니다. docker ps는 현재 실행중인 컨테이너의 리스트를 보여주며, docker ps -a는 종료된 컨테이너를 포함하여 모든 컨테이너를 보여줍니다.

docker ps --help 명령어를 입력하면 모든 옵션을 확인할 수 있습니다.

docker run 명령어는 새로운 컨테이너를 생성하고 실행하는 명령어 입니다. 만약 중지된 컨테이너를 재시작 하고 싶다면 docker start ${container_name} 을 사용합니다. docker ps -a 명령어의 결과를 확인해보면 컨테이너의 이름을 확인할 수 있습니다.

Understanding Attached and Detached Containers

docker start 명령어로 컨테이너를 재실행하면 docker run 명령어와 달리 명령 프롬프트창이 바로 다음 라인에서 입력을 받는걸 볼 수 있습니다. 즉, 컨테이너와 관련된 로그등의 정보는 명령창에 표시되지 않죠. 물론 컨테이너는 분명히 실행되어 있습니다.

docker run -p 8000:80 {image name} 하지만 이런식의 명령어로 하나의 컨테이너를 더 실행하면 터미널이 블로킹됩니다. 이런 현상이 나오는 이유는 실행 모드의 차이때문이며 attached mode, detached mode로 나뉩니다.

docker start 로 실행하는 경우 detached mode가 디폴트값이며, docker run 을 사용하는 경우 attached mode가 디폴트 값입니다.

두 모드는 사용자의 니즈에 따라 조절하며 사용할 수 있습니다. attached는 쉽게 말해 해당 컨테이너의 output을 터미널로 듣고 있겠다는 뜻입니다. 예를 들어 console 출력 등이죠.

만약 output을 확인하고 있을 필요가 없다면 detached mode를 사용하면 됩니다. docker run -p 8000:80 -d {image} 이렇게 -d 옵션을 주어 실행하면 detached mode로 실행하게 됩니다. 더이상 콘솔창이 컨테이너의 아웃풋을 추적하지 않죠.

docker attach {container_name} 명령어를 이용하면 해당 컨테이너에 대해 콘솔창이 다시 attached mode가 됩니다.

또 유용한 명령어로 docker logs {container_name} 명령어도 사용할 수 있습니다. 지금까지 찍혔던 컨테이너의 로그를 확인할 수 있습니다.

docker logs -f {container_name} 처럼 -f 테그를 달면 attached mode 처럼 과거의 로그를 보여준 후 다시 커테이너의 로그를 추적합니다.

Entering Interactive Mode

콘솔에 input입력이 필요한 경우 단순히 docker run 명령어를 사용하면 오류가 발생할 수 있습니다. 이런 경우 interactive mode가 필요합니다. 단순히 attached mode로 컨테이너의 아웃풋만 확인하는 것이 아니라, 콘솔을 이용해 컨테이너와 상호작용 해야 하는 것이죠. -i-t 를 이용하여 터미널로 인풋을 넣을 수 있습니다.

docker run -it {image_name} 명령어를 사용하면 콘솔을 이용한 interactive mode로 컨테이너를 실행할 수 있습니다. 이제 output뿐만 아니라 input을 콘솔로 넣어줄 수 있습니다.

정지한 컨테이너를 재실행할때도 docker start -a -i {container_name} 명령어를 통해 interactive mode를 사용할 수 있습니다. -t 옵션을 사용하지 않는 이유는 run 실행에서 -t 를 사용했다면 메모라이즈 하고 있기 때문입니다.

이렇듯 필요에 따라 모드들을 조절하며 사용하면 됩니다.

Deleting Images & Containers

deleting containers

지금까지 프로세스를 잘 따라했다면, docker ps -a 명령어를 실행하면 더이상 필요 없는 컨테이너가 많이 있을 겁니다.

docker rm {container_name} 명령어를 사용하면 컨테이너를 지울 수 있습니다. 물론 이 명령어는 실행중인 컨테이너에 사용할 수 없으며, docker stop {container_name} 으로 컨테이너를 중지하고 사용해야 합니다.

하지만 이 방법은 문제가 있는데, 모든 컨테이너를 삭제하기 위해 이름을 모두 넣어줘야 한다는 점입니다.
docker rm {container_name1} {container_name2} ...

당연히 위 방법은 효과적이지 못합니다. 이미지에 대한 내용을 살펴본 후 모든 컨테이너를 지우는 효과적인 방법을 살펴보겠습니다.

deleting images

docker images 명령어를 사용하면 모든 이미지를 볼 수 있습니다. 특정 이미지를 삭제하기 위해선 docker rmi {image_id} 명령어를 사용합니다. 컨테이너의 rm 명령어와 비슷하게 사용하면 됩니다.

이미지를 사용하기 위해선 이미지를 사용중인 컨테이너가 없어야 합니다. 중지된 컨테이너라도 마찬가지죠. 따라서 이미지를 삭제하기전 해당 이미지를 사용하는 컨테이너를 먼저 삭제 해야 합니다.

docker image prune -a 명령어를 사용하면 사용하는 컨테이너가 없는 모든 이미지를 제거합니다.

Removing Stopped Containers Automatically

--rm 옵션을 사용하면 컨테이너가 중지되는 경우 자동으로 해당 컨테이너를 제거해줍니다. docker run -p 3000:80 -d --rm {image} 이런식으로 --rm 옵션이 들어가도록 컨테이너를 실행하면, docker stop {container} 등을 통해 컨테이너를 지우는 경우 컨테이너가 자동으로 삭제됩니다. docker ps -a 를 이용해 확인해보면 컨테이너가 중지되고 자동으로 지워진 것을 확인할 수 있습니다.

물론 재실행이 반드시 필요하다면 이 옵션을 사용해선 안됩니다. 재실행이 필요없는 경우 컨테이너 관리에 매우 효과적일 수 있습니다.

Inspecting Images

이미지는 코드와 실행환경을 포함하고 있습니다. 따라서 많은 레이어가 존재하고 크기가 거대하죠. docker image inspect {image_id} 명령어를 사용하면 이미지 자체에 대한 정보를 확인할 수 있습니다.

size, Os, Containers, Metadata, layers 등 이미지에 포함된 다양한 정보들에 대해 확인할 수 있습니다.

Copying Files Into & From A Container

컨테이너에 파일을 복사하거나 컨테이너로부터 파일을 복사하여 가져올 수 있습니다. 로컬폴더에 특정 파일을 생성한 후 docker cp {src(local_folder or file)} {dest(container folder)} 명령어를 사용하면 실행중인 컨테이너의 폴더로 로컬 폴더의 파일 또는 폴더를 복사하여 넣어줄 수 있습니다.

cp 명령어의 src, dest 를 반대로 해주면, 실행중인 컨테이너의 파일이나 폴더를 로컬로 가져오는 것도 가능합니다. docker cp {src(container folder)} {dest(local_folder or file)} 이런 식으로 명령어를 사용하면 됩니다.

컨테이너나 이미지를 재실행하지 않아도 컨테이너와 특정 파일과 폴더를 주고 받을 수 있는 것이죠.

Naming & Tagging Containers and Images

지금까지 이미지를 imageId를 이용해 구별했습니다. 컨테이너를 사용할때도 자동으로 만들어지는 이름을 이용했죠. 이미지나 컨테이너에 네이밍이나 태깅을 사용하여 구별할 수 있습니다.

컨테이너 먼저 살펴봅시다. --name string 옵션을 사용하면 컨테이너에 특정 이름을 부여할 수 있습니다. docker run -p 3000:80 -d --rm --name goalsapp {image} 등의 명령어를 사용하면 생성되는 컨테이너에 'goalsapp' 이라는 이름이 부여됩니다. 다양한 명령어를 컨테이너의 이름을 이용해 적용할 수 있죠.

이미지도 비슷한 개념을 적용할 수 있습니다. 이미지에서는 이를 tag라고 부릅니다. tag는 크게 2가지 파트로 구별됩니다.
<name> : <tag> 의 형태인데요. 이미지의 이름과 버전을 구별할 수 있도록 하는 것입니다. node:14 이런 경우는 node의 14버전을 의미하는 것이죠. 도커허브에 올라온 node 베이스 이미지의 태그를 살펴보면 정말 많은 태그가 존재합니다.

만약 특정 태그를 부여하지 않는다면, 'latest'가 적용됩니다. 이미지는 수 많은 레이어의 집합이므로, 같은 이미지여도 다른 레이어그룹을 가진 이미지가 존재할 수 있고, 이를 이름과 버젼으로 구별하는 것이죠.

그럼 어떻게 이미지에 태그를 부여할까요? -t 옵션을 이용하면 가능합니다. docker build -t goals:12 . 등의 명령어를 사용하면 이미지에 태그가 부여됩니다. 컨테이너가 해당 이미지를 사용하려면 이미지의 태그를 사용하면 됩니다.

docker run -p 3000:80 -d --rm --name goalsapp goals:12 등으로 사용하는 것이죠.

Pushing Images to DockerHub

도커를 사용하는 큰 장점은 이미지만 있으면 이를 이용해 컨테이너를 생성할 수 있다는 것입니다. 즉, 컨테이너 자체를 공유할 필요 없이 이미지만 공유하면 어플리케이션과 실행환경을 공유할 수 있는 것이죠.

그리고 우리는 Docker Hub을 통해 여러 이미지를 공유할 수 있었습니다. 이미지를 다운 받을 필요도 없이 docker run image 명령어를 사용하면 도커허브에서 자동으로 해당 이미지를 다운받아 사용할 수 있었죠.

우리가 build를 통해 만든 이미지도 마찬가지로 도커허브에 올려 다른사람과 공유할 수 있습니다. 물론 도커허브에 가입이 되어있어야 합니다(free account도 괜찮습니다).

이후 repository를 도커허브에 생성합니다. 생성시 repository name을 원하는 대로 작성하고 생성하면 됩니다. 이후 public, private 정책을 통해 개인이 쓸지, 모두와 공유할지 선택합니다.

이제 docker push 명령어를 이용해 해당 이미지를 도커허브에 올릴 수 있습니다. 또한 docker pull을 통해 필요한 이미지를 도커허브에서 가져올 수 있죠.

업로드하는 경우 docker push repositoryName:imageTag 명령어를 사용합니다. docker push academind/node-hello-world:node-demo 등의 명령어를 사용하는 것이죠. 이렇게 하면 academind/node-hello-world 레포지토리에 해당 이미지를 공유할 수 있습니다.

물론 로컬 이미지명과 도커허브의 이미지명을 동일하게 맞추면(node-hello-world 등) 별도의 이미지태그가 필요하지 않겠죠. 물론 위에서 살펴본 것 처럼 여러 태그를 붙여가며 여러 버전을 생성할수도 있습니다.

Pulling & Using Shared Images

docker pull repositoryName 을 사용하면 도커허브의 레포지토리에 올라온 이미지를 당겨올 수 있습니다. 이후 docker run 명령어를 이용해 해당 이미지로 컨테이너를 실행할 수 있죠.

물론 도커허브는 이 외에도 배포를 위한 기능을 제공하지만 핵심 기능은 image의 push/pull을 통해 공유가 가능하다는 것 입니다.

게다가 로컬에 해당 이미지가 없어도 pull없이 docker run 명령어를 실행하면 도커는 이미지가 로컬에 없는 경우 자동으로 도커허브를 체크하고 이미지를 자동으로 pull 하여 사용합니다.

만약 이미지가 로컬에 있는 경우 도커허브의 이미지가 업데이트 되어도 자동으로 체크하지 않습니다. 따라서 최신 버전을 사용하고 싶다면 도커허브에서 다시 이미지를 pull해야 합니다.

출처

profile
웹 개발을 공부하고 있는 윤석주입니다.

0개의 댓글