Docker-Utility Containers

유틸리티 컨테이너
유틸리티 컨테이너란?
유틸리티 컨테이너는 애플리케이션이 담긴 컨테이너가 아니라 특정 환경만 포함하는 컨테이너를 의미한다. 예를 들면 NodeJS환경이나 PHP환경같은 것을 말하는 것이다.
왜 사용하는가?
기본적으로 호스트 머신에 환경을 구축하지 않고 이를 도커를 통해 사용하기 위해서 이용한다.
컨테이너에서 명령을 실행하는 다양한 방법
docker run node를 터미널에서 입력하면 컨테이너가 그대로 죽는다. interactive모드로 실행해야 정상 작동하기 때문이다.
docker run -it node 로 실행하면 터미널에서 interactive모드로 노드 컨테이너를 돌려서 실행할 수 있지만 우리가 원하는 건 detached모드에서(백그라운드에서 실행하면서) 컨테이너가 죽지 않게 하는 것이다. 이것은 간단하게
docker run -it -d node
-d옵션 하나만 더 붙여줘도 가능하다.
이를 실행하고 docker ps를 통해 실행중인 컨테이너를 확인하면
docker ps ─╯
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4551887165c2 node "docker-entrypoint.s…" 4 seconds ago Up 3 seconds eager_dubinsky
이런식으로 컨테이너가 생성된 것을 볼 수 있다.
그런데 이제 위에 만들어둔 컨테이너 내에 npm init이든, 뭐든 컨테이너 내부에 명령을 실행하고 싶을 수 있다. 그런데 이제 interactive모드에서 직접 터미널에서 바로 명령을 주는 것이 아니라, 저렇게 백그라운드에서 둔 상태로.
이를 위해 docker exec 명령어를 쓸 수 있다.
docker exec는 아까 말한 바와 같이 컨테이너에 특정 명령어를 실행할 수 있게 한다.
아까 docker run node는 -it 옵션을 붙여서 실행해야했으므로 마찬가지로
docker exec -it node_container_name npm init
을 실행하면 패키지에 대해 입력을 받는 부분들이 나오고 컨테이너에 패키지가 설치된다. 이러면 호스트 머신에 이들을 설치하지 않아도 환경을 만들 수 있다.
유틸리티 컨테이너 구축하기
만약 아래와 같은 도커파일을 작성했을 때
FROM node:14-alpine
WORKDIR /app
아래에 CMB npm init을 한 줄 더 적어줄 수도 있지만 init명령만 실행하는 것보다 유연하게 만들고자 한다.
그래서 도커파일은 위 상태 그대로 놔두고 이미지를 빌드해준 후 아까 했던대로 npm init명령어를 컨테이너에서 실행하고자 한다.
그런데 여기서 명령어는 컨테이너 내부에서만 돌기 때문에 이를 호스트 머신에서 관측하기 위해 미러링을 하려고 하는데, 이건 바인드 마운트를 이용해줄 수 있다.
docker run -it -v /home/max/devops/study_docker/section7:/app node-util npm init
와 같이 실행해주면 호스트 머신에도 package.json(컨테이너의 npm init 옵션에서 사용한 것들이) 생성된다.
ENTRYPOINT
ENTRYPOINT는 CMD와 외관상 유사해보이는 명령인데, 작동 방식은 조금 다르다.
CMD명령의 경우 CMD를 도커파일에 지정해놓아도 위에서 실행한 npm install명령을 실행해주면 도커파일에 있는 것을 덮어씌우고 진행되지만,
ENTRYPOINT의 경우 덮어씌우는 것이 아니라 그 뒤에 들어가게 된다. 그러니까
FROM node:14-alpine
WORKDIR /app
ENTRYPOINT ["npm"]
의 도커파일로 이미지를 빌드했다면
docker run -it -v /home/max/devops/study_docker/section7:/app node-util npm init
이렇게 init만 붙여도 되는 것이다.
마찬가지로
docker run -it -v /home/max/devops/study_docker/section7:/app node-util npm install express --save
도 같은 방식으로 실행해줄 수 있다.
Docker Compose 사용하기
도커파일이 하나이지만 도커 컴포즈를 여기서도 유용하게 사용할 수 있다.
version: "3.8"
services:
npm:
build: ./
stdin_open: true
tty: true
volumes:
- ./:/app
아까 엔트리포인트를 사용한 도커파일을 둔 디렉토리에 이런 식으로 도커 컴포즈 파일을 작성했을 때
단순히 docker compose up을 하게 되면 ENTRYPOINT ["npm"]밖에 없기 때문에 npm init이라든가 그 이후의 명령은 바로 실행되지 않는다.
그래서 사용할 수 있는 것이 docker compose run인데,
docker compose run npm init
을 실행해주면 우리가 원하는대로 npm init을 돌려줄 수 있다. 여기서 npm은 컴포즈 파일의 서비스 이름에서 온 것이고, init은 엔트리 포인트 이후의 명령이다.
그런데 docker compose run은 docker compose up과 다르게 docker compose down에 대응하는 것이 없다. 기본적으로 컨테이너가 시작되어 명령이 완료되면 종료되지만, 자동으로 제거되지는 않는다.
docker compose run --rm으로 --rm을 달아주면 종료될 시 자동으로 제거되게 할 수 있다.

