Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a GitHub Actions workflow to build the Docker container image #1

Merged
merged 12 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Build Docker container image

on:
push:
branches:
- 'main'
- 'beta'
- 'stable'
tags:
- 'v*'
pull_request:
merge_group:
workflow_dispatch:
inputs:
git-ref:
description: 'Git ref (optional)'
required: false

env:
REGISTRY_IMAGE: ghcr.io/planktoscope/streamlit-classification-app

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Prepare environment variables
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

# Build and publish Docker container image
- name: Get Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=sha

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v5
with:
context: ./
pull: true
push: ${{ (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork) || github.event_name == 'push' || github.event_name == 'push tag' }}
platforms: ${{ matrix.platform }}
tags: ${{ env.REGISTRY_IMAGE }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ !github.event.pull_request.head.repo.fork }}

- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
runs-on: ubuntu-latest
needs:
- build
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true

# Build and publish Docker container image
- name: Get Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=match,pattern=v(.*),group=1
type=edge,branch=main
type=ref,event=branch,enable=${{ github.ref != format('refs/heads/{0}', 'main') && github.ref != format('refs/heads/{0}', 'main') }}
type=ref,event=pr
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'stable') }}
type=sha

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
if: ${{ (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork) || github.event_name == 'push' || github.event_name == 'push tag' }}
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Create manifest list and push
working-directory: /tmp/digests
if: ${{ (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork) || github.event_name == 'push' || github.event_name == 'push tag' }}
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)

- name: Inspect image
if: ${{ (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork) || github.event_name == 'push' || github.event_name == 'push tag' }}
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
22 changes: 16 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Use an official Python runtime as the base image
FROM python:3.12
# We use the same base image as what the PlanktoScope segmenter's container image uses:
FROM docker.io/library/python:3.9.18-slim-bullseye

# Install curl for container healthcheck
RUN \
apt-get update && \
apt-get -y upgrade && \
apt-get -y install --no-install-recommends curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
rm -f /tmp/apt-packages

# Set the working directory in the container
WORKDIR /app
Expand All @@ -8,16 +18,16 @@ WORKDIR /app
COPY . .

# Install the required dependencies
RUN pip3 install -r requirements.txt
RUN \
pip3 install -r requirements.txt --index-url https://download.pytorch.org/whl/cpu --extra-index-url https://pypi.org/simple && \
pip3 cache purge && \
rm -rf /root/.cache/pip

# Make port 8501 available to anyone outside this container
EXPOSE 8501

# Add a healthcheck to the container
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health

# Set the command to run the Streamlit app (what the image will do when it starts as a container)
#CMD ["streamlit", "run", "app_model.py"]

# Run the Streamlit app
ENTRYPOINT ["streamlit", "run", "app_model.py", "--server.port=8501", "--server.address=0.0.0.0"]
ENTRYPOINT ["streamlit", "run", "app_model.py", "--server.port=8501", "--server.address=0.0.0.0", "--server.headless=true"]
6 changes: 6 additions & 0 deletions forklift-repository.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
forklift-version: v0.7.0

repository:
path: github.com/PlanktoScope/streamlit-classification-app
description: Forklift package for the PlanktoScope OS
readme-file: README.md
17 changes: 17 additions & 0 deletions pkg/compose-frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
server:
networks:
- caddy-ingress
labels:
caddy: :80
caddy.redir: /ps/streamlit-demo /ps/streamlit-demo/
caddy.handle_path: /ps/streamlit-demo/*
caddy.handle_path.reverse_proxy: "{{upstreams 8501}}"
environment:
STREAMLIT_SERVER_BASE_URL_PATH: /ps/streamlit-demo
healthcheck:
test: curl --fail http://localhost:8501/ps/streamlit-demo/_stcore/health || exit 1

networks:
caddy-ingress:
external: true
8 changes: 8 additions & 0 deletions pkg/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
server:
image: ghcr.io/planktoscope/streamlit-classification-app:sha-0703263

networks:
default:
name: none
external: true
33 changes: 33 additions & 0 deletions pkg/forklift-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package:
description: Demo app with a pre-trained demo model for classifying segmented objects
maintainers:
# Note: this is the maintainer of the Forklift package, not the maintainer of the app itself
- name: Ethan Li
email: lietk12@gmail.com
license: Apache-2.0
sources:
- https://github.com/PlanktoScope/streamlit-classification-app

deployment:
compose-files: [compose.yml]

features:
frontend:
description: Provides access to a browser landing page
compose-files: [compose-frontend.yml]
requires:
networks:
- description: Overlay network for Caddy to connect to upstream services
name: caddy-ingress
services:
- tags: [caddy-docker-proxy]
port: 80
protocol: http
provides:
services:
- description: PlanktoScope documentation site
port: 80
protocol: http
paths:
- /ps/streamlit-demo
- /ps/streamlit-demo/*
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
streamlit
opencv-python
opencv-python-headless==4.6.0.66
numpy
seaborn
matplotlib
plotly
Pillow
torch
torchvision
torchvision