본문 바로가기
IT/Docker & Kubernetes

Docker Compose

by 스마일엔지니어 2025. 1. 6.

-도커 컴포즈 (Docker Compose)

project = API server (인스타, 쇼핑몰 등..)

근데 이거 하나만으로 구동불가!! (위험성과 로드가 존재)

 

따라서, project는 Application의 조합이라 보면된다.

Backend Server DB Server
Front Server Cache Message (Storage)

 

네트워크의 경우 (Frontend-Backend-Cache, Backend-DB-Cache-Server-Message) 등 이렇게 묶는데

다양한 요구조건이 생성됨.

 

따라서, Docker Compose는 서비스의 조합(Network, Volume 포함),

서비스는 여러 개의 컨테이너 구성(서비스 ≠ 컨테이너)

 

-Yaml 파일 작성법 (docker compose, kubernetes, github ...)

JSON = { }  (거의 많이 사용해서 Yaml 파일과 호환, YAML 파일과 구조 유사 다만 작성법이 다름)

YAML   

XML =  (사용 많이 X)

 

-yaml 

Version : 3.6 or "3.6" (그 이후 버전에 대해 yaml 파일 적용하겠다. 이전은 허용 X - 일종의 주석이고 최신 버전을 적용)

name:  (프로젝트의 이름)

이름 -> 1. CLI 통해서 설정한 이름이 1순위 (-f 또는 -p로 설정한 이름)
             2. Yaml (docker-compose.yaml에 작되어 있는 이름)
             3. 디렉토리의 이름

---------------------------------------------------------------------------------------------------------------버젼과 이름은 옵션 (써도 안써도 무방)

services: (무조건 써줘야 함!!!)
    <service.name>:
                     <image>:  <repository>:<Tag>   또는 <repository>@digest
                     // 이미지는 필수값!! 이미지를 빌드하는 경우 빌드된 이미지의 이름
                   (로컬 스토리지에서 이미지 탐색을 하고 없다면 원격 레지스트리로 가서 검색한다.)

                                         container.name: --name 컨테이너 이름  
                                        (옵션, 굳이 필요하진 x 내가 몇 개의 컨테이너 쓸지 몰라서 / 컨테이너가 1개면 무조건 씀)
                                        ( 정의되지 않은 경우, (프로젝트이름_서비스이름_숫자(인덱스)) )

                                               export:  (같은 네트워크 안 다른 컨테이너들에게 포트 공개)
                                                  -80(숫자 표기) 
                                                  -"80" (문자열) 
                                                  -80-90 (범위 지정)  -> 리스트 형식으로 작성
                                              

                                               ports: (다른 네트워크 혹은 외부(호스트)에 포트 공개)
                                                  -[호스트의 포트]:[컨테이너의 포트]  // 나 또는 호스트가 접근할 포트(1명):앱이 이용하는 포트
                                                  -(뒤가 아닌 앞을 변경해줘야 함)

                                              entrypoint: (문자열이나 리스트형식으로 쓰이나 행동방식이 다름, 웬만하면 리스트로 작성)
                                              만약 값을 정의한 경우 (수정), 기존 CMD는 정의되어있다 하더라도 폐기되어버린다.
                                              -예를 들어 echo ep echo cmd 했을 때, ep echo cmd가 출력되지만, executable 부분을 echo co                                               mpose로 바꾸게 되면 그냥 compose 출력된다. echo cmd는 자동 폐기!

                                             command: 문자열이나 리스트로 표시 , 프로그램 구동을 위해 옵션을 주기에 엄청 쓰임!
                                             값을 정의한 경우 기존 CMD를 "대체", EP는 그대로 유지된다.
                                             *Null과 " " 차이를 아는 것이 중요!! Null은 값이 존재 X, " "는 값은 존재하나 빈 값임.

                                             environment: 환경 변수 정의 2가지 방법이 존재 (들여쓰기해서 dictionary 구조 혹은 list 형식)
                                                           key1 : value1 
                                                           key2 : value 2 (dict)
                                                         -----------------------------
                                                           key1 = value1
                                                           key2 = value2 (list)

                                             env-file: (string, 개별정의하는 environment 와 달리 대량으로 정의)
                                                       .env (list)

                                           *environment와 env-file 내 중복값이 나서 충돌할 경우 environment 정의된 게 1순위
                                           *env-file 내 값이 충돌하면 아래로 갈수록 우선순위가 높아짐!! (순차적이라고 생각하면 됨)

                                            pull-policy: 이미지를 가져오는 방식
                                            ((운영방식) 문제가 생겼을 경우 어떻게 처리할 것인지, 쿠버네티스에서도 사용!!)
                                                    -always : 실행할 때 마다 매번 가져온다
                                                    -never : 전혀 가져오지 않는다.
                                                    -missing : 없는 경우
                                                    -build : 제작
                                                    
                                           restart: 컨테이너가 종료되었을 때 내가 어떻게 행동하는가
                                                  -NO : 무슨 일이 있어도 실행 X
                                                  -Always : 제거하지 않는 이상 항상 재실행 (no랑 always가 젤 중요 & 많이 사용)
                                                  -On-failure : 문제가 생겼을 경우에만 재실행 (Exit Code 1 같은 거 나올 때)
                                                  -Unless-stopped : 명시적으로 종료/삭제 않았을 경우 재실행

                                          platform: 많이 안 쓰임.. 가끔 가다 사용

                                          build: 옵션 // 이미지를 제작해서 사용해야 하는 경우 쓰이는 단락
                                               context: .           ./src 혹은 src
                                               dockerfile: ./docker/dockerfile
                                                args: 
                                        (remind)  docker build -f <도커파일의 상대경로>   .(context, 도커파일 내 상대경로 해석)
                                                       --build-arg : ARG지시어 값 전달
                                         여기서 제작된 이미지의 이름이 위에 이미지 이름 (존재한다면 dangling, 그렇지 않으면 신규)



