목표
이번 장에서는
- Docker Compose를 사용하는 이유와 어디에 사용하는지 알아 볼 수 있습니다.
- Docker Compose를 사용하여 FastAPI, Postgres, Redis, Celery 생성 및 관리를 할 수 있습니다.
- Docker, Docker Compose를 사용하여 애플리케이션 개발 속도를 올릴수 있습니다.
Docker Compose
Docker Compose는 멀티-컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구입니다. YAML 파일을 사용해 애플리케이션의 서비스를 구성하며, 단일 명령으로 모든 컨테이너의 생성 및 시작 과정을 수행합니다. 이러한 접근 방식은 개발 환경을 단순화하고 표준화하는 데 큰 이점을 제공합니다.
Docker Compose의 필요성
Docker Compose를 사용하여 개발 환경을 컨테이너화하는 이유는 여러 가지입니다:
- 프로세스 관리의 단순화
개발자는 Uvicorn/FastAPI, Celery worker, Celery beat, Flower, Redis, Postgres 등의 프로세스를 각기 다른 터미널 창에서 수동으로 실행해야 하는 번거로움 없이, Docker Compose를 사용해 단일 명령으로 모든 서비스의 컨테이너를 관리하고 실행할 수 있습니다. 이는 개발 효율성을 크게 향상시킵니다. - 구성의 단순화
Docker Compose를 사용하면 FastAPI와 Celery를 위한 다양한 구성을 단일 YAML 파일에서 쉽게 생성하고 관리할 수 있습니다. 현재 FastAPI 앱의 구성이 Celery 구성에 바인딩되어 있는 것이 이상적이지 않은 경우, Docker Compose를 통해 이러한 문제를 해결할 수 있습니다. - isolated, reproducted 가능하며, portable 개발 환경: Docker는 격리된 개발 환경을 제공하므로, 개발자는 로컬 OS에 Postgres나 Redis와 같은 도구를 직접 설치하거나 가상 환경을 설정하는 등의 번거로움 없이 일관된 개발 환경을 갖출 수 있습니다. 이는 개발 환경의 재현 가능성과 이식 가능성을 보장합니다.
### Docker Compose의 이점
- 통합 관리
Docker Compose는 프로젝트의 모든 컴포넌트를 하나의 파일에서 관리할 수 있게 해줍니다. 이는 프로젝트의 복잡성을 줄이고, 새로운 개발자가 프로젝트에 빠르게 적응할 수 있도록 도와줍니다. - 환경 일관성
모든 개발자와 환경에서 동일한 Docker 컨테이너를 사용함으로써, "내 컴퓨터에서는 되는데" 문제를 방지할 수 있습니다. - 개발 생산성 향상
여러 서비스의 종속성과 설정을 쉽게 관리할 수 있으며, 개발-테스트-배포 사이클을 단순화합니다.
Docker Compose를 사용하는 것은 현대적인 개발 흐름에 있어서 중요한 부분으로, 개발 환경을 효율적이고 체계적으로 관리할 수 있는 방법을 제공합니다. 이는 특히 복잡한 애플리케이션 개발과 여러 서비스가 연동되는 마이크로서비스 아키텍처에서 큰 이점을 제공합니다.
설치
Docker Compose를 설치하고 사용하기 위한 첫 단계는 Docker 자체를 설치하는 것입니다. Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 실행하기 위한 도구로, Docker를 필요로 합니다.
Docker 및 Docker Compose 설치
- Mac과 Windows 사용자: Docker Desktop을 설치하면 Docker와 Docker Compose가 함께 설치됩니다. Docker Desktop은 이 두 도구를 쉽게 관리하고 사용할 수 있는 GUI를 제공합니다.
- Linux 사용자: Linux에서는 Docker와 Docker Compose를 별도로 설치해야 할 수 있습니다. Docker의 설치는 대부분의 Linux 배포판의 패키지 관리자를 통해 수행할 수 있으며, Docker Compose는 GitHub 릴리즈 페이지에서 직접 다운로드하거나 패키지 관리자를 통해 설치할 수 있습니다.
Docker와 Docker Compose 버전 확인
설치가 완료되면, 터미널에서 다음 명령어를 사용하여 Docker와 Docker Compose가 올바르게 설치되었는지, 그리고 어떤 버전이 설치되어 있는지 확인할 수 있습니다.
Docker 버전 확인
docker --version
예시 출력: `Docker version 20.10.16, build aa7e414`
Docker Compose 버전 확인
docker compose version
또는
docker-compose version
예시 출력: Docker Compose version v2.6.0
Config File Structure
├── alembic
├── # files omitted for brevity
├── alembic.ini
├── compose
│ └── local
│ └── fastapi
│ ├── Dockerfile
│ ├── celery
│ │ ├── beat
│ │ │ └── start
│ │ ├── flower
│ │ │ └── start
│ │ └── worker
│ │ └── start
│ ├── entrypoint
│ └── start
├── docker-compose.yml
├── main.py
├── project
├── # files omitted for brevity
├── requirements.txt
Docker Compose를 사용하여 복잡한 애플리케이션을 구성할 때, 효율적인 파일 구조를 갖추는 것이 매우 중요합니다. 여기서 제시된 구조는 FastAPI 애플리케이션과 관련된 다양한 컴포넌트(예: 웹 애플리케이션 서버, Celery 작업자, Celery Beat, Flower 등)를 Docker 컨테이너화하여 관리하는 방법을보여줍니다. 이 구조는 애플리케이션의 각 부분이 어떻게 조직될 수 있는지에 대한 개요를 제공합니다.
alembic 및 alembic.ini:
데이터베이스 마이그레이션을 관리하기 위해 Alembic을 사용합니다. alembic 폴더는 마이그레이션 스크립트를 저장하고, alembic.ini는 Alembic 설정을 담고 있습니다.
compose 폴더:
이 폴더는 Docker Compose를 사용하여 구성된 각 환경의 설정 파일, 쉘 스크립트, 관련 Dockerfile을 저장합니다. 이 예에서는 로컬 개발 환경(local)에 대한 구성을 다룹니다.
fastapi/Dockerfile:
FastAPI 애플리케이션을 실행하기 위한 Docker 이미지를 정의합니다.
celery 폴더:
Celery 관련 스크립트를 포함합니다.
beat/start, flower/start, worker/start: 각각 Celery Beat, Flower, 및 Celery Worker를 시작하기 위한 스크립트입니다.
entrypoint:
컨테이너가 시작될 때 실행될 스크립트를 정의합니다. 일반적으로 애플리케이션을 시작하기 전에 필요한 준비 작업을 수행합니다.
start:
FastAPI 애플리케이션을 시작하는 스크립트입니다.
docker-compose.yml:
Docker Compose를 사용하여 여러 컨테이너의 실행을 정의하는 파일입니다. 이 파일은 애플리케이션의 모든 서비스(웹 서버, 데이터베이스, 백그라운드 작업 처리기 등)를 선언적으로 구성합니다.
main.py:
FastAPI 애플리케이션의 진입점입니다.
project 폴더:
FastAPI 애플리케이션의 실제 소스 코드를 포함합니다. 모델, 라우트, 종속성 등을 정의합니다.
requirements.txt:
애플리케이션 및 그 종속성을 실행하는 데 필요한 Python 패키지 목록입니다.
중요 포인트
- Declarative Syntax:
docker-compose.yml 파일에서는 선언적 구문을 사용하여 환경의 원하는 최종 상태를 설명합니다. Docker Compose는 이 구성을 읽고, 필요한 모든 서비스를 자동으로 시작 및 연결합니다. - 환경 분리:
compose 폴더 내의 구조를 통해 개발, 테스트, 프로덕션 등 다양한 환경을 위한 별도의 설정과 스크립트를 관리할 수 있습니다. 이는 환경 간 설정 차이를 쉽게 관리하고, 각 환경에 맞는 도구 및 서비스를 효율적으로 구성할 수 있게 해줍니다.
이러한 구조는 Docker와 Docker Compose를 사용하는 프로젝트에서 일관성 있고 관리하기 쉬운 개발 환경을 구축하는 데 도움이 됩니다.
Application Services

