클로드(Claude)와 쳇지피티(ChatGPT)로부터 얻은 답변을 바탕으로, Docker, Apache, Gunicorn을 사용하여 Flask 애플리케이션을 배포하는 방법을 단계별로 설명합니다. 동작에는 성공했지만 보통 쓰는 방법과 다른 점도 있을듯합니다.
최초작성 2025. 3. 6
각 구성 요소는 다음과 같은 역할을 합니다:
Docker
Flask 앱과 그 실행에 필요한 모든 의존성을 하나의 컨테이너(상자)에 패키징하여, 어떤 환경에서도 동일하게 실행할 수 있도록 도와줍니다. 이를 통해 환경 간의 차이로 인한 문제를 줄이고 배포를 단순화합니다.
Apache
Apache는 사용자가 웹 서비스에 접속할 때 가장 먼저 만나는 웹 서버로, 클라이언트의 요청을 받아 안전하게 처리하거나 Flask 애플리케이션(또는 Gunicorn)에 요청을 전달하는 리버스 프록시 역할을 수행합니다.
Gunicorn
Gunicorn은 Flask 앱을 실제로 구동하는 WSGI 서버입니다. 여러 개의 워커(worker)를 사용하여 동시 다발적인 요청을 효율적으로 처리할 수 있게 해줍니다.
전체적인 작동 흐름은 아래와 같습니다:
클라이언트 요청 → Apache (리버스 프록시) → Gunicorn (WSGI 서버) → Flask 애플리케이션
.
VirtualBox에 Ubuntu 22.04를 설치한 환경에서 진행했습니다. Ubuntu 24.04를 설치할 경우엔 차이가 좀 있을 수 있습니다.
설치 방법은 다음 영상을 참고하세요.
Windows에 VirtualBox를 설치하여 Ubuntu 24.04 설치하기
이제 Docker, Apache, Gunicorn을 설치해봅니다.
사전 준비작업으로 우분투에 설치되어 있는 패키지를 업데이트 해줍니다.
도커 설치
1. 도커를 사용하기 위해 필요한 패키지를 설치합니다.
공식 Docker 저장소의 패키지 무결성을 검증하기 위해 GPG 키를 추가하고, Ubuntu에 Docker 저장소 정보를 등록합니다.
2. Docker 패키지를 설치하고, 데몬을 시작 및 부팅 시 자동 시작하도록 설정합니다.
또한, 현재 사용자를 Docker 그룹에 추가하여 루트 권한 없이 Docker 명령을 사용할 수 있게 합니다.
3. Docker 설치를 확인합니다.
docker run hello-world 명령을 실행하여 Docker 컨테이너가 제대로 실행되는지 테스트합니다.
이 과정에서는 Docker 클라이언트가 데몬에 요청하고, 데몬이 Docker Hub에서 "hello-world" 이미지를 가져와 컨테이너를 생성 및 실행하는 과정을 거칩니다.
문제 없다면 다음과 같은 로그가 출력됩니다. 중간에 노란색으로 표시한 Hello from Docker! 메시지가 출력됩니다.
Apache 설치
Apache는 외부 클라이언트의 요청을 받아 내부 애플리케이션(Flask)을 호출하는 리버스 프록시 역할을 합니다.
1. Apache를 설치합니다.
2. 리버스 프록시 기능을 사용하기 위해 proxy와 proxy_http 모듈을 활성화합니다.
3. 새로운 사이트 설정 파일을 만들어 Apache가 Flask 애플리케이션으로 요청을 전달하도록 구성합니다.
/etc/apache2/sites-available/file-share.conf 파일 생성하여
다음 내용을 추가합니다. nano 편집기를 사용했다면 Ctrl + O를 눌러 저장하고 Ctrl + X를 눌러 nano 편집기에서 빠져나오면 됩니다.
ProxyPass, ProxyPassReverse: Apache가 들어오는 요청을 내부의 Gunicorn 서버(127.0.0.1:8000)로 전달하도록 설정합니다.
로그 설정: 에러 및 접근 로그를 지정하여 추후 문제 발생 시 디버깅에 도움을 줍니다.
4. 새 설정 파일을 활성화하고 기본 사이트 설정을 비활성화한 후 Apache를 재시작합니다.
5. Apache 서비스 상태와 설정 테스트를 통해 올바르게 동작하는지 확인합니다.
아파치 서비스 상태 확인을 합니다.
문제 없으면 다음처럼 보입니다. q를 누르면 터미널로 빠져나옵니다.
아파치 설정을 테스트합니다.
다음처럼 보이면 문제 없다 보면 됩니다. 마지막줄에 Syntax OK 메시지가 출력되어 있습니다.
Python 및 Gunicorn 설치
1. Python 가상환경 설정프로젝트 디렉토리를 생성하고, Python 가상환경을 만들어 활성화합니다.
webnautes@webnautes-VirtualBox:~/myapp$ python3 -m venv venv
webnautes@webnautes-VirtualBox:~/myapp$ source venv/bin/activate
(venv) webnautes@webnautes-VirtualBox:~/myapp$
2. 가상환경 안에서 Flask 애플리케이션과 Gunicorn을 설치합니다.
3. 테스트에 사용할 Flask 앱을 생성합니다.
현재 위치에 app.py 파일 생성합니다.
다음 내용을 저장합니다.
애플리케이션은 기본 경로 / 에 접속 시 간단한 인사말을 반환합니다.
4. Gunicorn 설정 파일인 gunicorn.conf.py 파일을 생성하여 Gunicorn의 동작 방식을 설정합니다.
현재 위치에 gunicorn.conf.py 파일을 생성합니다.
다음 내용을 저장합니다.
Docker 설정
Docker 컨테이너 내에서 Apache와 Gunicorn을 함께 실행하여 Flask 애플리케이션을 제공할 수 있도록 Dockerfile 및 관련 파일들을 생성합니다.
1. 현재 위치에 Dockerfile을 생성합니다. Dockerfile은 컨테이너 이미지를 빌드하기 위한 레시피입니다.
다음 내용을 저장합니다.
각 단계는 다음과 같은 의미를 갖습니다:
베이스 이미지: Python 3.9 이미지를 사용하여 Python 환경을 구성합니다.
Apache 설치: 컨테이너 내에서 Apache를 설치하여 리버스 프록시 역할을 수행합니다.
파일 복사 및 의존성 설치: 필요한 파일들을 복사하고, requirements.txt에 명시된 Python 패키지를 설치합니다.
포트 노출: 외부에서 80번 포트를 통해 접근할 수 있도록 설정합니다.
시작 스크립트: 컨테이너 실행 시 Apache와 Gunicorn을 함께 실행하는 스크립트를 지정합니다.
2. 현재 위치에 requirements.txt 파일을 생성하여 필요한 Python 패키지들을 명시합니다.
다음 내용을 저장합니다.
3. 현재 위치에 start.sh 파일을 생성합니다. 컨테이너 시작 시 실행되는 스크립트입니다. Apache를 시작한 후 Gunicorn으로 Flask 애플리케이션을 구동합니다.
다음 내용을 저장합니다.
service apache2 start: 컨테이너 내부에서 Apache를 시작합니다.
gunicorn -c gunicorn.conf.py app:app: Gunicorn을 설정 파일을 기반으로 실행하여 Flask 애플리케이션을 구동합니다.`
5.4 현재 위치에 apache.conf 파일을 생성합니다. 컨테이너 내 Apache의 리버스 프록시 설정을 지정하는 파일입니다.
다음 내용을 저장합니다.
이 파일은 호스트의 포트 80으로 들어온 요청을 내부의 8000번 포트(즉, Gunicorn이 실행되는 곳)로 전달합니다.
빌드 및 실행
1. 현재 디렉토리의 Dockerfile을 기준으로 도커 이미지를 빌드합니다. 빌드하는데 시간이 좀 걸립니다.
2. 호스트 시스템에 이미 설치된 Apache와의 포트 충돌을 피하기 위해 기존 Apache 서버를 중지한 후, Docker 컨테이너를 실행합니다.
테스트 및 검증
배포한 서비스가 정상 동작하는지 확인하는 단계입니다.
1. 서비스 상태 확인
Docker 컨테이너 상태 확인: 실행 중인 컨테이너 목록과 상태를 확인합니다.
(venv) webnautes@webnautes-VirtualBox:~/myapp$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2127b484be7 myapp "./start.sh" 8 seconds ago Up 7 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp myapp_container
(venv) webnautes@webnautes-VirtualBox:~/myapp$ docker logs myapp_container
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
Starting Apache httpd web server: apache2.
Apache 및 Gunicorn 로그 확인:
컨테이너 내부에서 Apache와 Gunicorn 로그를 확인하여 에러 여부를 점검할 수 있습니다.
2. 웹 서비스 테스트
로컬에서 테스트하여 서비스가 올바르게 응답하는지 확인합니다. Hello, World! Docker + Apache + Gunicorn is working! 메시지가 출력되는지 확인합니다.
curl 테스트
(venv) webnautes@webnautes-VirtualBox:~/myapp$ curl http://localhost
Hello, World! Docker + Apache + Gunicorn is working!(venv) webnautes@webnautes-VirtualBox:~/myapp$
웹 브라우저 테스트
웹브라우저에서 http://localhost에 접속하여 "Hello, World! Docker + Apache + Gunicorn is working!" 메시지를 확인합니다.
호스트 운영체제인 윈도우에서 테스트하려면 NAT 네트워크 환경에서 외부(호스트)에서 컨테이너에 접근할 수 있도록 포트 포워딩 설정이 필요합니다.
가상 머신 창의 메뉴에서 머신 설정을 선택하고 왼쪽 메뉴에서 네트워크를 선택합니다.
어댑터 1 탭에 보이는 포트 포워딩 버튼을 클릭합니다.
+ 아이콘 클릭후, 다음처럼 포트 포워딩 규칙을 추가합니다.
이름: WebService
프로토콜: TCP
호스트 IP: 127.0.0.1 (또는 비워두어도 됨)
호스트 포트: 8080 (또는 원하는 포트)
게스트 IP: 비워둠
게스트 포트: 8080 (또는 Docker 컨테이너에서 사용하는 포트)
다음처럼 입력했습니다.
Windows 등 다른 호스트 환경에서 웹브라우저를 열고 http://localhost:8080/에 접속하여 메시지를 확인합니다:
윈도우의 명령 프롬프트에서 ipconfig 명령으로 IP를 확인한후, 다음처럼 모바일에서 접속해서도 동작합니다.
아이피가 192.168.45.245인 경우 http://192.168.45.245:8080로 접속하면 다음처럼 보입니다.
테스트 종료 후 정리
서비스 테스트가 완료된 후, Docker 리소스를 정리합니다.
Member discussion