networks:

volumes:

config:

secret:

Volume

: 도커에서의 볼륨과 유사, 세부적으로 기능적인 차이 有

 

services:

   service_name:

        image: <repository>:<tag>

        volumes:

           - <Host local path>:<Container path>

           - <Volume name>:<Container path>

           - target: <Container path> (어디로 넣을 것인지)

           - source: <Host path> or <Volume key>

           - type: bind or volume

             docker run -v Name:path (volume)

             docker run -v host path: path (bind)

           - read-only: T/F boolean (RO 여부)

                                        .

                                        .

                                        .

 

(그리고 서비스와 같은 레벨 상에서 볼륨이 뭔지 정의해야 한다.)

 

Volumes:   volume_name: 컴포즈 사용되는 이름 (연두색 부분들은 optional, 라벨만 있어도 볼륨 생성되긴 함)       name: 생성시 사용할 이름 (문자열) -> 관리용도지 컴포즈에서 사용되는 네임은 아님!!

       external: 기존에 미리 생성한 볼륨을 사용하는 지 여부 (boolean -> true(1) / false(0) - 디폴트값, 볼륨생성 )

       labels: (도커 컴포즈보단 쿠버네티스에서 사용성 높음)

               - key = value

                         .

                         .

                         .

 

연습문제

 

master는 디폴트(rw)로 하고 slave에 ro 부여

 

master에 /root/vault/temp.txt에 master가 추가된 거 확인하고 마운트된 slave에도 똑같은 내용물 확인 가능하다.

하지만, slave에 ech 했을 때 read-only라는 오류가 뜨는 것을 확인할 수 있다.

 

 

마지막에 container:volume-external-slave-1:ro 즉, 컨테이너 주소로부터 공유됐기 때문에

cat을 했을 때 똑같이 master가 나오는 것을 확인할 수 있다.

그리고 공유된 slave는 ro이기 때문에 echo를 했을 때 read-only라는 오류가 떴음을 확인할 수 있다.

 

Network

구조 자체는 volume과 유사

 

Compose file advance - Anchor(&) , Alias(*)

1. 재사용 모듈의 이름은 prefix(x-) 사용해야 한다.

2. &의 경우 주소값이 되고 *는 호출이 된다.

3. <<: 를 사용하면 yaml 을 병합하는 형태로 사용하게 된다.

4. <<: 에 경우 충돌(중복)이 발생할 경우 최신에꺼가 덮어쓰기 한다. (병합되지 않음!!!!!)

-> 병합이 안 일어나고 전에 꺼가 삭제되기 때문에 다시 한번 더 명시해주는 것이 좋다.

 

Frontend의 경우 &common과 image와 environment가 중복되기 때문에

Frontend는 nginx:latest 그리고 environment는 FOO:VAR, Stage:dev, k1:23(*v1) 만 남게 된다.

만약에 common에 있는 것도 가져오고 싶다면,

k1:*v1, k2:v2, FOO:VAR, Stage:dev 다 명시해주는 것이 좋다.

 

Profile

:일부 서비스를 실행하는 용도로 사용

 

 

다음 Yaml 파일에서 pgadmin에 profile 부여하고 나머지 postgres와 서버엔 부여하지 않았다.

 

단순히 그냥 compose up 했을 때 pgadmin은 실행 안되고 나머지 2개만 실행됐음을 확인할 수 있다.

다음과 같은 명령어 넣었을 때 기존에 생성되지 않은 pgadmin 서비스가 실행됨을 확인할 수 있다.

 

Deploy (쿠버네티스에서 중요!!)

1. limits - 이걸 넘어가면 사용x (최대 조건)

2. reservations - 사용할 사용량 표시 (최소 조건)

3. restart_policy - 재사용 설정 -> 배포 때 상세한 조건을 명시

4. update_config - 배포의 기초적 작업

stop-first: 기존껄 죽이고 새로운 서버를 띄우자

ex. 예를 들어 서버1이 1억씩 나가는데 서버2를 신규로 가동시킨다고 생각해보자. 그럼 신규2까지 가동시키면 2억씩 나가끼 때문에 비용 소모가 너무 크다. 따라서, 서버1을 먼저 끄고 서버2를 가동시킨다면 1억 그대로 유지된 상태에서 소모될 수 있다.

 

 

다음과 같이 구성했을 때 ngnix 컨테이너 3개 구성을 확인 가능하다.

 

 

하지만, 컨테이너 이름은 web이라 넣었을 때

같은 이름을 사용하기에 충돌난 것을 확인할 수 있다.

'IT > Docker & Kubernetes' 카테고리의 다른 글

Kubernetes - Baseline  (0) 2025.01.09
Docker Final - Docker Compose & Advance  (0) 2025.01.07
Docker - Muliti-Builds & Docker Compose  (1) 2025.01.03
Docker Image II - Volume & Network & Buildx  (1) 2025.01.02
Docker Image I  (4) 2025.01.01