Docker·서버 배포
WASM이 맞지 않는 상황이 있습니다. Pyodide가 지원하지 않는 패키지를 쓰거나, 로컬 파일에 접근하거나, 외부 API를 호출해야 하는 앱이라면 서버에서 marimo를 직접 실행하는 방법을 선택해야 합니다.
이 챕터는 marimo 앱을 Docker 컨테이너로 묶어 서버에 배포하는 방법을 다룹니다. Docker는 앱을 환경에 독립적인 컨테이너로 패키징하기 때문에 "내 컴퓨터에서는 되는데 서버에서는 안 된다"는 상황을 크게 줄여줍니다.
Dockerfile 작성
다음은 marimo 앱을 컨테이너화하는 기본 Dockerfile입니다.
FROM python:3.11-slimWORKDIR /appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY app.py .EXPOSE 8080RUN useradd -m app_userUSER app_userCMD ["marimo", "run", "app.py", "--host", "0.0.0.0", "--port", "8080"]
각 줄이 무엇을 하는지 순서대로 살펴봅니다.
FROM python:3.11-slim은 베이스 이미지를 지정합니다. slim 태그는 불필요한 패키지를 제외한 경량 이미지입니다.
WORKDIR /app은 컨테이너 안에서 작업 디렉토리를 /app으로 설정합니다. 이후의 COPY와 RUN 명령은 이 디렉토리를 기준으로 동작합니다.
COPY requirements.txt .와 RUN pip install은 의존 패키지를 먼저 설치합니다. 앱 코드 변경 시 패키지 재설치를 건너뛸 수 있도록 코드 복사보다 앞에 배치합니다. Docker는 레이어 캐시를 활용하기 때문에 변경이 없는 레이어는 다시 빌드하지 않습니다.
EXPOSE 8080은 컨테이너가 8080 포트를 사용한다고 문서화합니다. 실제 포트 바인딩은 컨테이너 실행 시 -p 옵션으로 지정합니다.
RUN useradd -m app_user와 USER app_user는 보안을 위해 root가 아닌 일반 사용자로 앱을 실행합니다.
CMD의 --host 0.0.0.0 --port 8080은 Ch 01에서 다룬 외부 접근 허용 옵션입니다. EXPOSE에 명시한 포트와 일치시켜야 합니다.
requirements.txt 작성
marimo==0.23.*# 앱에서 사용하는 추가 패키지pandas==2.*plotly==6.*
PART 01 Ch 02에서 강조한 것처럼 버전을 고정합니다. marimo==0.23.*은 0.23.x 시리즈의 최신 패치를 사용하되 0.24 이상은 설치하지 않겠다는 의미입니다.
이미지 빌드와 컨테이너 실행
# 이미지 빌드docker build -t my-marimo-app .# 컨테이너 실행docker run -p 8080:8080 my-marimo-app
-p 8080:8080은 호스트의 8080 포트를 컨테이너의 8080 포트에 연결합니다. 브라우저에서 http://localhost:8080으로 접근합니다.
서버에 배포한 경우에는 서버 IP나 도메인으로 접근합니다.
http://서버IP:8080
리버스 프록시를 앞에 두는 이유
marimo만 실행하는 것으로 끝나지 않는 경우가 많습니다. 실제 운영 환경에서는 보통 리버스 프록시를 marimo 앞에 배치합니다.
리버스 프록시가 필요한 이유는 크게 세 가지입니다.
첫째, HTTPS 처리입니다. marimo run은 HTTP로 동작합니다. 공개 서비스라면 HTTPS가 거의 필수인데, SSL/TLS 인증서 처리는 nginx 같은 리버스 프록시에 맡기는 것이 일반적입니다.
둘째, 포트 정리입니다. 기본 HTTP 포트인 80이나 HTTPS 포트 443에서 접근하도록 앞단에서 포트를 처리하고, 실제 marimo 서버는 8080처럼 내부 포트로 구성합니다.
셋째, 접근 제어입니다. Ch 01에서 언급했듯 marimo run 자체에는 인증 기능이 없습니다. nginx의 auth_basic이나 플랫폼 수준의 접근 제어를 리버스 프록시 레이어에 추가하는 방식으로 대응합니다.
기본 nginx 설정 예시입니다.
server { listen 80; server_name your-domain.com; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }}
proxy_set_header Upgrade와 Connection "upgrade" 설정은 WebSocket 연결을 위한 것입니다. marimo는 브라우저와 WebSocket으로 통신하므로 이 설정이 빠지면 위젯 조작이 동작하지 않을 수 있습니다.
클라우드 배포
Docker 이미지를 만들었다면 다양한 클라우드 플랫폼에 배포할 수 있습니다. marimo가 공식적으로 지원을 언급하는 플랫폼으로는 HuggingFace Spaces와 Railway가 있습니다. 그 외 Docker를 지원하는 모든 플랫폼(AWS ECS, Google Cloud Run, Fly.io 등)도 동일한 방식으로 배포할 수 있습니다.
클라우드 플랫폼마다 환경 변수 설정, 포트 설정, 헬스체크 방법이 다릅니다. 각 플랫폼의 문서를 확인하되, Dockerfile과 marimo run --host 0.0.0.0 --port 포트번호 명령이 기반이 된다는 사실은 동일합니다.
FastAPI 임베딩
marimo 앱을 FastAPI 애플리케이션 안에 마운트하는 방식도 가능합니다. 이미 FastAPI로 운영 중인 서비스가 있고 그 안에 데이터 앱을 포함시키고 싶을 때 유용합니다. 상세한 방법은 marimo 공식 문서의 배포 가이드를 참고하세요.
다음 단계
서버에서 marimo를 직접 실행하는 방법과 Docker 컨테이너로 묶는 방법을 다뤘습니다. 다음 챕터는 서버 없이 정적 파일만으로 배포하는 두 가지 방법, 정적 HTML과 WASM 결과물을 GitHub Pages에 게시하는 절차를 다룹니다.
정리
FROM python:3.11-slim과pip install -r requirements.txt를 담은 Dockerfile로 marimo 앱을 컨테이너화합니다.marimo run app.py --host 0.0.0.0 --port 8080을 CMD로 지정하고, EXPOSE와 CMD의 포트 번호를 일치시킵니다.docker build -t my-marimo-app .로 이미지를 빌드하고,docker run -p 8080:8080 my-marimo-app으로 실행합니다.- HTTPS 처리, 포트 정리, 접근 제어를 위해 nginx 리버스 프록시를 앞단에 배치합니다. WebSocket 프록시 설정(
Upgrade,Connection) 누락 시 위젯이 동작하지 않을 수 있습니다. - Docker 이미지를 만들면 HuggingFace Spaces, Railway, AWS ECS, Google Cloud Run 등 다양한 클라우드 플랫폼에 배포할 수 있습니다.