프로젝트 루트에 docker-compose.yml파일을 추가합니다.
version: '3.8'
services:
web:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_web
# '/start' is the shell script used to run the service
command: /start
# this volume is used to map the files and folders on the host to the container
# so if we change code on the host, code in the docker container will also be changed
volumes:
- .:/app
ports:
- 8010:8000
env_file:
- .env/.dev-sample
depends_on:
- redis
- db
db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=fastapi_celery
- POSTGRES_USER=fastapi_celery
- POSTGRES_PASSWORD=fastapi_celery
redis:
image: redis:7-alpine
celery_worker:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_celery_worker
command: /start-celeryworker
volumes:
- .:/app
env_file:
- .env/.dev-sample
depends_on:
- redis
- db
celery_beat:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_celery_beat
command: /start-celerybeat
volumes:
- .:/app
env_file:
- .env/.dev-sample
depends_on:
- redis
- db
flower:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_celery_flower
command: /start-flower
volumes:
- .:/app
env_file:
- .env/.dev-sample
ports:
- 5557:5555
depends_on:
- redis
- db
volumes:
postgres_data:
이 docker-compose.yml 파일은 FastAPI 및 Celery를 사용하는 프로젝트의 Docker 환경을 정의합니다. 파일은 여섯 개의 서비스(web, db, redis, celery_worker, celery_beat, flower)를 구성합니다. 각 서비스는 프로젝트의 다른 부분을 담당하며, Docker Compose를 통해 함께 동작하도록 설정됩니다.
yml 설명
web
- FastAPI 서버를 위한 서비스입니다.
- build 섹션에서는 Dockerfile의 위치(./compose/local/fastapi/Dockerfile)를 지정하여 이미지를 빌드합니다.
- image 태그로 이미지에 이름을 지정합니다.
- command는 컨테이너 내에서 실행될 명령어(/start)를 정의합니다.
- volumes는 호스트와 컨테이너 간의 파일 시스템을 공유합니다. 코드 변경 사항이 호스트에서 컨테이너로 실시간으로 반영됩니다.
- ports는 호스트의 포트 8010을 컨테이너의 포트 8000에 바인딩합니다.
- env_file은 환경 변수 파일을 지정합니다.
- depends_on은 web 서비스가 redis와 db 서비스에 의존함을 나타냅니다.
db
- Postgres 데이터베이스 서버입니다.
- image는 사용할 Postgres 이미지를 지정합니다.
- volumes를 사용하여 데이터베이스 데이터를 영구적으로 저장합니다.
- environment 섹션에서는 데이터베이스 이름, 사용자, 비밀번호 등을 설정합니다.
redis
- Celery 메시지 브로커 및 result backend로 사용될 Redis 서비스입니다.
- image는 Redis 이미지를 지정합니다.
celery_worker
- Celery 워커 프로세스입니다.
- build, image, volumes, env_file 설정은 web 서비스와 유사합니다.
- command는 Celery 워커를 시작하는 커맨드(/start-celeryworker)를 지정합니다.
celery_beat
- Celery beat 프로세스로, 예약된 작업을 관리합니다.
- 설정은 celery_worker와 유사하지만, command는 /start-celerybeat로 설정됩니다.
flower
- Celery 작업의 모니터링 및 관리를 위한 대시보드인 Flower 서비스입니다.
- ports는 호스트의 포트 5557을 Flower의 포트 5555에 바인딩합니다.
공통 요소
- web, celery_worker, celery_beat, flower 서비스는 모두 같은 Dockerfile을 사용합니다. 이는 빌드 과정을 단순화하고, 모든 서비스가 동일한 환경에서 실행될 수 있도록 합니다.
- volumes를 통한 코드 공유, 환경 변수 파일의 사용, depends_on을 통한 서비스 간 의존성 설정은 이러한 서비스들이 효율적으로 협업할 수 있도록 돕습니다.
이 구성을 통해 개발자는 단일 docker-compose up 명령으로 전체 애플리케이션과 필요한 모든 서비스를 시작할 수 있습니다. 이는 개발 프로세스를 크게 단순화하고, 프로젝트의 설정과 실행을 더욱 용이하게 만듭니다.
환경변수
.env디렉토리를 프로젝트의 루트 경로에 만들어 줍니다. 그리고 .dev-sample파일을 생성하고 아래와 같이 정의합니다.
FASTAPI_CONFIG=development
DATABASE_URL=postgresql://fastapi_celery:fastapi_celery@db/fastapi_celery
CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/0
환경 변수는 애플리케이션의 구성을 관리하는 데 중요한 역할을 합니다. 이들은 코드 내에서 하드코딩하는 대신 외부에서 주입할 수 있는 설정값들로, 개발, 테스트, 프로덕션 등 다양한 환경에 따라 애플리케이션의 동작을 쉽게 변경할 수 있게 해줍니다. .env 폴더와 .dev-sample 파일을 프로젝트 루트에 생성하여 환경 변수를 정의하는 방법을 살펴보겠습니다.
.env 폴더
.env 폴더는 환경 변수 파일들을 저장하는 곳입니다. 이 폴더를 프로젝트 루트에 생성함으로써, 환경별(개발, 테스트, 프로덕션) 설정을 분리하여 관리할 수 있습니다. 파일 이름에 환경을 명시(.dev-sample, .prod-sample 등)함으로써, 필요에 따라 적절한 환경 설정을 쉽게 선택할 수 있습니다.
.dev-sample 파일
.dev-sample 파일은 개발 환경을 위한 환경 변수를 정의합니다. 이 파일에 포함된 설정은 다음과 같습니다:
- FASTAPI_CONFIG=development: FastAPI 애플리케이션의 구성을 개발 모드로 설정합니다. 이는 개발 중인 기능이나 디버깅 정보에 접근할 수 있도록 해줍니다.
- DATABASE_URL=postgresql://fastapi_celery:fastapi_celery@db/fastapi_celery: PostgreSQL 데이터베이스에 연결하기 위한 URL입니다. 이 URL은 사용자 이름(fastapi_celery), 비밀번호(fastapi_celery), 호스트(db), 그리고 데이터베이스 이름(fastapi_celery)을 포함합니다.
- CELERY_BROKER_URL=redis://redis:6379/0: Celery의 메시지 브로커로 사용될 Redis 서버의 연결 URL입니다. 이 URL은 Redis 서버의 호스트(redis)와 포트(6379), 그리고 데이터베이스 인덱스(0)를 지정합니다.
- CELERY_RESULT_BACKEND=redis://redis:6379/0: Celery 작업의 결과를 저장할 백엔드로 Redis를 사용하도록 설정합니다. 설정값은 메시지 브로커 URL과 동일합니다.
이 환경 변수들은 Docker Compose 설정에서 env_file 옵션을 통해 서비스에 주입됩니다. 이를 통해 애플리케이션과 관련 서비스들이 필요한 구성 정보를 환경 변수에서 직접 읽어 사용할 수 있게 됩니다. 환경 변수를 사용하는 접근 방식은 애플리케이션의 구성을 유연하게 관리할 수 있게 해주며, 보안상의 이유로 중요한 설정값들을 코드에 직접 포함시키지 않아도 됩니다.
Dockerfile
project 루트 경로에서 아래와 같이 디렉토리와 파일을 생성합니다.
└── compose
└── local
└── fastapi
└── Dockerfile
compose/local/fastapi/Dockerfile 파일을 아래와 같이 구성합니다.
FROM python:3.11-slim-buster
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
RUN apt-get update \
# dependencies for building Python packages
&& apt-get install -y build-essential \
# psycopg2 dependencies
&& apt-get install -y libpq-dev \
# Additional dependencies
&& apt-get install -y telnet netcat \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*
# Requirements are installed here to ensure they will be cached.
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./compose/local/fastapi/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint
COPY ./compose/local/fastapi/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start
COPY ./compose/local/fastapi/celery/worker/start /start-celeryworker
RUN sed -i 's/\r$//g' /start-celeryworker
RUN chmod +x /start-celeryworker
COPY ./compose/local/fastapi/celery/beat/start /start-celerybeat
RUN sed -i 's/\r$//g' /start-celerybeat
RUN chmod +x /start-celerybeat
COPY ./compose/local/fastapi/celery/flower/start /start-flower
RUN sed -i 's/\r$//g' /start-flower
RUN chmod +x /start-flower
WORKDIR /app
ENTRYPOINT ["/entrypoint"]
이 Dockerfile은 FastAPI와 Celery 작업을 실행하기 위한 Docker 이미지를 구축하는 방법을 정의합니다. Docker 이미지는 애플리케이션 실행에 필요한 모든 종속성과 환경을 포함하는 lightweight, portable, self-efficient한 컨테이너입니다. Dockerfile은 이미지를 만들기 위한 단계별 명령어를 포함합니다.
Dockerfile 분석
베이스 이미지
- FROM python:3.11-slim-buster: Python 3.11을 포함하는 Debian Buster를 기반으로 하는 슬림 버전의 이미지를 사용합니다. 이 베이스 이미지는 필요한 Python 환경과 함께 최소한의 패키지만 포함하여 이미지 크기를 줄입니다.
환경 변수 설정
- ENV PYTHONUNBUFFERED 1 및 ENV PYTHONDONTWRITEBYTECODE 1: Python 출력을 버퍼링하지 않도록 설정하고, Python이 .pyc 파일을 디스크에 쓰지 않도록 합니다. 이는 Docker 컨테이너에서 Python 애플리케이션을 실행할 때 일반적으로 권장되는 설정입니다.
패키지 설치
- apt-get update && apt-get install ...: 필요한 시스템 패키지를 설치합니다. 여기에는 Python 패키지를 빌드하는 데 필요한 build-essential, psycopg2 (PostgreSQL을 위한 Python 어댑터) 의존성인 libpq-dev, 그리고 추가 유틸리티인 telnet과 netcat이 포함됩니다.
종속성 설치
- COPY ./requirements.txt /requirements.txt: 호스트의 requirements.txt 파일을 컨테이너로 복사합니다.
- RUN pip install -r /requirements.txt: requirements.txt에 정의된 Python 패키지를 설치합니다.
시작 스크립트
- 여러 COPY 및 RUN 명령어를 사용하여 FastAPI 애플리케이션과 Celery 서비스를 시작하기 위한 쉘 스크립트를 컨테이너로 복사하고, 실행 가능하게 만듭니다.
- RUN sed -i 's/\r$//g' /entrypoint: Windows에서 Unix/Linux로 파일이 복사될 때 발생할 수 있는 줄바꿈(CRLF) 문제를 수정합니다.
작업 디렉토리 설정
- WORKDIR /app: 이후의 모든 RUN, CMD, ENTRYPOINT 명령어의 실행 디렉토리를 /app으로 설정합니다.
엔트리포인트 설정
- ENTRYPOINT ["/entrypoint"]: 컨테이너가 시작될 때 실행될 기본 명령어를 지정합니다. 이 스크립트는 필요한 사전 작업을 실행하고 애플리케이션 서버를 시작하는 역할을 합니다.
이 Dockerfile을 통해, FastAPI 애플리케이션과 Celery 서비스를 포함한 모든 종속성을 가진 Docker 이미지를 생성할 수 있습니다. 이 이미지는 로컬 개발 뿐만 아니라 테스트 및 프로덕션 환경에서도 사용될 수 있습니다. Docker Compose 파일과 함께 사용하면, 전체 애플리케이션 스택을 간편하게 구성하고 실행할 수 있습니다.
질문사항
Dockerfile에서 root directory에 entrypoint, start, start-celeryworker, start-celerybeat, start-flower 쉘 스크립트 파일을 위치시키는 이유는 무엇일까?
Dockerfile에서 entrypoint, start, start-celeryworker, start-celerybeat, start-flower 같은 쉘 스크립트 파일을 컨테이너의 루트 디렉토리에 위치시키는 것은 일반적인 관행 중 하나입니다. 이러한 접근 방식은 몇 가지 이유에서 유용합니다:
1. 명확성과 접근성
루트 디렉토리에 위치한 스크립트는 파일 시스템에서 쉽게 찾을 수 있으며, 컨테이너의 실행과 관련된 중요한 스크립트임을 명확하게 합니다. /app 같은 작업 디렉토리는 애플리케이션의 소스 코드와 리소스를 저장하는 용도로 사용되며, 실행 관련 스크립트와 분리하여 관리하는 것이 좋습니다.
2. 실행 환경 분리
/app 디렉토리는 애플리케이션 코드와 그에 관련된 파일을 위한 곳입니다. 반면, 실행과 관련된 스크립트(예: entrypoint, start)는 애플리케이션의 구동 방식을 정의하며, 이를 애플리케이션 코드와 분리하여 관리하는 것이 일반적으로 권장됩니다. 이렇게 하면 애플리케이션 코드와 실행 환경 사이의 관심사를 명확하게 분리할 수 있습니다.
3. Docker 관행
Docker 컨테이너에서 실행 관련 스크립트를 루트 디렉토리에 배치하는 것은 널리 사용되는 관행입니다. 이러한 스크립트는 컨테이너가 시작될 때 실행되어야 하는 명령을 포함하며, 종종 ENTRYPOINT와 CMD 지시어와 함께 사용됩니다. 루트 디렉토리에 배치함으로써 이러한 스크립트들을 쉽게 찾고 관리할 수 있습니다.
4. 권한 문제 회피
컨테이너에서 스크립트를 실행할 때 경로나 권한 문제를 최소화할 수 있습니다. 루트 디렉토리에 스크립트를 두면, 복잡한 경로 없이 직접 참조하여 실행할 수 있으며, 실행 권한 설정도 간단해집니다.
결론적으로, 이러한 접근 방식은 컨테이너의 실행 환경을 구성하는 데 있어 명확성과 관리의 용이성을 제공합니다. 그러나 프로젝트의 구체적인 요구 사항이나 팀 내부의 관행에 따라 다른 경로나 방식을 선택할 수도 있습니다.
Entrypoint
#!/bin/bash
# if any of the commands in your code fails for any reason, the entire script fails
set -o errexit
# fail exit if one of your pipe command fails
set -o pipefail
# exits if any of your variables is not set
set -o nounset
postgres_ready() {
python << END
import sys
import psycopg2
import urllib.parse as urlparse
import os
url = urlparse.urlparse(os.environ['DATABASE_URL'])
dbname = url.path[1:]
user = url.username
password = url.password
host = url.hostname
port = url.port
try:
psycopg2.connect(
dbname=dbname,
user=user,
password=password,
host=host,
port=port
)
except psycopg2.OperationalError:
sys.exit(-1)
sys.exit(0)
END
}
until postgres_ready; do
>&2 echo 'Waiting for PostgreSQL to become available...'
sleep 1
done
>&2 echo 'PostgreSQL is available'
exec "$@"
이 entrypoint 스크립트는 Docker 컨테이너가 시작될 때 FastAPI 웹 서비스가 PostgreSQL 데이터베이스에 성공적으로 연결될 수 있도록 보장하는 역할을 합니다. 데이터베이스 서버가 준비되지 않은 상태에서 웹 서비스가 시작되면 연결 오류가 발생할 수 있으므로, 이를 방지하기 위해 entrypoint 스크립트를 사용합니다.
스크립트 구성 요소
Shebang: `#!/bin/bash`는 이 스크립트가 Bash 쉘에서 실행되어야 함을 나타냅니다.
옵션 설정:
- set -o errexit:
스크립트 내의 명령어가 실패할 경우 즉시 스크립트 실행을 중단합니다. - set -o pipefail:
파이프라인의 명령어가 실패하면 해당 실패를 반환 값으로 사용하여, 파이프라인의 성공 여부를 정확하게 판단할 수 있습니다. - set -o nounset:
정의되지 않은 변수를 참조하려고 시도할 경우 스크립트가 에러와 함께 종료됩니다. - postgres_ready 함수*:
PostgreSQL 데이터베이스에 연결할 수 있는지를 확인하는 Python 스크립트입니다. 환경 변수 DATABASE_URL에서 데이터베이스 연결 정보를 파싱하여 psycopg2 라이브러리를 사용해 데이터베이스에 연결을 시도합니다. 연결에 실패하면 스크립트는 -1을 반환하며, 이는 데이터베이스가 준비되지 않았음을 의미합니다. - 루프 실행*:
until postgres_ready; do ... done 루프는 postgres_ready 함수가 성공적으로 실행될 때까지 (즉, 데이터베이스가 사용 가능해질 때까지) 반복적으로 실행됩니다. PostgreSQL이 사용 가능하다는 메시지를 출력한 후, 다음 명령어로 넘어갑니다. - exec "$@"*:
이 명령어는 스크립트에 전달된 인자들($@)로 쉘 명령어를 실행합니다. 이는 Docker 컨테이너에서 사용자가 지정한 명령어(예: /start)를 실행하는 데 사용됩니다. exec를 사용함으로써, 이 스크립트는 전달된 명령어를 실행한 후 종료되며, 실행된 프로세스는 쉘 스크립트를 실행한 쉘의 PID를 그대로 이어받습니다.
### Redis 대기 로직의 부재 이 스크립트에서 Redis 서비스가 준비되기를 명시적으로 대기하지 않는 이유는, PostgreSQL 서비스의 시작 시간이 Redis보다 일반적으로 길기 때문입니다. 따라서 PostgreSQL이 준비된 시점에는 Redis 역시 이미 사용 가능한 상태일 것이라고 가정합니다. 이러한 가정 하에, 스크립트는 데이터베이스 준비 상태만을 체크하며, 이는 전체 시스템 시작 과정을 간소화합니다.
Start Scripts
start scripts를 추가 해봅니다.
compose/local/fastapi 폴더의 구조는 아래와 같습니다.
└── fastapi
├── Dockerfile
├── celery
│ ├── beat
│ │ └── start
│ ├── flower
│ │ └── start
│ └── worker
│ └── start
├── entrypoint
└── start
이제 4개의 start script를 생성 혹은 수정 해봅니다.
compose/local/fastapi/start
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
alembic upgrade head
uvicorn main:app --reload --reload-dir project --host 0.0.0.0
compose/local/fastapi/start 스크립트는 FastAPI 애플리케이션을 시작하기 위한 쉘 스크립트입니다. 이 스크립트는 Docker 컨테이너 내에서 애플리케이션 서버를 실행할 때 사용됩니다. 각 옵션과 명령어의 역할을 설명하겠습니다.
FastAPI 애플리케이션 실행
- alembic upgrade head: Alembic을 사용하여 데이터베이스 마이그레이션을 최신 상태로 업그레이드합니다. 이는 애플리케이션을 시작하기 전에 데이터베이스 스키마가 최신 상태임을 보장합니다.
- uvicorn main:app --reload --reload-dir project --host 0.0.0.0: Uvicorn을 사용하여 FastAPI 애플리케이션을 호스팅합니다. main:app은 Uvicorn이 실행할 애플리케이션 객체를 지정합니다(main.py 파일의 app 객체). --reload 옵션은 코드 변경 시 서버를 자동으로 재시작하여 개발 중에 편리합니다. --reload-dir project 옵션은 project 디렉토리 안의 파일 변경을 감지합니다. --host 0.0.0.0은 서버가 모든 네트워크 인터페이스에서 들어오는 연결을 수락하도록 설정합니다, 즉 Docker 컨테이너 외부에서 액세스할 수 있게 합니다.
이 스크립트는 Docker 컨테이너가 시작될 때 FastAPI 애플리케이션과 관련된 필요한 준비 작업을 자동으로 실행하고, 애플리케이션 서버를 구동하는 역할을 합니다. 이를 통해 개발 환경을 효율적으로 관리하고, 애플리케이션의 실행 과정을 자동화할 수 있습니다.
compose/local/fastapi/celery/beat/start
#!/bin/bash
set -o errexit
set -o nounset
rm -f './celerybeat.pid'
celery -A main.celery beat -l info
compose/local/fastapi/celery/worker/start
#!/bin/bash
set -o errexit
set -o nounset
celery -A main.celery worker --loglevel=info
compose/local/fastapi/celery/flower/start
#!/bin/bash
set -o errexit
set -o nounset
worker_ready() {
celery -A main.celery inspect ping
}
until worker_ready; do
>&2 echo 'Celery workers not available'
sleep 1
done
>&2 echo 'Celery workers is available'
celery flower \
--app=main.celery \
--broker="${CELERY_BROKER_URL}"
이 스크립트들은 FastAPI와 Celery 작업을 위한 Docker 컨테이너의 시작 스크립트입니다. 각각의 스크립트는 특정 서비스를 시작하기 위한 명령어를 포함하고 있으며, 서비스 간의 의존성과 실행 순서를 관리합니다. 이들은 compose/local/fastapi 디렉토리에 위치하며, Docker Compose 설정에 의해 각 서비스의 시작 시 호출됩니다.
Celery Beat 시작 스크립트 (celery/beat/start)
- 기존의 celerybeat.pid 파일을 삭제하여 Celery Beat 프로세스가 이전 실행에서 생성한 PID 파일에 의해 방해받지 않도록 합니다.
- Celery Beat를 시작하여 주기적인 작업 스케줄링을 활성화합니다.
Celery Worker 시작 스크립트 (celery/worker/start)
- Celery Worker를 시작하여 백그라운드 작업 처리를 시작합니다. 로그 레벨은 info로 설정됩니다.
Flower 시작 스크립트 (celery/flower/start)
- Celery Worker가 준비될 때까지 대기하는 로직을 포함합니다. celery -A main.celery inspect ping을 사용하여 worker의 상태를 확인합니다.
- 모든 worker가 준비되면, Celery Flower를 시작합니다. Flower는 Celery 작업과 worker를 모니터링하고 관리하는 웹 기반 도구입니다. --broker 옵션으로 메시지 브로커의 URL을 지정합니다.
스크립트의 역할
이 스크립트들은 Docker 컨테이너 내에서 서비스를 안정적으로 시작하고 관리하기 위한 초기화 과정을 담당합니다. 의존성 있는 서비스가 준비되기 전까지 대기하거나, 필요한 사전 설정 작업(예: PID 파일 삭제, 데이터베이스 마이그레이션 적용)을 수행합니다. 이런 방식으로, 각 서비스는 올바른 순서와 환경에서 시작되어 애플리케이션의 전반적인 안정성과 가용성을 향상시킵니다.
의문사항
1. 왜? celery beat만 pid 파일을 생성하고 별도로 관리하는가?
Celery Beat는 스케줄된 작업을 주기적으로 실행하기 위해 Celery의 스케줄러 역할을 합니다. Celery Beat가 실행될 때, 현재 실행 중인 인스턴스의 프로세스 ID(PID)를 파일에 기록합니다. 이 celerybeat.pid 파일은 Celery Beat 프로세스가 이미 실행 중인지 확인하는 데 사용됩니다. 만약 Celery Beat를 재시작하거나, 비정상적으로 종료된 후 다시 시작하려고 할 때 이전 실행에서 생성된 PID 파일이 존재하면, 새 인스턴스의 시작을 방해하게 됩니다. 이는 Celery Beat 인스턴스가 이미 실행 중이라고 잘못 판단하게 만들 수 있습니다.
따라서, Celery Beat 서비스를 시작하기 전에 기존의 celerybeat.pid 파일을 삭제하는 것은 중복 실행을 방지하고, 각 실행 시마다 새롭고 깨끗한 상태에서 시작할 수 있도록 하는 중요한 단계입니다. 이 절차를 통해 어떤 이유로든 Celery Beat가 비정상적으로 종료되었을 때도 안정적으로 재시작할 수 있습니다.
반면에, Celery Worker나 Flower 서비스는 PID 파일을 사용하지 않습니다. Celery Worker는 독립적인 작업 처리 단위로 실행되며, 여러 인스턴스가 동시에 실행될 수 있습니다. Flower도 별도의 PID 파일을 관리하지 않으며, Celery 클러스터의 모니터링 및 관리를 위한 웹 기반 도구로 동작합니다. FastAPI 애플리케이션 역시 PID 파일을 생성하거나 관리하지 않습니다. 이러한 서비스들은 PID 파일을 통한 프로세스 관리 방식을 사용하지 않으므로, 시작 스크립트에서 PID 파일을 삭제할 필요가 없습니다.
2. 더 구체적인 설명
- PID 파일의 목적
- Celery Beat가 PID 파일을 사용하는 주된 이유는 싱글턴(Singleton) 패턴을 보장하기 위해서입니다. 싱글턴 패턴은 특정 클래스의 인스턴스가 단 하나만 생성되어 시스템 전역에서 접근 가능하도록 하는 디자인 패턴을 말합니다. Celery Beat의 경우, 동일한 스케줄 설정에 대해 여러 인스턴스가 동시에 실행되면 예상치 못한 문제가 발생할 수 있습니다. 예를 들어, 동일한 작업이 중복으로 실행되어 데이터의 일관성이 손상될 수 있습니다.
- Celery Beat의 역할
- Celery Beat는 스케줄에 따라 반복적으로 실행되어야 하는 작업을 관리합니다. 이런 작업들은 주로 데이터베이스 정리, 이메일 발송, 정기적인 데이터 처리 등이 있을 수 있습니다. Celery Beat는 이러한 작업들이 정확한 시간에 실행되도록 스케줄링하는 책임을 지니고 있습니다.
- PID file을 통한 프로세스 관리
- Celery Beat는 시작할 때 현재 실행 중인 인스턴스의 PID를 파일에 기록합니다. 이 PID 파일은 Celery Beat가 이미 실행 중인지 아닌지를 확인하는 데 사용됩니다. 만약 PID 파일이 이미 존재하고, 파일에 기록된 PID에 해당하는 프로세스가 시스템에 존재한다면, 이미 Celery Beat 인스턴스가 실행 중임을 의미하고, 또 다른 인스턴스의 실행을 방지합니다.
- celery worker와의 차이점
- 반면, Celery Worker는 주로 비동기 작업을 처리하는 데 사용되며, 동시에 여러 인스턴스가 실행될 수 있습니다. 각 Worker 인스턴스는 독립적으로 작업 큐에서 작업을 가져와 처리합니다. 이러한 특성 때문에 Worker는 싱글턴 패턴이나 PID 파일을 관리할 필요가 없습니다.
4. beat를 제외한 나머지 프로세스가 비정상적으로 종료하고 다시 시작하려고 할때 이전 실행에서 생성된 PID가 존재하면 새인스턴스의 시작을 방해하지 않는가?
비정상적으로 종료된 후 다시 시작하는 과정에서 Celery Worker나 Flower와 같은 다른 프로세스들은 Celery Beat와 달리 PID 파일을 사용하지 않습니다. 이들은 Celery Beat와는 다른 운영 메커니즘을 가지고 있기 때문에, 프로세스의 재시작에 PID 파일이 직접적으로 영향을 주지 않습니다.
**Celery Worker**
- 재시작 문제:
Celery Worker는 비정상 종료 후 재시작할 때 PID 파일을 체크하거나 생성하지 않습니다. 따라서 이전 실행에서 생성된 PID 파일이 존재한다 하더라도, Worker 프로세스의 재시작을 방해하지 않습니다. - 운영 메커니즘:
Worker는 독립적인 작업 단위로 작동하며, 여러 Worker 인스턴스가 동시에 실행되어 각자 할당된 작업을 처리할 수 있습니다. 이러한 특성 때문에 싱글턴 패턴이나 PID 파일을 통한 실행 관리가 필요하지 않습니다.
Flower
- 재시작 문제:
Flower 역시 PID 파일을 관리하지 않습니다. Flower는 Celery의 모니터링 도구로, Celery Worker의 상태를 시각적으로 표시합니다. 비정상적으로 종료되었다가 재시작하는 경우, 이전 실행과 관련된 PID 파일의 존재 여부가 재시작에 영향을 미치지 않습니다. - 운영 메커니즘:
Flower 인스턴스의 주된 목적은 Celery 시스템의 작업 실행 상태를 모니터링하는 것입니다. 따라서, 여러 인스턴스의 동시 실행이 필요하지 않고, PID 파일을 통해 인스턴스를 단일화할 필요가 없습니다.
일반적인 경우
- 대부분의 백엔드 프로세스나 웹 애플리케이션 서비스에서는 비정상 종료 후 재시작 시, 이전 실행의 잔여물(예: PID 파일, 임시 파일 등)로 인해 문제가 발생할 수 있습니다. 그러나, Celery Worker나 Flower와 같은 특정 서비스는 설계상 이러한 파일을 사용하지 않으므로, 이 문제에 영향을 받지 않습니다.
- 필요에 따라, 이전 실행의 잔여물을 정리하는 작업(예: 임시 파일 삭제, 데이터베이스 연결 초기화 등)은 애플리케이션 로직이나 시작 스크립트에서 처리할 수 있습니다.
Celery Beat의 경우처럼 PID 파일을 사용하는 경우는 특정 프로세스의 중복 실행을 방지하고 싱글턴 패턴을 유지하기 위한 명시적인 요구사항이 있을 때 주로 적용됩니다.
Basic Workflow

