Compose file - Basic
[ Config 파일의 형식들 ]
- json : { }으로 key와 value로 구성됨
{ "A" : { "key" : "value" }, "B" : 30, "items" : [ "Apple", "Banana" ] }
- XML : <>으로 tree형태의 계층구조로 구성됨
- YAML : 들여쓰기로 단락을 구분함 / json과 호환( 작성법만 다름 ), 섞어서 쓰기 가능
⇒ config 파일에서 주로 쓰이는 형식 : docker compose yaml, kbuernates, Circle CI, github action- 들여쓰기나 즉시 값은 value가 됨
value에 해당하는 값은 들여쓰기를 통한 단일값(key:val), value값, 다중값 리스트(-)
A : key : value B : 30 items : - Apple - Banana
- 들여쓰기나 즉시 값은 value가 됨
Docker compose YAML 구성
- Version : YAML 문법의 버전, 해당 버전 이후에서 작동함 ⇒ 하지만 이는 단순한 참고사항(optional : 2 or 3), 실제 실행은 실행가능한 최신버전을 이용 일종의 주석으로 큰 영향이 없음, YAML파일과 호환되는 최신버전으로 실행 3.6으로 명시 → 3.2버전 수행시 수행여부 알 수 없음, 3.6버전 수행시 3.6으로 수행, 3.8버전 수행시 3.8로 수행
- Name : 프로젝트의 이름 “cloudwave” ( * 선택항목 optional )
docker 명령은 컨테이너를 대상으로 명령을 발행 ↔ docker compose 명령은 프로젝트를 대상으로 명령을 발행( -p옵션 )
[ project name의 우선순위 ]
(1) CLI를 통해서 설정한 이름 ( -p로 지정 )
(2) YAML(docker-compose.yaml)에 작성되어있는 name의 값
(3) 명령을 수행하는 디렉토리의 이름 → 충돌가능성이 매우 높음 ( 가능한 피할 것 )
* 고유성이 중요( 하나의 YAML은 하나의 프로젝트를 정의하도록함 ) → 프로젝트 이름이 동일하면 병합되어 처리 - Services( *필수항목 )
서비스를 구성하는 컨테이너들은 여러 개일 수 있으나 모두 동일한 이미지로부터 비롯된다!
services : < [service.name](<http://service.name>) > : < cmd >
services : <[service.name](<http://service.name>)> : image : : 또는 @ build : container-name : expose : - 80 - "81" - "2000-2090" ports : entrypoint : command : environment : env_file : pull_policy : 관리정책 restart : 관리정책 platform :
- image ( *유일한 필수항목 )
- local storage에서 탐색 → 없다면 remote registry에서 다운로드(pull)
- 이미지를 build하는 경우 이미지의 이름을 제공하는 역할 <repo>:<tag>의 조합
- container_name ( 선택항목 )
컨테이너 이름을 지정 = docker run에서 —name 옵션- 보통 하나의 이미지를 컨테이너화할 때는 이름을 지정하는 것이 좋지만 서비스에 해당하는 컨테이너를 몇 개 쓸 것인지를 알 수 없기에 지정하지 않음( 컨테이너 이름은 중복되지 않음에 유의)
더불어, 서비스에 소속된 컨테이너들은 하나의 목적을 위해서 존재하기에 식별할 필요가 크게 없음 - 지정하지 않을시 자동적인 이름 규칙 : <project_name>_<service_name>_<int숫자>
- 사용가능한 경우 : 컨테이너 이름이 한 개인 경우 = 서비스 내 컨테이너가 무조건 1개일 경우 ( <project_name>_<service_name>_1만 쓰이는 경우 container name으로 대체 가능 )
- 보통 하나의 이미지를 컨테이너화할 때는 이름을 지정하는 것이 좋지만 서비스에 해당하는 컨테이너를 몇 개 쓸 것인지를 알 수 없기에 지정하지 않음( 컨테이너 이름은 중복되지 않음에 유의)
- expose ( 선택항목 ) : 동일한 네트워크에 존재하는 다른 컨테이너에게 포트를 열어주는 행위 ( 네트워크를 공유한다 = bridge 네트워크로 묶여있기에 별도로 네트워크를 확장할 필요없음 )
- 숫자(INT) 80 , 문자열(STRING) “81” , 범위(RANGE) “2000-2090”
⇒ 다양한 지정값들을 리스트 형식(-)으로 작성가능 - 호스트에서 접근불가 ( localhost ), 호스트는 해당 프로젝트 네트워크에 속하지 않음
- 숫자(INT) 80 , 문자열(STRING) “81” , 범위(RANGE) “2000-2090”
- port ( 선택항목 ) : 외부( 호스트를 포함한 다른 머신들, 다른 네트워크 영역에 속하는 것들 )에 포트를 공개하는 행위
- expose와 동일하게 사용가능한 포트들을 리스트 형식으로 작성 [host]:<host_port>/protocol
host머신을 명시할경우( 127.0.0.1:8080:80 ) → 현재 로컬 호스트에서만의 접근을 한정 - <host_port> : <container_port> = 내가 사용할 포트 : app이 사용하는 포트
단순하게 container_port만 적으면 동일한 host_port와 바인딩, 내가 사용할 host_port를 수정해서 사용하는 구조 - map구조(long syntax)로 상세하게 작성가능( protocol, 지정 host_ip .. ) ⇒ 자주 사용하지 않음
- expose와 동일하게 사용가능한 포트들을 리스트 형식으로 작성 [host]:<host_port>/protocol
- entrypoint : 진입점(executable) ⇒ string형태, list형태( 가급적이면 list형태로 작성할 것 )
entrypoint : “sleep 3600” -------------------------- entrypoint : - "sleep" - "3600"
- 기존의 docker RUN에서는 불가능했던 오버라이드가 가능 → 그러나 가급적 수행하지 않는 것이 좋음, entry point는 제작자의 의도를 나타내는 핵심적인 부분
- entrypoint를 정의함에 따라(=수정) 기존에 정의되었던 CMD값은 폐기됨 ( CMD값은 entrypoint에 종속되는 값이기에 ~ )
EP CMD compose EP result echo ep echo cmd ep echo cmd echo ep echo cmd echo compose compose echo cmd(X)
compose(O)
- command : 옵션(argument) ⇒ string형태, list형태( 가급적이면 list형태로 작성할 것 )
command : “sleep 3600” -------------------------- command : [ "sleep", "3600" ] -------------------------- command : - "sleep" - "3600"
- command를 정의함에 따라(=수정) 기존의 CMD값을 대체함 ( 오버라이드 처리 ) 그러나 entrypoint는 그대로 유지됨
- command를 비워두는 것 = NULL( 정의하지 않음 ) → 도커파일의 CMD를 그대로 쓴다
↔ commdn를 “ “ / [ ] 로 지정하는 것 = 빈 값으로 정의함, 오버라이드 수행됨 ( 기존의 CMD를 무시하고 싶으나 따로 수행할 것은 없을 때 )
- image ( *유일한 필수항목 )
-
- environment( 선택항목 ) : 환경변수를 개별적으로 정의
- map방식 = dictionary구조( 들여쓰기 + key : val )
- list구조( - key =val )
- env_file( 선택항목 ) : 환경변수의 값이 많아질때 파일을 이용하여 정의, 혹은 여러 서비스에서 공통된(중복된) 환경변수 설정작업이 필요할때 사용 ⇒ 그룹화된 환경변수 설정작업
env파일(.env)의 구조 : key = value의 형태
- string값 : 기본파일(.env), 이름지정( prod.env )
- list구조( 여러파일을 지정 )
(1) 개별정의, 직접정의한 것(envorinment항목)
(2) 파일 중에서는 가장 나중에 선언된 것( 덮어쓰기 작업과 유사하게 진행 )
- environment( 선택항목 ) : 환경변수를 개별적으로 정의
-
- pull_policy : 서비스 컨테이너의 운영방식에 대한 설정( 이미지를 어떻게 가져올 것인가? ) → 4가지
기본행동양상( 이미지 컨테이너화 ) : 로컬에서 이미지 탐색 → 없다면 레지스트리에서 탐색- always : 매번 이미지를 다운로드 ( 로컬에서 이미지 탐색을 수행하지 않음, 항상 레지스트리에서 검색 → 동일한 태그이나 digest가 변경되었다면 다운로드 ) ⇒ 업데이트 반영면에서는 좋으나, 컨테이너가 전부 동일한 태그이나 동일한 이미지를 쓰지 않을 수 있음
- never : 이미지를 절대 다운로드 하지 않음 ( 외부 레지스트리 검색을 수행하지 않음 ) ⇒ 컨테이너들은 모두 동일한 이미지를 사용함을 보장할 수 있음
- missing : 이미지가 없는 경우에만 다운로드 ( 기본 행동양상과 동일함 ) ⇒ 컨테이너들은 모두 동일한 이미지를 보장함 ( 로컬에 있는 것을 반복적으로 사용 )
- build : 매번 이미지를 제작( docker run —build )
- restart : 서비스 컨테이너의 관리방식에 대한 설정( 컨테이너가 종료된 후 처리방식) → 4가지 ( 대부분 no, always로 설정 )
- no : 무슨일이있어도 재실행하지 않음 ⇒ 일회성 job인 경우 설정, 끝이 존재하는 경우
- always : 무슨일있어도 재실행( 컨테이너를 제거하지 않는다면 ) (( 컨테이너 종료 ↔ 컨테이너 제거 ))
⇒ 항상 서비스를 제공하는 서버인 경우 설정( ex. API 서버 ), 24시간 구동되며 끝이 존재하지 않는 경우 - on-failure : 문제가 생긴경우, 에러로 종료되었을때만 재실행 = exit code가 0이 아님( 장애상황 )
- unless-stopped : 명시적으로 종료 또는 삭제하는 경우(관리자 의지)를 제외하고 모두 재실행
- platform ( 선택항목 ) : 컨테이너의 운영 플랫폼을 명시
- build ( 선택항목 ) : 이미지를 제작해서 사용해야하는 경우
이 영역은 명시적으로 빌드를 수행하라고 작성했을 때만 유효함 : pull_policy를 build로 설정하거나 docker compose up에서 —build옵션을 넣음 ( build 여부가 명시적으로 설정되지 않으면 image에 명시된 이미지를 기반으로 실행 )- 빌드할 이미지의 이름은 Image에서 지정 ( 빌드가 자주 발생하여 dangling이미지가 많을 수 있음 )
- context : 도커파일의 상대경로를 해석하는데 사용됨 = 도커파일의 <PATH> 영역
- dockerfile : 빌드에 사용할 도커파일의 경로를 명시 ( 상대경로 ) = docekr build명령어의 -f 옵션
- dockerfile_inline : 이미지 빌드를 위한 도커파일 명령어들을 직접 작성
- args : 도커파일의 ARG에 지시어 값을 전달 = docker build명령어의 —build-arg
- pull_policy : 서비스 컨테이너의 운영방식에 대한 설정( 이미지를 어떻게 가져올 것인가? ) → 4가지
Docker Compose Service elements (vs) Docker Run CLI option
docker compose YAML | docker RUN CLI |
container_name | —name |
expose | —expose |
ports | -p / —ports |
entrypoint | 없음(불가) |
command | 이미지명 뒤에 명시 ⇒ 도커파일 CMD를 오버라이드 |
environment | -e |
env_file | —env-file |
tty | -t |
stdin_open | -i |
docker compose file 관련 실습
[연습] ubuntu 서버 실행하기
# docker-compose.yaml
version: '3.8'
services:
ubuntu:
image: ubuntu:22.04
restart: no
restart를 no로 설정한 경우 서비스 컨테이너는 수행종료후 즉시 종료됨
- 해결방안1 : tty, stdin_open을 열어서 대기상태로 만듬 = docker run에서 -it 옵션
# docker-compose.yaml version: '3.8' services: ubuntu: image: ubuntu:22.04 tty : true stdin_open : true restart: no
- 해결방안2 : sleep infinity 명령어를 통해 프로세스가 종료되지 않고 유지되도록함
# docker-compose.yaml version: '3.8' services: ubuntu: image: ubuntu:22.04 entrypoint : /bin/bash command : - -c - sleep infinity restart: no
[연습] 환경변수를 이용하여 compose file 제어하기
$ 환경변수 : compose YAML file과 같은 위치에 있는 .env파일 혹은 호스트 환경변수에서 자동주입받음
컨테이너에 환경변수를 주입하지 않았음에도 환경변수가 설정된다.
컨테이너를 만들때 주입되는 환경변수, 컨테이너 내부의 환경변수가 아니라 삽입한 개념
- env file에서 주입받는 경우
- 호스트의 환경변수에서 주입받는 경우
C:\\Users\\KHP>set FROM="host”
[연습] command 에서 컨테이너 환경변수 사용하기
$$ 환경변수 : 컨테이너 내부의 지정된 환경변수를 사용, 컨테이너화 된 것의 변수를 해석한다.
$환경변수는 컨테이너가 실행될때 전달되어 하드코딩된 형태(주입처리) ↔ $$환경변수는 컨테이너 내부의 변수값을 이용하는 형태(변수처리)
[연습] Docker compose에서 build 사용하기
해당이름을 가진 이미지로 빌드
명령옵션에 —build를 반드시 명시
[ 환경변수의 주입 및 설정 양상 ]
Volume 등록 및 설정
docker run -v <volume>:<container_path> 또는 <host_local_path>:<container_PATH>
- volume : 볼륨이름 or host file경로
- container_path : 절대경로( 컨테이너 내의 mount위치 )
services :
< service_name > :
image : <repo> : <tag>
volumes :
- <host_local_path> : <container_PATH> : ro
- <volumne_key> : <container_PATH> : rw
volume_NAME을 사용했다면 하단에 volumen_NAME에 대한 상세 정의를 기록해주어야함( services와 같은 level에서 volumes를 정의 )
- ro( read-only), rw( read-write ) 등의 설정을 진행
- 볼륨을 여러 개를 정의하더라도 서비스에서 사용하지 않으면 생성하지 않음
docker volume create <NAME>
volumes :
< volume_key > :
name
external
labels
- volume_key : 컴포즈 파일내에서 볼륨을 명명하는 핵심이름 ( 필수 )
나머지는 모두 optional, 볼륨에 대해 추가적으로 서술하는 내용들
- name : 생성시 사용할 이름 ( STRING ) ⇒ volume_key와 일치하지 않을 수도 있음
- 볼륨이름 : (1순위) 지정한 이름 → (2순위) <project_name>_<volume_key>
- external : 기존에 생성한 볼륨을 사용하는지에 대한 여부 ( BOOL : true/false ) = 새로 생성여부
→ 기존 볼륨 리스트에서 name과 일치하는 것을 우선적으로 검색, 없다면 key에 정의된 것을 탐색 - labels : 관리목적을 위한 라벨 = key(reverse-domain) : value
key에 description과 같은 단어를 사용하지 않음 → dev.data.description, ops.data.description과 같이 reverse-domain으로 기재
volumes
- target : <container_PATH>
source : <host_local_path> 또는 <volume_key>
type : bind / volume # short syntax와 가장 큰 차별점
read_only : true / false # true일경우 ro값, false일경우 rw값으로 설정
volume :
options
Long syntax 작성방식
- type을 명시 가능하다는 점이 가장 큰 특징
- docker run -v에서는 <host_local_path> 혹은 <volume_key> 을 식별하기 위해 경로를 직접 적어주어야함 → 그러나 YAML 문법에서는 type으로 명시적으로 지정( bind or volume )
볼륨의 정의는 serivces와 같은 레벨에서 진행
볼륨의 사용은 service 내부에서 진행
Volume설정 실습
vault라는 볼륨을 사전에 생성 = external volume
C:\\Users\\KHP>docker volume create vault
vault
read_only 로 설정하여 사용하기
master서비스에서는 볼륨에 read write가 가능하고 slave서비스에서는 볼륨에 read only만 가능하게 설정한다. 볼륨은 사전에 생성된 external 볼륨으로 설정한다.
프로젝트 실행
마스터 서비스에서는 볼륨에 write가 가능함
슬레이브 서비스에서는 볼륨에 read만 가능함
volumes_from 을 이용하여 volume 사용하기
서비스에서 사용할 모든 볼륨을 서술/정의해야하기에 복잡함 → volumes from 을 통해 모든 볼륨을 상속받는 형태로 가져올 수 있음
service :
...
volumes_from :
- container:가져올 컨테이너이름:ro/rw
...
특정 컨테이너로부터 볼륨정보를 상속받음 & 이때 볼륨을 ro/rw로 가져올지는 추가적으로 지정가능
동일한 프로젝트가 아닌 다른 프로젝트의 것도 상속가능 ( 테스트 환경에서 주로 사용 )
slave 서비스가 가지는 볼륨을 그대로 가져옴 & read-only 설정 ⇒ 접근, 읽는 것만 가능하고 쓰는 것은 불가함
Network 등록 및 설정
: docker compose의 네트워크는 서비스 레벨에서 구축되고 서비스에 속하는 모든 컨테이너에 적용된다.
[ 네트워크 정의 ]
networks:
private: # network_key
name: "private_net"
external: true
labels:
com.example.description: "private network"
- name은 docker network를 참조하는 것( 기존의 도커엔진에서 찾음 )
- <network_key>는 compose 파일 내에서 지칭하는 이름
- external : 기존 프로젝트와 통신하는 상황, 다른 프로젝트에서 생성한 네트워크를 사용한다 name으로 탐색 → key로 탐색
- 볼륨과 동일하게 network 를 정의하였더라도 service 에서 사용하지 않는 경우, 생성되지 않음
[ 네트워크 설정 ]
서비스의 networks 항목에 지정 : List형식(단순이름지정) 혹은 Map형식
docker compose 내의 서비스들은 기본적으로 상호 통신이 가능해야함
⇒ 서비스에 네트워크를 하나도 지정하지 않더라도 프로젝트 단위로 큰 네트워크가 하나 생성되고 모든 서비스가 이에 속하게 됨
⇒ 그러나 네트워크를 하나라도 명시하게 되면 기존의 default 네트워크는 사용하지 않게됨 ( default도 사용하고 싶다면 명시적으로 추가해줘야함, 하나만 명시한다면 서비스가 isolate되는 효과(기존 전체 네트워크와 분리되고 하나에만 속함) )
bastion:
image: bastion
network_mode: host
network_mode로 네트워크 드라이브를 지정가능
- 이때 host는 네트워크가 단 하나만 존재한다는 것임( 현재 호스트의 네트워크를 그대로 이용 ) → 이미 존재함, 새로 만들어서 정의하는 것이 아니라 컨테이너에 모드가 host 모드임만을 명시하면 된다.
- 아래에서 정의한다는 것은 모두 bridge임을 가정함
- alias : 다른 서비스에서 호출하기 위함 ⇒ 서비스내 여러 컨테이너중 하나가 호출됨
Network 설정실습
[연습] host 네트워크를 사용하는 컨테이너 만들기
docker run -d -p 80:80 --name nginx nginx:latest
호스트 머신의 80포트(localhost:80)에 바인딩되는 nginx 웹서버 컨테이너를 실행한다.
우분투가 호스트 머신과 동일한 네트워크대역에 호스트 머신의 네트워크, 포트를 이용하여 nginx서버에 접속이 가능하다 ( 로컬과 동일한 80포트로 )
[연습] 이미 생성된 네트워크 사용하기
bridge 드라이버를 사용하는 네트워크 private을 생성
프로젝트에서 external로 해당 네트워크를 정의하고 서비스에서 사용
이때 name을 제거해도 정상동작 : name을 제거하면, private 키 이름 자체가 네트워크 이름으로 인식 ( 키는 반드시 존재!!! )
그러나 존재하지 않는 네트워크인 my-private으로 지정하면 탐색불가
[연습] alias 설정하기 ( alias ⇒ ip없이 서비스(컨테이너)에 접근가능하게 함 )
서비스의 컨테이너들은 동일한 서비스를 제공 → 누구에나 접근해도 동일한 결과물을 얻어낼 수 있음 , 외부에서는 서비스이름으로 접근하게 됨
inspect로 서비스 네트워크의 alias를 조회해보면 개별적인 컨테이너 이름, ID가 출력되지만 서비스 이름을 공통적이다.
inspect : 컨테이너를 호출하는 방식 3가지를 보여준다.
[ 실습 ] 서로다른 프로젝트의 서비스와 연결하기
(1) across_project 네트워크를 생성하세요.
(2) network-across-project-1 프로젝트를 생성하세요
# docker-compose.yaml
version: '3.8'
name: 'network-across-project-1'
services:
ubuntu:
image: ubuntu:22.04
entrypoint: /bin/bash
command:
- -c
- apt-get update && apt-get -y install curl && sleep infinity
networks:
across_project :
aliases :
- main
networks :
across_project :
name : across_project
external : true
(3) network-across-project-2 프로젝트를 생성하세요
# docker-compose.yaml
version: '3.8'
name: 'network-across-project-2'
services:
nginx:
image: nginx:latest
# entrypoint: /bin/bash : nginx를 실행하기 위한 ep는 잡혀있으니까 이런짓 하지마셈
expose :
- 80
restart : always
networks:
across_project :
aliases :
- web
networks :
across_project :
name : across_project
external : true
(4) docker network inspect 를 이용하여 각 서비스의 IP를 확인하세요
(5) ubuntu 서버에서 curl을 이용하여 web 을 호출하세요
IP를 이용하여 호출하기
docker exec network-across-project-1-ubuntu-1 bash -c "curl 172.27.0.2:80"
DNS(alias)를 이용하여 호출하기
docker exec network-across-project-1-ubuntu-1 bash -c "curl web:80"
config & secret
보안과 관련된 설정
기존에 password는 환경변수(-e)로 주입함 → log기록으로 조회가능
공유파일을 이용 :: 개발상황에서 패스워드를 알지 못하는 상태로 운용가능
( 컨테이너 외부에서 파일을 제공 → 컨테이너 내부에 mount하는 방식 )
- config : ip와 같은 정보 → 단순 설정값 / 쿠버네티스의 config map
기본 mount위치 : /<config-name> - secret : passwd와 같은 정보 → 중요한 암호값 / 쿠버네티스의 secret
기본 mount위치 : /run/secrets/<secret-name>
docker swarm이용시에만 암호화되고 docker compose에서는 암호화X
하위레벨에서 정의 → 상단의 개별서비스에서 이용하는 방식 ( 볼륨과 유사함 )
임의의 텍스트 파일을 생성 → 패스워드로 이용
password.txt내부의 값을 패스워드로 이용하겠다고 정의함
# docker-compose.yaml
version: '3.8'
name: 'config-mount'
services:
ubuntu:
image: ubuntu:22.04
entrypoint: /bin/bash
command:
- -c
- sleep infinity
configs:
- source: password
target: /root/web_password.txt
configs:
password:
file: password.txt
정의 : 이름이 password인 config는 password.txt 파일( config파일 )로 설정하도록 함
설정 : 실제로 서비스의 config인 password( source )는 컨테이너 target경로에 매핑됨
docker exec 를 통해 config 파일을 확인가능
Compose file - Advance
anchor & Alias
yaml파일이 점점 길어지면서 중복사항(공통사항)이 발생
공통분모를 독립시켜 놓고( custom, anchor ) → 하단에서 호출하여 사용( alias )
x-common:
&common
restart: always
volumes:
- source:/code
environment:
&default-env
BY: "x-common"
x-value: &v1 x
- anchor : 값 또는 구조 / 같은 레벨이하의 것들을 모두 담음
- &command → restart, volumes, environment의 항목
- &defulat-env → BY
- &v1 → x
services:
ubuntu:
<<: *common
image: ubuntu:22.04
environment:
<<: *default-env
FROM: "env definition"
X: *v1
entrypoint: /bin/bash
command:
- -c
- echo 'env from ${FROM}' && echo env from $${BY}
restart: no
- alias : 호출
- **<< *** : 기존의 YAML형식을 그대로 가져감→ 이때 뒤에 한번더 정의되어있다면 정의된 것을 사용( alias로 가져온 값은 default와 같은 역할 )
- 병합과정에서 우선순위는 anchor의 반대쪽에 있음
- *: 기존의 YAML형식이 아닌 string값으로 가져감
- *v1 = x를 의미함
<< : *common의 결과
restart: always → no로 교체
volumes: -source:/code가 추가
environment: … → 하단의 것(명시한 것)으로 교체됨
환경변수를 env file로 공유할수도 있지만 다음과 같이 anchor로 공유하기도 가능
custom 모듈들은 최상단에 prefix(x-)를 붙여서 사용해야함 → 커스텀 용도를 규명하는 것
docker compose config 명령 : docker compose YAML파일을 확인하는 기능 → 이때 **Anchor & Alias 가 반영(1)**된 YAML확인가능 ( 병합이 반영된 결과, 최종본 ) + 환경변수가 반영(2)
profile
stage별로 서비스 구성조합을 설정가능
프로젝트 구성 : db서비스 & 우분투 서버 & pgadmin서버
⇒ 개발단계에서는 모두 사용
⇒ production단계에서 pgadmin서비스를 보안적으로 포함하지 않는 것이 좋음
profile이 정의되어있는 서비스 → 하위 프로파일이 제공될때(옵션화)만 제공
profile이 정의되어있지 않은 서비스 → profile옵션을 명시하지 않을때에도 무조건적으로 제공
삭제시( docker compose down )에도 profile옵션을 명시해야 profile 서비스까지 삭제가 됨
pgadmin서비스와 프로젝트 전체 네트워크까지 함께 삭제됨
deploy
서비스의 운영방식을 구체적으로 설정
- replicas : 원하는 갯수만큼 지정 ⇒ 자동으로 네이밍됨 ( 이때 컨테이너 이름을 반드시 명시하면 안됨 충돌남 )
name: deploy-replica
services:
web:
image: nginx:latest
expose:
- 80
deploy:
replicas: 3
- resources: 리소스( limit과 reservation으로 구분됨 ⇒ 쿠버네티스의 limit, request로 대체됨 )
- limit : 제한 = hardline, 전체 시스템의 안정을 위해서 지정해둔 최대값
- reservation : 평균적인 사용량, 컨테이너를 운영하기 위한 최소값
- restart_policy : 배포와 실패관련 설정
실패하더라도 즉시 재실행이 아닌 5초간 지연후에 재실행
재실행 시도는 최대 3회, 120초간 - update_config : 컨테이너의 이미지, 환경변수가 새롭게 설정되었을때 어떻게 업데이트 할 것인가? → 기본적인 배포전략
- parallelism : 2 ⇒ 서비스 전체를 업데이트하지 않고 동시에 2개씩 업데이트 작업을 수행, 서비스를 안정적으로 지원가능
- order( 순서 ) : 기존서버를 내리고 새로운 서버를 올리는것 사이의 순서관계
depends_on
- 하나의 서비스의 구동은 다른 서비스 환경이 정상구동됨을 가정
- 여러 서비스를 동시에 구동시킬 수 없음( 각기 다른 부팅속도 )
(ex) Nginx, API서버, DB, Redis로 구성된 프로젝트
API서비스의 전제조건 : DB, redis가 실행중
DB 및 Redis서비스의 전제조건 : X
Nginx 서비스의 전제조건 : API가 실행중
⇒ 서비스의 전제조건을 내부에 depend_on으로 기재한다
services
DB :
image :
API :
image :
depends_on :
- DB
- API
Nginx :
image :
depends_on :
- API
Redis :
image :
전제조건이 없는 서비스부터 실행 → 종속성이 적은 서비스 실행 → 종속성이 많은 서비스 실행
서비스 실행의 의미
- depends_on에서 의미하는 서비스 실행의 의미
- health check에서 서비스 상태를 판단하는 기준
(1) 서비스(container)가 생성되었다. ( status = RUNNING ) ( 부팅상황 )
↔ 응답가능한 상황 = 기능적인 완성상황 = 서비스기준 healty 상황
(2) 서비스(container)가 운영중이다. ( 사용가능 ) : 정상적인 부팅이후 응답을 받을 수 있는 상태
(3) 서비스가 완료되었다. ( 이미지가 완성된 상태 )
일회성 JOB(ex.다운로드 및 설정작업), 끝이 존재하는 작업
- short syntax방식( list ) : 의존적인 서비스이름 명시 → 해당 서비스가 단순 running 상태를 보장( 부팅, 구동 )
- long syntax방식( Map ) : 의존적인 서비스의 구체적인 condition까지 기입
- condition : 의존성을 연결한 서비스의 정확한 상태조건을 정의 ⇒ service_started(부팅완료), service_healty(서비스응답가능), service_completed_successfully(일회성 작업완료)
- restart : 의존성을 연결한 서비스가 업데이트되면 재실행여부 ( true/false ) ( ex. pgadmin 서비스는 DB의 버전, 상태에 따라 다르게 세팅 )
- required : 의존성이 있지만 실행되지 않더라도 구동은 해야함 ( ex. API 서버 )
health check
서비스가 정상적으로 운영중인지( 정상구동상태인지 ) 확인하는 일종의 절차
→ n초(intervals)마다 테스트(test)를 진행하여 n번(retries)이상 응답이 없는 경우 지정된 방식으로 처리( 재실행, 삭제 등 … )
→ time window : 실패횟수는 단위시간당(구간당) 실패횟수를 의미함 ⇒ 짧은 시간안에 실패가 반복될 경우 처리하기 위함
health check는 running상태에서 진행할 때에만 의미가 유효함
( ex. 부팅이 10분걸리는데 10초, 5번의 window를 가질 경우 실패로 판단하게 됨 ⇒ 계속 재부팅되는 잘못된 형태 )
서비스가 구동되기 위해 필요한 시간( 부팅시간 )을 정해둠(start_period) = health check의 진행이 시작될때까지의 대기시간
docker run -p 80:80 nignx:latest /bin/bash
- 문제가 되는 이유는 nginx는 구동시키는데 entrypoint+CMD의 조합이 정해짐
- 이렇게 기재하면 CMD영역을 /bin/bash로 오버라이딩하는 것이기에 정상구동이 안됨
- 단순 docker ps로 만으로는 상태체크불가 → 단순하게 Running & Exited ( status가 RUNNING이어도 서비스의 정상수행, 응답이 진행되지 않을 가능성 )
- nignx의 구동확인 : curl localhost:80 혹은 curl 컨테이너주소:80을 수행했을때 응답코드 200을 반환받을 때
[ 쿠버네티스에서의 health check ]
쿠버네티스의 pod = 배포단위 = 컨테이너의 집합 → YAML파일로 작성하며 health check방식도 정의함
(1) liveness probe : 살아있는가(RUNNING상태인가)를 파악함 ⇒ 재생성, 재부팅
(2) readiness probe : 정상적으로 서비스를 수행할 수 있는가를 파악함 ⇒ 서비스가 해당 pod로 일정시간동안 요청을 보내지 않음 ( 서비스는 일종의 LB )
(3) startup probe : 구동에 필요한 시간을 대기 → (1), (2)의 검사를 잠시 중단함
healcheck 작업의 정의(구성)
- test : 테스트 명령어 ( 보통 http응답, CMD실행 등… )
- interval : 상태체크의 시간간격, 5~10초간의 간격을 둠 → 작아지면 DDoS공격임
- timeout : 응답까지 걸리는 최대시간
- start_period : 컨테이너의 실행까지 소요되는 시간 = 부팅되는 시간 → 체크를 수행하지 않음
- disable : 순간적인 비활성화 = 주석처리
'CLOUDWAVE' 카테고리의 다른 글
Kubernetes Basic : Cluster, Node, Pod, Label&Annotation, Namespace ( 25.01.09 ) (0) | 2025.01.15 |
---|---|
Abstraction : Container, MSA ( 25.01.08 ) (0) | 2025.01.15 |
Docker Compose practice : compose CLI ( 2025.01.03 ) (0) | 2025.01.14 |
Dokcer Practice : Docker Volume, Docker Network, Docker Advance ( 2025.01.02 ) (0) | 2025.01.14 |
Dokcer Practice : Docker IMAGE, Docker Container ( 2024.12.31 ) (0) | 2025.01.14 |