Skip to content

1995parham-learning/streamlit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

When Nostradamus uses Streamlit

Streamlit

banner

GitHub Workflow Status (with event) GitHub Pipenv locked Python version

Introduction

With Streamlit, you can easily host your Python scripts as web applications, making it a great tool for demonstrating your results or models.

Development

It's best to deploy your Streamlit applications separately rather than using a single deployment for all of them. Since Streamlit is built on Python, it's crucial to use a dependency manager for your application. Please consider one of the following options:

In this example, we're using pipenv as our dependency manager, but feel free to choose any of the others. Most of these dependency managers can provide a specific Python version for your project, allowing you to use a different version than your system's default Python installation.

pipenv install streamlit

You may need following libraries too:

pipenv install numpy
pipenv install pandas
pipenv install polars

After installing the requirements, you have Pipfile (which is written in TOML and you can also manually change it) and Pipfile.lock:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
streamlit = "*"
pandas = "*"

[dev-packages]
ruff = "*"
mypy = "*"
pandas-stubs = "*"

[requires]
python_version = "3.12"

Python is a dynamically typed language, so we strongly suggest use following linters in your code:

How to run?

streamlit config show

streamlit run main.py

Deployment

When you're ready to deploy your application to production, you should build your Docker image and integrate this process into your CI pipeline.

The following Dockerfile installs the requirements using pipenv and then serve Streamlit application on port 1378.

FROM python:3.12-slim

ENV TZ="Asia/Tehran"

RUN apt-get update && apt-get install -y --no-install-recommends \
  build-essential \
  curl \
  software-properties-common \
  git \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY Pipfile Pipfile
COPY Pipfile.lock Pipfile.lock

RUN pip install --no-cache-dir pipenv && \
  pipenv install --system --clear

COPY . .

EXPOSE 1378

HEALTHCHECK CMD curl --fail http://localhost:1378/_stcore/health
ENTRYPOINT ["streamlit", "run", "main.py", "--server.port=1378", "--server.address=0.0.0.0"]

Then you can build docker image in your CI:

  • GitHub

    name: ci
    on:
      - push
    jobs:
    # you can remove lint stage, but remember to remove it from docker stage
    # requirements too.
    lint:
      name: lint
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-python@v5
          with:
            python-version: "3.12"
        - run: pip install pipenv
        - run: pipenv install --dev -v
        - run: pipenv run mypy .
    
    docker:
      name: docker
      runs-on: ubuntu-latest
      needs:
        - lint
      steps:
        - uses: actions/checkout@v4
        - uses: docker/setup-buildx-action@v3
        - uses: docker/setup-qemu-action@v3
        - uses: docker/login-action@v3
          with:
            registry: ghcr.io
            username: ${{ github.repository_owner }}
            password: ${{ secrets.GITHUB_TOKEN }}
        - uses: docker/bake-action@v5
          with:
            files: "docker-bake.json"
            push: true
  • GitLab

    lint:
    stage: lint
    # set this to true if you don't want to have linting
    allow_failure: false
    image: python:3.12-slim
    variables:
      # proxy variables are required because GitLab workers are in Iran.
      http_proxy: "http://proxy.snappcloud.io:3128"
      https_proxy: "http://proxy.snappcloud.io:3128"
      no_proxy: ".snappcloud.io,.snapp.ir"
    before_script:
      - pip install -U pipenv pip
      - pipenv install --dev -v
      - echo "lint stage ${CI_PROJECT_NAME} on ${CI_COMMIT_REF_SLUG} branch"
    script:
      - pipenv run ruff check main.py rides.py
      - pipenv run mypy .
    build-and-release:
    image: docker:latest
    stage: build
    when: manual
    variables:
      # set these variables according your target namespace in which you want to
      # push the image.
      OKD4_TEH1_REGISTRY: "image-registry.apps.private.okd4.teh-1.snappcloud.io"
      RELEASE_CONTAINER_REGISTRY_ADDRESS: "$OKD4_TEH1_REGISTRY"
      RELEASE_CONTAINER_REGISTRY_IMAGE: "$OKD4_TEH1_REGISTRY/visualization/$CI_PROJECT_NAME"
      RELEASE_CONTAINER_REGISTRY_USERNAME: "gitlab-runner"
      RELEASE_CONTAINER_REGISTRY_PASSWORD: ${OKD4_TEH1_VISUALIZATION_TOKEN}
    before_script:
      - docker info
      - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
      - docker login -u ${RELEASE_CONTAINER_REGISTRY_USERNAME} -p ${RELEASE_CONTAINER_REGISTRY_PASSWORD} ${RELEASE_CONTAINER_REGISTRY_ADDRESS}
    script:
      - export CURRENT_DATETIME=$(TZ=Asia/Tehran date ' %FT%T')
      # proxy variables are required because GitLab workers are in Iran.
      - docker build --build-arg BUILD_DATE=$CURRENT_DATETIME --build-arg VCS_REF=${CI_COMMIT_SHA} --build-arg BUILD_VERSION=${CI_COMMIT_REF_NAME} --build-arg HTTP_PROXY=http://proxy.snappcloud.io:3128/ --build-arg HTTPS_PROXY=http://proxy.snappcloud.io:3128/ -t ${CI_PROJECT_NAME}:${CI_COMMIT_REF_NAME} -f Dockerfile .
      - docker tag ${CI_PROJECT_NAME}:${CI_COMMIT_REF_NAME} ${RELEASE_CONTAINER_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}
      - docker push ${RELEASE_CONTAINER_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}

Kubernetes

To Deploy the application on Kubernetes, you only need to have a deployment and httpproxy. If your application has configuration (the easiest way for handling configuration in python is environment variables) then you may need secret and configmap too.

---
kind: Service
apiVersion: v1
metadata:
  name: <name>
  labels:
    app: <name>
spec:
  ports:
    - protocol: TCP
      port: 1378
      targetPort: 1378
  selector:
    app: <name>

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: <name>
  name: <name>
spec:
  replicas: 1
  selector:
    matchLabels:
      app: <name>
  template:
    metadata:
      labels:
        app: <name>
    spec:
      containers:
        - name: <name>-main
          image: <image>
          imagePullPolicy: Always
          env:
            - name: CLICKHOUSE_HOST
              value: "****"
            - name: CLICKHOUSE_PORT
              value: "****"
          resources:
            limits:
              cpu: 1
              ephemeral-storage: 1Gi
              memory: 1Gi
            requests:
              cpu: 300m
              ephemeral-storage: 1Gi
              memory: 1Gi
      volumes:
        - name: data
          emptyDir: {}
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: <name>
  labels:
    app: <name>
    router: private
spec:
  host: <url>
  path: /
  to:
    kind: Service
    name: <name>
    weight: 100
  port:
    targetPort: 1378
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None

References