이전 포스트
이전 포스트에서는 인스턴스를 생성하고 작성한 프로젝트를 가져와 인스턴스에서 정상적으로 실행되는지 테스트 해보는 과정을 가졌다. 이번 포스트에서는 nginx+gunicorn+flask+docker-compose를 활용하여 배포를 진행해보고자 한다.
전체 디렉토리 구조
├── README.md
├── .dockerignore
├── .gitignore
├── .gitmodules
├── pacage-lock.json
├── docker-compose.yml
│
├── .github/workflows
│ └── main.yml
│
├── .nginx
│ ├── Dockerfile
│ ├── default.conf
│ └── nginx.conf
│
└── src
│ ├── Dockerfile
└── ...
배포 형태
진행 과정
프로젝트를 docker를 사용해 이미지화 시킬려면 Dockerfile를 작성해줘야 한다. nginx를 통해 배포를 진행할 예정이기 때문에 nginx에 대한 Dockerfile과 작성한 코드에 대한 Dokcerfile를 각각 작성해 주었다. 관련 내용은 프로젝트 구조를 참고하면 된다.
Flask(Dockerfile)
FROM python:3
RUN mkdir /src
COPY requirements.txt /
RUN pip install -r requirements.txt
RUN pip install fastai
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
COPY . /src
WORKDIR /
RUN export FLAKS_APP=src
코드에 대해 설명하자면 /src 폴더를 만들고 requiremets.txt 목록를 설치하고 그 외 필요한 패키지를 설치 하고 모든 내용을 src 폴더에 복사하고 workdir는 루트 폴더로 지정하겠다는 의미이다.
Nginx
nginx를 사용하기 위해서 관련된 파일들을 작성해줘야 한다. 파일 목록은 전체 디렉토리 구조를 참고하면 된다.
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events{
worker_connections 1024;
}
http{
include /etc/nginx/mime.types;
default_type text/html;
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access_log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
default.conf
server {
listen 80;
location / {
proxy_pass http://flask:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Dockerfile
FROM nginx
RUN rm /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/
RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d
코드 내용을 간단하게 설명하자면 80번 포트에서 요청을 받아 8000번 포트로 요청을 전달한다는 내용과 로그 내용 수집 등에 대한 내용을 담고 있고 Dockerfile를 통해 변경 내용을 적용시키는 코드이다.
docker-compose
nginx와 flask에 대한 세팅까지 모두 완료되었다면 docker-compose를 사용해 작성한 두 컨테이너를 묶어주어야 한다.
docker-compose.yml의 내용은 다음과 같다.
version: "3.7"
services:
flask:
build: ./src # src 디렉터리 안에 있는 dockerfile를 빌드한다
container_name: flask
hostname: flask
restart: always
environment:
- APP_NAME=src
ports: # 8000포트 개방
- "8000:8000"
command: gunicorn -b 0.0.0.0:8000 src.__init__:app # 실행할 명령어
networks:
- default
nginx:
build: ./nginx # nginx 디렉토리 안에 있는 Dockerfile 빌드
container_name: nginx
hostname: nginx
restart: always
ports: # 80번 포트 개방
- "80:80"
networks:
- default
depends_on: # 의존할 컨테이너 명시
- flask
여기서 중요한 점은 flask 부분에서 command이다. 이 부분이 틀리면 프로젝트가 정상적으로 실행되지 않으므로 주의해서 실행해주어아한다. 그리고 nginx 부분에서 depend_on으로 flask 컨테이너를 명시해줘야 두 컨테이너를 같이 실행할 수 있다.
배포
여기까지 모두 진행하였다면 모든 준비가 끝났다. 이제 배포만 하면 된다.
배포를 진행할 디렉토리로 들어가 다음 명령어를 실행해주면 된다.
docker-compose rm -fs #기존에 있는 docker 프로세스 삭제
docker-compose up --build -d # docker-compose.yml 빌드
혹시 기존에 배포하고 까먹은 docker 프로세스가 존재할 수도 있으므로 깔끔하게 지우고 빌드해주는 과정을 가진다.
빌드까지 모두 완료되면 다음 명령어로 정상적으로 배포가 되었는지 확인하면 된다.
docker ps -a # 실행중인 docker 프로세스 확인
위에 명령어로 확인을 해봤는데 연결이 끊겨 있거나 정상적으로 배포가 되지 않았을 경우 도중에 오류가 발생한 것이므로 로그 기록을 통해 어느 부분에서 오류가 생겼는지 확인하고 수정 후 다시 배포를 해주면된다. 다시 배포를 할 때는 기존 이미지를 지우고 배포하는게 깔끔하다. 아래 명령어는 로그를 확인하는 명령어이다.
docker logs "이미지 이름 예시: flask"
후기
여기까지 nginx+gunicorn+flask+docker-compose를 이용한 클라우드 배포에 대한 내용을 정리해보았다. 이번 프로젝트를 진행하면서 재대로 배포를 해본건 처음이였는데 중간중간 오류도 많이 생기고 삽질도 많이 해서 시간을 상당히 많이 잡아먹었다. 하지만 막상 다 하고 나니 삽질을 했던 것에 비해 깔끔하고 생각보다 간단하게 배포가 이뤄진다는 느낌을 받았다.
결과적으로 이번 경험을 통해 서버의 구조를 이해하는데 도움이 많이 되었다.
'devops' 카테고리의 다른 글
[flask+gunicorn+nginx+docker compose] 클라우드 배포하기(2) (0) | 2024.04.06 |
---|---|
[flask+gunicorn+nginx+docker compose] 클라우드 배포하기(1) (0) | 2024.04.06 |