설정이 완료되었다면 전체 작업 흐름을 명확히 파악하기 위해 어떻게 함께 작동하는지 살펴보겠습니다.
psycopg2-binary==2.9.9
가상환경을 비활성화하고 이미지를 빌드해줍니다.
$ docker compose build
이미지 빌드가 되었다면 컨테이너를 detached 모드로 기동시킵니다.
$ docker compose up -d
Docker 컨테이너 환경에서 FastAPI 애플리케이션과 관련 서비스(Celery Worker, Celery Beat, Flower)를 실행하기 전에 몇 가지 준비 단계가 필요합니다. psycopg2-binary
를 requirements.txt
에 추가하는 것부터 시작하여, Docker 이미지를 빌드하고, 컨테이너를 분리 모드에서 실행하는 과정까지를 설명하겠습니다.
psycopg2-binary 추가
psycopg2-binary
는 PostgreSQL 데이터베이스에 연결하기 위한 Python 라이브러리입니다.-binary
접미사는 이 라이브러리가 바이너리 패키지를 포함하고 있음을 의미하며, 추가적인 컴파일 없이 설치가 가능합니다.requirements.txt
파일에psycopg2-binary==2.9.9
를 추가하면, 이후 Docker 이미지 빌드 시 이 라이브러리가 설치되어 PostgreSQL 데이터베이스에 연결할 수 있습니다.
가상 환경 비활성화
- Docker를 사용할 때는 호스트 시스템의 Python 가상 환경을 비활성화하고 제거하는 것이 좋습니다. Docker 컨테이너 자체가 격리된 환경을 제공하기 때문입니다.
Docker 이미지 빌드
- Docker Compose를 사용해 이미지를 빌드합니다. 이 과정에서
docker-compose.yml
파일에 정의된 모든 서비스에 대한 Docker 이미지가 생성됩니다. - 터미널에서
docker compose build
명령어를 실행합니다. 이 명령은 현재 디렉토리의docker-compose.yml
파일을 찾아 해당 파일에 정의된 모든 서비스의 이미지를 빌드합니다.
컨테이너 실행
- 이미지 빌드가 완료되면,
docker compose up -d
명령어를 사용하여 모든 컨테이너를 분리 모드(detached mode)에서 실행합니다. 분리 모드에서 실행하면 터미널이 바로 반환되며, 컨테이너는 백그라운드에서 실행됩니다. depends_on
옵션에 정의된 순서에 따라,redis
와db
컨테이너가 먼저 실행되고, 그 다음web
,celery_worker
,celery_beat
,flower
컨테이너가 실행됩니다.
서비스 사용
- 컨테이너가 실행되면,
entrypoint
스크립트가 자동으로 실행되어 데이터베이스 및 기타 의존성이 준비될 때까지 대기합니다. 그 후, 데이터베이스 마이그레이션과 개발 서버가 실행됩니다. - FastAPI 애플리케이션은
http://localhost:8010/
에서 확인할 수 있습니다. 여기서 "Hello World" 메시지나 기타 API 엔드포인트의 응답을 볼 수 있습니다. - Celery 작업의 모니터링을 위한 Flower 대시보드는
http://localhost:5557/
에서 접근할 수 있습니다.
Troubleshooting
Docker Compose를 사용하여 여러 컨테이너를 실행하고 관리하는 과정에서 문제가 발생할 수 있습니다. 이러한 문제를 해결하기 위한 몇 가지 방법을 확인해보겠습니다.
로그 확인
문제를 진단하는 첫 번째 단계는 관련 로그를 확인하는 것입니다. 로그는 실행 중인 컨테이너의 상태와 이벤트, 오류 메시지 등 유용한 정보를 제공합니다. 로그를 확인하려면 다음 명령어를 사용합니다:
$ docker compose logs -f
-f
옵션은 로그를 실시간으로 팔로우(follow)합니다. 이를 통해 로그 메시지가 출력되는 즉시 볼 수 있으며, 문제 해결 과정에서 새로운 이벤트를 관찰할 수 있습니다.
문제 해결 및 재시도
로그를 통해 문제를 파악한 후에는 해당 문제를 해결하려고 시도해야 합니다. 문제 해결이 완료되면 변경 사항을 적용하기 위해 이미지를 다시 빌드하고 컨테이너를 재시작해야 할 수 있습니다. 이를 위해 다음 명령어를 사용합니다:
$ docker compose build
$ docker compose up -d
먼저, docker compose build
명령어로 이미지를 다시 빌드합니다. 그 후, docker compose up -d
명령어로 컨테이너를 분리 모드(detached mode)에서 다시 시작합니다.
Mac Silicon 사용자를 위한 추가 조치
Apple Silicon(M1, M2 칩 등)을 탑재한 Mac 사용자는 아키텍처 호환성 문제로 인해 예상치 못한 오류에 직면할 수 있습니다. 이 경우, Docker가 기본적으로 사용할 플랫폼을 linux/amd64
로 설정하는 것이 도움이 될 수 있습니다. 이는 다음 환경 변수 설정으로 수행할 수 있습니다:
$ export DOCKER_DEFAULT_PLATFORM=linux/amd64
이 명령어는 현재 쉘 세션에 대해 Docker의 기본 플랫폼을 linux/amd64
로 설정합니다. 이 설정을 적용한 후 Docker Compose 명령어를 다시 실행해보세요.
compose 유용한 명령어
Docker Compose를 사용할 때 유용한 몇 가지 명령어를 소개하겠습니다. 이러한 명령어는 컨테이너와 상호작용하고, 컨테이너 내부에서 작업을 실행하는 데 도움이 됩니다.
실행 중인 컨테이너에 접속하기
실행 중인 특정 서비스의 컨테이너에 쉘 접근을 원할 때, docker compose exec
명령어를 사용합니다. 이는 이미 실행 중인 컨테이너에 명령을 실행하게 해줍니다.
$ docker compose exec <service-name> bash
<service-name>
: 쉘에 접속하고자 하는 서비스의 이름입니다.docker-compose.yml
파일에서 정의된 서비스 이름을 사용합니다.bash
: 실행하고자 하는 명령어입니다. 이 경우bash
쉘을 열어서 컨테이너 내부에 접속하게 됩니다.
예를 들어, web
서비스의 컨테이너 내부에 접속하려면 다음과 같이 명령어를 사용합니다:
$ docker compose exec web bash
이 명령어는 web
서비스의 컨테이너 내부에서 bash 쉘을 열어서, 직접 파일을 수정하거나, 환경을 확인하거나, 다른 명령어를 실행할 수 있게 해줍니다.
새 컨테이너에서 명령 실행하기
아직 실행 중이지 않은 컨테이너에서 특정 명령어를 실행하고 싶다면, docker compose run
명령어를 사용할 수 있습니다. 이 명령은 새로운 컨테이너를 생성하고 그 안에서 지정된 명령을 실행한 후, 컨테이너를 삭제합니다.
$ docker compose run --rm <service-name> <command>
--rm
: 컨테이너가 종료되면 자동으로 삭제하도록 지시합니다. 이 옵션은 임시 작업을 위한 컨테이너를 생성할 때 유용하게 사용됩니다.<service-name>
: 명령어를 실행할 서비스의 이름입니다.<command>
: 컨테이너 내에서 실행할 명령어입니다.
예를 들어, web
서비스에 대해 새 컨테이너를 생성하고 bash 쉘을 실행한 후, 작업을 마친 뒤에 컨테이너를 삭제하려면 다음과 같이 명령어를 사용합니다:
$ docker compose run --rm web bash
이 명령어는 임시로 web
서비스의 컨테이너를 생성하고, bash 쉘에 접속한 후, 쉘을 종료할 때 컨테이너를 자동으로 삭제합니다. 이 방법은 일시적인 실험이나 테스트를 위해 컨테이너를 사용할 때 특히 유용합니다.
테스트
이 시나리오에서는 FastAPI 애플리케이션과 Celery를 사용하여 간단한 백그라운드 작업을 실행하고, 그 결과를 확인하는 과정을 설명합니다. 여기서는 Docker Compose를 사용하여 웹 서비스, Celery worker, Redis 서비스 등을 포함한 여러 컨테이너를 실행하고 있습니다. 각 단계를 자세히 살펴보겠습니다.
1단계: Python 쉘에서 작업 실행
먼저, 실행 중인 `web` 서비스의 컨테이너 내부에 Python 쉘로 접근합니다.
$ docker compose exec web python
Python 쉘에서 다음 코드를 실행하여 divide
작업을 Celery를 통해 비동기적으로 실행합니다. 이 때, divide
함수는 두 숫자를 나누는 간단한 작업을 수행합니다.
>>> from main import app
>>> from project.users.tasks import divide
>>>
>>> divide.delay(1, 2)
<AsyncResult: decba749-8f7e-49b3-9d40-62da39298fef>
이 코드는 divide
작업을 비동기적으로 실행하고, 실행 결과를 나타내는 AsyncResult
객체를 반환합니다. 이 객체에서는 작업 ID를 확인할 수 있습니다.(예. <AsyncResult: decba749-8f7e-49b3-9d40-62da39298fef>
)
2단계: Celery Worker 로그 확인
새 터미널 창을 열고 프로젝트 디렉토리로 이동한 다음, Celery Worker의 로그를 확인합니다.
$ docker compose logs celery_worker
로그에서는 divide
작업이 받아들여지고 성공적으로 처리된 것을 확인할 수 있습니다. 로그에는 작업 ID와 함께 작업이 수행된 시간, 결과 값 등의 정보가 표시됩니다.
3단계: Redis에서 작업 결과 확인
Redis 서비스의 컨테이너 내부에 쉘로 접근합니다.
$ docker compose exec redis sh
Redis CLI를 사용하여 작업 결과를 직접 조회합니다. 작업 ID를 키로 사용하여 MGET
명령어로 결과를 조회할 수 있습니다.
$ redis-cli 127.0.0.1:6379> MGET celery-task-meta-<task-id>
조회 결과에는 작업의 상태, 결과 값, 완료 시간 등의 정보가 JSON 형식으로 표시됩니다.
4단계: Flower 대시보드에서 결과 확인
웹 브라우저를 사용하여 Flower 대시보드에 접속합니다. 주소는 `http://localhost:5557/`입니다.
대시보드에서는 실행 중이거나 완료된 Celery 작업의 리스트와 상태, 결과 등을 시각적으로 확인할 수 있습니다. 여기서도 `divide` 작업의 결과를 확인할 수 있습니다.
이 테스트 과정을 통해 FastAPI 애플리케이션과 Celery를 사용한 비동기 작업 처리의 전체적인 흐름을 확인할 수 있습니다. Docker Compose를 사용하면 이러한 다중 컨테이너 환경을 쉽게 구성하고 관리할 수 있으며, Redis와 Flower를 통해 작업 처리와 모니터링을 효율적으로 수행할 수 있습니다.
이 장에서는 Docker와 Docker Compose를 사용하여 FastAPI, Postgres, Redis, Celery를 실행하는 방법에 대해 알아보았습니다. Docker Compose를 통해 단일 터미널 창에서 각 서비스를 손쉽게 시작할 수 있게 되었습니다. 이를 통해 개발 환경의 설정과 관리가 크게 단순화되며, 애플리케이션의 배포와 확장성도 개선됩니다.
프로젝트 구조
최종 프로젝트 구조는 다음과 같아야 합니다:
├── alembic
│ ├── README
│ ├── env.py
│ ├── script.py.mako
│ └── versions
│ ├── 399011ac3c75_.py
│ └── b48ac95a682c_.py
├── alembic.ini
├── celerybeat-schedule
├── compose
│ └── local
│ └── fastapi
│ ├── Dockerfile
│ ├── celery
│ ├── entrypoint
│ └── start
├── db.sqlite3
├── docker-compose.yml
├── main.py
├── project
│ ├── __init__.py
│ ├── celery_utils.py
│ ├── config.py
│ ├── database.py
│ └── users
│ ├── __init__.py
│ ├── models.py
│ └── tasks.py
└── requirements.txt
결론
Docker와 Docker Compose를 사용하여 FastAPI 애플리케이션과 관련 서비스들을 컨테이너화함으로써, 개발 환경을 효과적으로 관리하고, 애플리케이션의 배포를 간소화하는 방법을 배웠습니다. 이러한 도구들은 현대적인 웹 애플리케이션 개발에서 중요한 역할을 하며, 개발자가 생산성을 높이고 애플리케이션을 안정적으로 운영할 수 있도록 돕습니다.
'프로그래밍 언어 > 파이썬' 카테고리의 다른 글
Celery와 FastAPI - 6 (1) | 2024.03.24 |
---|---|
Celery와 FastAPI - 5 (1) | 2024.03.24 |
Celery와 FastAPI - 3 (1) | 2024.03.23 |
Celery와 FastAPI - 2 (1) | 2024.03.22 |
Celery와 FastAPI - 1 (0) | 2024.03.22 |