: 여러 컨테이너를 정의하고 실행하기 위한 도구
YAML파일을 사용해 애플리케이션의 서비스, 네트워크, 볼륨 등을 구성하고, 이 파일을 기반으로 한 명령어로 모든 서비스를 빌드하고 시작할 수 있다.
→ 개발, 테스트, 스테이징, 프로덕션 환경에서 일관성을 보장하는 데 유용하다.
간편한 구성
명령어 단순화
개발 효율성 증대
로컬 환경에서 전체 애플리케이션을 손쉽게 시뮬레이션하고 테스트할 수 있다.
→ 다른 개발자나 환경과 충돌 없이 독립적인 작업이 가능하다
환경 일관성 보장
개발부터 프로덕션까지 애플리케이션의 환경을 일관되게 유지할 수 있다.
→ 사용성 문제 : 개발환경에서는 동작되던것이 실제 환경에서는 안된다! 와 같은 문제를 방지해준다.
다중 서비스 관리
데이터 베이스 , 백엔드, 프론트엔드 등을 한번에 관리 가능하다. 각각은 독립적인 컨테이너로 실행되지만 도커 컴포즈로 연결되고 조율된다.
도커 컴포즈 파일의 버전을 명시한다. 일반적으로는 최신 버전을 사용하는 것이 좋다.
version: '3'
애플리케이션을 구성하는 컨테이너들을 정의한다. 각 서비스는 하나의 컨테이너를 의미하며, 도커 이미지, 포트바인딩, 볼륨 마운트 등 컨테이너를 실행하기 위한 설정이 포함된다.
services:
web:
image: nginx
ports:
- "8080:80"
db:
image: postgres
volumes:
- db-data:/var/lib/postgresql/data
컨테이너 간 통신을 위한 네트워크를 정의한다.
networks:
app-network:
데이터를 영구적으로 저장하기 위한 볼륨을 정의한다. → 여러 컨테이너 간에 데이터를 공유할 수 있도록 한다.
volumes:
db-data:
https://github.com/docker/awesome-compose
→ 도움이 된 자료 ! 여러 YAML파일을 제공한다.
위 사이트를 참고해 도커 컴포즈를 실행해보자
mkdir composetest
cd composetest
test환경을 따로 만들어준다.
app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
requirements.txt
flask
redis
flask 와 redis사용할 것 이다 requirements.txt에 위와 같이 입력하자
Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.10-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run", "--debug"]
Dockerfile을 세팅한다.
compose.yaml
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
docker compose up을 입력해 실행한다.
🔥그런데 !!!!
Ports are not available: exposing port TCP 0.0.0.0:8000 -> 0.0.0.0:0: listen tcp 0.0.0.0:8000: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
1. natstat -o -a 를 통해 포트를 사용중에 있는지 확인했다.
-> 아니였다.
2. [Docker] Ports are not available 에러 -> 이 글을 참고해 윈도우 자체에서 막고 있는지 확인했다.
-> 아니였다.
그래서 사용하지 않을것같은 9090포트로 다시 설정했다.
-> compose.yaml에 8000:5000을 9090:5000으로 수정했다.
다시돌아와서 docker compose up을 입력해 실행해보자
-> 이 경고 메시지가 나타난 이유는 플라스크 서버가 개발 모드로 실행되었기 때문이다. 지금은 넘어가도 문제 없다.

localhost:9090으로 접속했을때는 1times -> 새로고침 후 2times로 변경된것을 확인할 수 있다.

docker desktop을 확인해보면 다음과 같이 구성되어있음을 확인할 수 있다.
종료하려면
-> 다른 터미널을 열어 docker compose down하거나
-> 현재 터미널에서 CTRL+C를 입력한다.
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync
path: .
target: /code
redis:
image: "redis:alpine"
파일이 변경될 때마다 Compose는 /code컨테이너 내부의 해당 위치에 파일을 동기화한다. 복사한 후 번들러는 재시작 없이 실행 중인 애플리케이션을 업데이트한다.
-> 위의 코드는 develop 모드일 때 watch를 사용하겠다고 설정했다.
docker compose watch또는 docker compose up --watch를 입력한다.
수정 전 app.py : return 'Hello World! I have been seen {} times.\n'.format(count)
수정 후 app.py : return 'Hello World hehehe! I have been seen {} times.\n'.format(count)
바로 변경되는 것을 확인할 수 있다 !!
원래 compose.yaml 코드는 다음과 같다.
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync
path: .
target: /code
redis:
image: "redis:alpine"
redis부분을 따로 빼서 infra.yaml에 저장한다.
redis:
image: "redis:alpine"
그리고 compose.yaml 코드를 아래와 같이 수정한다.
include:
- infra.yaml
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync
path: .
target: /code
-> 앞서 확인했던 것처럼 Hello world브라우저에 메시지가 표시되는 것을 확인할 수 있다!
+) 옵션 -d를 사용하면 백그라운드에서 실행가능하다. -> docker compose up -d