[docker] part 4. docker compose!!

Minyoung kim·2024년 12월 7일
0

devops

목록 보기
5/6

Docker Compose

redis, mysql, python web server 등등을 사용하는 하나의 복잡한 어플리케이션이 있다고 가정해보겠습니다. 보통의 웹 어플리케이션의 경우 이와 같이 여러개의 이미지를 사용할 수 밖에 없을 것입니다.
이럴 때는 물론 여러개의 image를 모두 docker run을 통해 실행하고 연결해줄 수 있지만, 그것 보다는 docker compose를 사용하는 것이 좋습니다.

docker compose는 하나의 단일 서버에서 여러개의 도커 컨테이너를 하나의 서비스로 정의해 컨테이너의 묶음으로 관리할 수 있는 작업환경을 제공하는 도구라고 볼 수 있습니다.
docker compose는 yaml형식의 구성 파일 안에 서비스를 실행하기 위한 다양한 옵션들을 조합해 저장하기 때문에, 실행하고 유지하는 것이 훨씬 수월합니다. 또한 조합된 여러개의 컨테이너는 하나의 도커 호스트에서만 실행될 수 있습니다.

도커 컴포즈는 기본적으로 설치되지 않기 때문에 도커 호스트를 설치할 때 도커 컴포즈를 같이 설치해줘야 합니다.

예시

조금 더 복잡한 웹 어플리케이션을 예시로 들어보겠습니다. 개와 고양이 중 더 좋아하는 것에 투표하는 웹사이트가 있다고 가정해보겠습니다. 이 웹 어플리케이션에는 사용자에게 투표를 받는 인터페이스인 voting-app이 있고 python으로 작성되어 있습니다. 그리고 이 것을 저장하는 in-memory 형식의 db인 redis가 있습니다. 그리고 이 것을 영구 스토리지에 업데이트 하는 worker라는.net으로 작성된 어플리케이션이 있습니다. 여기서 사용하는 영구 스토리지로 postgresql이 있고, 이 투표 결과를 보여주는 node.js로 작성된 인터페이스가 있습니다.

정리하자면 다음과 같습니다.

  • voting-app(python)
  • in-memeory db(redis)
  • worker(.net)
  • db(postgresql)
  • result-app(node.js)

그냥 실행하기

먼저,이 각각의 서비스들을 도커 호스트에서 실행하고자 하는 경우를 생각해보겠습니다.

docekr run -d --name=redis redis
docker run -d --name=db postres
docker run -d --name=vote -p 5000:80 voting-app
docker run -d --name=result -p 5001:80 result-app
docekr run -d --name=worker worker

그리고 이 때 voting-app에서는 redis를 사용하게 되는데, 단순히 docker run만 해주면 voting-app에서 redis를 어디서 찾아 사용해야힐지 모를 것입니다. 이 때 컨테이너를 link해줘야 합니다.

docker run -d --name=vote -p 5000:80 --link redis:redis voting-app

위와 같이 작성해줄 수 있습니다. redis:redis중 첫번째 redis는 voting-app에서 사용하는 redis의 host 이름입니다. 그리고 두번째 redis는 도커 호스트에서 실행중인 redis 컨테이너의 이름입니다. 따라서 컨테이너를 실행시킬 때 이름을 적절히 지정해주는 것이 중요합니다.

마찬가지로 result-app에도 사용하는 db를 연결시켜줘야 합니다.

docker run -d --name=result -p 5001:80 --link db:db result-app

위와 같이 작성해줄 수 있습니다.

또한 worker에도 redis와 postgres를 모두 연결해줘야 합니다.

docekr run -d --name=worker --link db:db --link redis:redis worker

그러나 이러한 작성방법은 deprecated되어 docker에서 추후에는 지원하지 않을 것입니다.
docker swarm과 네트워킹을 통해 위 과정을 훨씬 수월하게 만들어줄 것입니다. 이는 추후 살펴보도록 하겠습니다.

docker compose로 실행하기

도커 컴포즈 파일을 작성하는 방법에는 여러가지 버전이 있습니다. 차례대로 살펴보겠습니다.

V1

redis : 
	image: redis
db :
	image : postgres:9.4
vote:
	image: voting-app
    ports:
      - 5000:80
    links:
      - redis
result:
	image: result-app
    ports:
      -5001:80
    links:
      - db 
     
worker:
	image: worker
    links:
      -db
      -redis

docker run을 통해 실행시킨 과정들을 docker 컴포즈 파일에 v1 버전으로 작성하면 위와 같습니다.
컨테이너 이름을 지정하고, 사용할 이미지, port mapping,link 정보들을 작성합니다.
link시에는 db:db라고 작성해주었던 것을 타켓 이름만 작성해줘도 알아서 타겟의 이름과 같은 이름의 링크를 생성하게 됩니다. 그리고 docekr-compose up을 실행하면 애플리케이션 스택 전체를 불러오게 됩니다.

위 docker compose 파일의 경우, redis와 postgres는 docker hub에서 빌드된 이미지를 실행시키지만, result-app, voting-app, worker의 경우 직접 build해 생성한 이미지입니다.
그러나 빌드된 이미지를 넣어주는 것 대신에 아래와 같이 이미지 빌드 옵션을 넣어줄 수도 있습니다.

vote:
	build: ./vote
    ports:
      - 5000:80
    links:
      - redis

