티스토리 뷰

반응형

이번 글은 기본이 부족해 삽질한 경험이 바탕이 되는 글입니다. 🥲

docker-compose에서 multiple commands를 사용하는 법에 대해 알아보겠습니다 😸


docker-compose 에서 multiple commands 가 왜 필요해 ?

아래와 같은 docker-compose 파일을 작성해 개발 중이었습니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script

위 docker-compose 파일에 대해 설명드리자면, docker registry에 등록된 이미지가 아닌 현재 directory의 Dockerfile을 빌드하고 특정 volume을 마운트해 구동됩니다. 해당 Dockerfile은 corretto jdk 이미지를 기본 이미지로 구성하고 있습니다.

 

 

그리고 저는 해당 docker-compose를 통한 docker 구동이 완료가 되면 특정 script를 시작해야만 했습니다. 즉 , start up script가 존재해 container가 구동될 때, 시작해야만 했습니다. 이 start up script는 volume으로 mount 한 디렉토리 중에 존재하는 상황이었습니다. 그리고 start up script를 시작한 후에 container가 종료되지 않고, bash script로 바로 동작하게 끔 구현하고 싶었습니다.

 

수행해야 할 프로세스가 따로 존재하지 않는 container image인 경우, container 구동을 완료하면 바로 종료되게 됩니다. 이를 멈추기 위해서 보통 '/bin/bash'를 구동시켜 bash를 동작하게 만듭니다. 그러면 bash가 종료되기 이전까지 container가 종료되지 않습니다. 즉, docker가 종료되지 않게 하려면 '/bin/bash'를 시작시켜야만 하고 결국엔 현재 상황에선 2개의 command (명령)을 수행해야하는 것입니다.

- 1. start up script 수행

- 2. /bin/bash 수행

 

 

보통 Container가 구동하고 바로 command를 실행하기 위해 아래와 같이 사용하고 있습니다.

- Dockerfile에서는 'CMD', 'ENTRYPOINT'를 활용합니다.

- docker-compose에서는 'command:', 'entrypoint:'에 명시해주면 됩니다.

 

근데 일반적으로 하나의 command 구문만 사용할 수 있습니다.

예를 들어 아래처럼 작성하면 오류가 납니다. 이 부분의 더 자세한 내용은 여기 공식문서를 참조해주세요.

당연히도 docker-compose인 경우에도 정상적으로 동작하지 않습니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command: sh some_script1.sh
        command: sh some_script2.sh

 

 

그렇기에 저와 같이 2개 이상의 command를 실행해야 하는 경우, 위와 같은 방법으로는 구동시킬 수 없습니다.

그러면 어떻게 해야하는 걸까요~?


docker-compose  multiple commands !

일단, 저는 docker-compose를 활용해 개발 중이었으므로 이 글에서는 docker-compose에서 multiple commands를 사용하는 법만 다루겠습니다. 하지만 docker-compose에서 하는 방법과 Dockerfile에서 하는 방법은 비슷하니 참고하시면 도움 될 것 같네요.

 

 

방법은 간단하면서 다양한 방법을 통해 구현할 수 있습니다. 하지만 핵심은 '&&'를 통해 명령어를 묶으면 됩니다.

 

너무 간단하지 않나요?😂  사실 CLI에서 command를 여러개 묶어 한 줄에서 수행할 때 '&&'를 사용하곤 하는데, 저는 docker file이라는 것에 시선과 생각이 묶여 이런 생각을 안하고 .... 계속 다른 방법이 있겠지 찾아 다녔습니다.

 

아무튼 아래와 같은 것이 '&&'를 통해 command를 한 번에 실행한 예라고 보면 될 것 같습니다.

이러한 방법을 사용해서 docker-compose에서 multiple commands를 사용하면 다음과 같이 작성하면 됩니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command: sh -c "/some_script1.sh && /some_script2.sh"

단순하죠 ?

 

 

단순하게 생각하면 아래처럼 작성하면 될 것 같은데..... 라는 생각이 안드시나요? ㅎㅎㅎㅎ 아래처럼은 작성하시면 안됩니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command: sh -c /some_script1.sh && /some_script2.sh

- 'sh -c'를 통해 실행되면서 뒤에 있는 것들은 모두 args(arguments) 취급 받게 됩니다. sh는 첫 번째 파일만 실행시키기 때문에 뒤에는 실행되지 않아 원하는 대로 동작하지 않습니다.


더 다양한 방법 !

앞서 말씀드린 것처럼 더 다양한 방법으로 작성할 수 있습니다.

 

아래 예들은 위 방법에서 줄 바꿈을 통해 다 간결하게 command를 볼 수 있도록 수정한 예 입니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command: >
            sh -c "
                /some_script1.sh && 
                /some_script2.sh
            "
version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command: sh -c "
            /some_script1.sh && 
            /some_script2.sh"
version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        command:
          - sh 
          - -c 
          - |
            /some_script1.sh
            /some_script2.sh

 

 

 

아래 예제는 entrypoint를 사용한 예입니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        entrypoint: ["sh", "-c"]
        command:
          - |
            /some_script1.sh
            /some_script2.sh

 

참고로 entrypoint(ENTRYPOINT)와 command(CMD)의 차이를 잘 모르시는 분들은 아래 블로그 글을 참조하시면 도움 될 것 같습니다 :)

 

Dockerfile Entrypoint 와 CMD의 올바른 사용 방법

ENTRYPOINT 와 CMD 는 무엇인가  ENTRYPOINT 와 CMD는 해당 컨테이너가 수행하게 될 실행 명령을 정의하는 선언문이다.  즉, 컨테이너가 무슨 일을 하는지 결정하는 최종 단계를 정의하는 명령이라고 생

bluese05.tistory.com

 

Dockerfile의 CMD와 ENTRYPOINT 차이. docker-compose.yml의 command

인트로 Docker를 처음 배우면서 Dockerfile을 작성할 때 CMD 와 ENTRYPOINT의 차이점을 잘 몰랐다. 사실은 Entry가 참가자 명단 뭐 그런 뜻이라는데 나는 뭔가 입구같은 느낌을 받아서, Container의 Working Direc.

senticoding.tistory.com

 

저는 맨 아래의 방법인 entrypoint와 command를 나눠 작성하는 것을 선호하는 편입니다.

그래서 맨 앞에서 언급한 제 문제를 해결하도록 docker-compose를 작성해보면 다음과 같습니다.

version: "3"
services:
    some_service:
    	container_name: some_service
        build: .
        volumes:
          - ~/some-data:/some-data
          - ~/some-info:/some-info
          - ~/some-script:/some-script
        entrypoint: ["/bin/bash","-c"]
        command:
          - |
            /some_start_up_script.sh
            /bin/bash

 

사람마다 차이가 있으니 여러 방법 중 제일 맘에 드는 방법을 사용해서 여러 문제들을 해결하셨으면 좋겠네요.

320x100
반응형
댓글
반응형
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함