개요
Docker 이미지 하나에 서비스를 하나로 합치는 일이 필요할까요? 요즘 대세는 마이크로서비스인데 말이죠. 대답은 케바케 입니다. 김새는 결론이지만 애매모호한 대답을 할 수 밖에 없는게 상황에 따라 다르다는 것이 이유입니다. Kubernetes나 Docker compose를 사용해서 여러개의 서비스를 한 번에 배포, 중지, 삭제가 가능하기 때문에 아니라고 생각한다면 너무 이상적인 환경만 고려한다고 볼 수 있습니다. 때로는 여러개의 서비스를 Docker 이미지 하나로 만들어 솔루션 형태로 전달해야만 하는 드문 경우도 있습니다.
이 글에서는 마이크로서비스 중 업계에서 가장 많이 사용되는 Nginx와 최근 Python을 사용하여 웹형태로 빠르게 데모를 만들 수 있는 Streamlit을 하나의 Docker 이미지에서 만드는 방법을 공유합니다. 그리고, Nginx의 기능을 사용하기 위해 프록시 패스를 사용하여 Streamlit 서비스 경로를 노출하지 않는 것을 적용하였습니다.
코드 소스만 필요할 경우 Single Docker image for Nginx & Streamlit에서 확인하세요.
목차
Streamlit Demo
Streamlit 데모는 Streamlit Gallery에서 선택한 To-do List 어플리케이션을 사용합니다. 공개된 데모 중에 별도의 라이브러리를 사용하지 않으며, 추가 구성 파일(예: 모델 체크포인트, 이미지 파일 등)을 사용하지 않는 것 중 코드가 심플한 것을 택했습니다.
Streamlit은 기본적으로 포트 번호 8501
을 사용하지만 여기에서는 환경 설정 파일을 통해 2022
번으로 바꿔서 사용합니다. (참고)
[server]
address = "0.0.0.0"
port = 2022
Nginx Configuration
Nginx 환경 구성 파일의 핵심은 Streamlit 어플리케이션의 포트 번호를 잘 바인딩하는 것입니다.
upstream streamlit {
server 127.0.0.1:2022;
}
그리고, Nginx 서비스를 8888
번으로 노출해주고, 프록시 패스를 Streamlit 주소로 해주는 것이죠.
server {
listen 8888;
charset utf-8;
...
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://streamlit;
}
location /static {
proxy_pass http://streamlit;
}
}
위에 보여지는 코드 블럭은 온전히 동작하지 않으니 GitHub에서 꼭 확인하세요.
Dockerizing
이제 Dockerfile을 만들 차례이므로 베이스 이미지를 선택해야 합니다. 저는 Python slim 버전을 선택하여 추가로 Nginx를 설치하기로 했으나 반대의 경우도 충분히 가능하고, Streamlit이 아닌 다른 언어의 서비스를 사용할 경우 상황에 맞게 응용하시면 됩니다. 그럼 아래의 명령어로 Docker 이미지를 만들 때 Nginx를 설치해줍니다.
FROM python:3.9.10-slim
RUN apt-get -qq update && \
apt-get -y install wget gnupg && \
wget https://nginx.org/keys/nginx_signing.key && \
cat nginx_signing.key | apt-key add - && \
apt-get -qq update && \
apt-get -y install nginx && \
rm nginx_signing.key && \
rm -rf /var/lib/apt/lists/*
그리고 Python에서 사용할 패키지 목록이 있는 requirements.txt
파일과 Nginx 구동을 위한 start-nginx.sh
스크립트 파일을 복사하여 적절하게 실행해줍니다. 이 외에도 Root가 아닌 일반 User를 만들어서 사용, 환경 변수 설정, 그리고 실행 명령어등은 Dockerfile에서 확인할 수 있습니다.
마무리
Docker 이미지를 빌드하고 컨테이너를 실행시켜주면 컨테이너 로그에 URL: https://0.0.0.0:2022 가 출력되며 서비스가 실행됩니다. 물론 별도의 포트 접근 권한을 제한하지 않았기 때문에 웹브라우저에서 localhost:2022
로도 Streamlit 서비스를 확인할 수 있습니다. 또한, 이 글에서 소개하기로 한 프록시 패스를 확인하기 위해 웹브라우저에서 localhost:8888
을 통해 정상적으로 서비스가 보일 뿐만 아니라 주소창에 포트 번호 변화없이 그대로 보이는 것을 알 수 있습니다.