vote 어플리케이션을 위한 소스코드와 이미지 빌드를 위한 도커 파일이 모두 vote 폴더에 들어있습니다. 위와 같이 작성해줄 경우, docker-compose up을 실행할 때 이미지를 구축하고 임시 이름을 붙인 다음 해당 이미지를 통해 지정한 옵션과 함께 컨테이너를 실행합니다.

V2

version : "2"
services: 
	redis : 
		image: redis
	db :
		image : postgres:9.4
	vote:
		image: voting-app
    	ports:
      	  - 5000:80
        depends_on:
          - redis
	result:
		build : ./result
    	ports:
      	  -5001:80
        depends_on:
          - db
	worker:
		image: worker
        depends_on:
          - redis
          - db

version 2부터는 도커 컴포즈 파일의 버전을 반드시 파일 가장 위에 작성해줘야 합니다.

version 2는 모든 실행할 서비스들을 services: 라는 항목 아래에 위치시켜 작성해야 합니다.

version1에서는 도커 컴포즈가 기본 브리지 네트워크에 실행하는 모든 컨테이너를 연결하고 링크를 사용해 컨테이너 간 연결을 활성화합니다.
version2 이상부터는 도커 컴포즈가 자동으로 애플리케이션 전용 브리지 네티워크를 생성하고, 이 새롭게 생성된 새 네트워크에 모든 컨테이너를 연결합니다. 또한 각자의 서비스 이름을 통해 컨테이너 간 연결이 활성화됩니다. 따라서 version 1과 같이 링크 옵션을 따로 지정해줄 필요가 없습니다.
또힌 vote나 result 등은 redis 혹은 db 컨테이너가 실행된 후에야 실행될 수 있습니다. 이러한 의존성을 depends_on 옵션을 통해 지정해줄 수 있습니다.

V3

version : "3"
services: 
	redis : 
		image: redis
        networks:
          - back-end
	db :
		image : postgres:9.4
        networks:
          - back-end        
	vote:
		build: ./vote
    	ports:
      	  - 5000:80
        networks:
          - back-end 
          - front-end
	result:
		build : ./result
    	ports:
      	  -5001:80
        networks:
          - back-end
          - front-end
	worker:
		image: worker
        networks:
          - back-end        
networks:
	front-end:
    back-end:

version 3는 가장 최신의 버전입니다. version 3부터는 docker swarm을 제공합니다. 또한 몇가지 옵션이 추가되고 제거되었습니다.

기존에는 기본 네트워크 브릿지에 여러 서비스들을 연결하여 사용했지만, 이번에는 예를 들어 voting-app과 result-app과 같은 사용자 인터페이스는 front network로 redis, db, woker와 같은 서비스는 backend 네트워크로 연결한다고 가정해보겠습니다. 이 경우 프론트엔드와 백엔드 두개의 네트워크가 존재합니다.

이 때 도커 컴포즈 파일의 하단에 사용하는 네트워크를 netwokrs 항목으로 나열해줍니다.
이제 여기서 나열해준 network 항목들을 서비스에 mapping해줍니다.

services 항목의 각 컨테이너 아래 networks property를 두고, 해당 컨테이너에서 사용할 네트워크들을 나열해줍니다. 위 예를 들어 redis와 db, worker는 backend- network만 사용하지만, voting-app과 result-app은 front와 backend 네트워크를 모두 사용하므로, 두가지를 모두 작성해줍니다.

실전!

docker-compose.yml 파일을 생성하고, version에 따라서 적절히 서비스 내용들을 작성해줍니다.

그리고 docker-compose up 명령어를 작성해줍니다. 별도의 파일 지정 없이 docker-compose up만 입력해줘도 docker-compose.yml 파일을 인식해, 이 파일을 바탕으로 모든 컨테이너들을 생성합니다. 그리고 이때 현재 위치해 있는 디렉토리의 이름은 프로젝트의 이름이 됩니다.

예를 들어 우리가 code라는 디렉토리에 있고, 여기에서 docker-compose up을 해주었다면
컨테이너 이름은 code_redis_1, code_db_1 등이 될 것입니다.

만약 version 2 이상을 사용한다면 기존에 존재하는 도커의 기본 네트워크를 사용하는 것이 아니라 해당 서비스 만을 위한 새로운 네트워크를 생성합니다. 따라서 생성되는 네트워크의 이름도 code_()가 됩니다. 만약 위에서 살펴본 예시와 같이 front와 backed 등의 별도의 네트워크를 지정해주지 않으면, code_defualt라는 이름의 네트워크를 생성하게 됩니다.

version : "3"
services: 
	redis : 
		image: redis
	db :
		image : postgres:9.4     
	vote:
		build: ./vote
    	ports:
      	  - 5000:80
	result:
		build : ./result
    	ports:
      	  -5001:80
	worker:
		image: worker     

만약 위와 같이 docker-compose file을 작성하고 up을 하면 error가 발생할 것입니다.
postgres에서는 컨테이너를 실행할 때 환경 변수로 database 연결에 사용할 user 이름과 비밀번호를 지정해주도록 요구하고 있는데, 이를 지정해주지 않아서 오류가 발생하게 됩니다.

db :
	image : postgres:9.4    
    environment:
    	POSTGRES_USER : postgres
    	POSTGRES_PASSWORD : postgres

이때 위와 같이 docker compose 파일에 enviornment property를 사용해 환경 변수를 지정해줄 수 있습니다.

0개의 댓글