From d2ee117a0a21a3944c0ba0b41d95f097ef18e3f0 Mon Sep 17 00:00:00 2001 From: Chaoqun <27287694+OpenWaygate@users.noreply.github.com> Date: Fri, 22 Dec 2023 19:16:02 +0800 Subject: [PATCH] docker : Dockerize whisper.cpp (#1674) * build: add dockerfile for ci * ci: add action to build/push docker image * fix: lowercase repository to fix ci * ci: update cuBLAS flag * build: install curl and ffmped in image * docs: add docker section * fix: improve args check when download model --- .devops/main-cuda.Dockerfile | 34 +++++++++++++++++++++ .devops/main.Dockerfile | 19 ++++++++++++ .github/workflows/docker.yml | 57 +++++++++++++++++++++++++++++++++++ README.md | 31 +++++++++++++++++++ models/download-ggml-model.sh | 10 +++--- 5 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 .devops/main-cuda.Dockerfile create mode 100644 .devops/main.Dockerfile create mode 100644 .github/workflows/docker.yml diff --git a/.devops/main-cuda.Dockerfile b/.devops/main-cuda.Dockerfile new file mode 100644 index 0000000..0ce7642 --- /dev/null +++ b/.devops/main-cuda.Dockerfile @@ -0,0 +1,34 @@ +ARG UBUNTU_VERSION=22.04 +# This needs to generally match the container host's environment. +ARG CUDA_VERSION=12.3.1 +# Target the CUDA build image +ARG BASE_CUDA_DEV_CONTAINER=nvidia/cuda:${CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} +# Target the CUDA runtime image +ARG BASE_CUDA_RUN_CONTAINER=nvidia/cuda:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_VERSION} + +FROM ${BASE_CUDA_DEV_CONTAINER} AS build +WORKDIR /app + +# Unless otherwise specified, we make a fat build. +ARG CUDA_DOCKER_ARCH=all +# Set nvcc architecture +ENV CUDA_DOCKER_ARCH=${CUDA_DOCKER_ARCH} +# Enable cuBLAS +ENV WHISPER_CUBLAS=1 + +RUN apt-get update && \ + apt-get install -y build-essential \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY .. . +RUN make + +FROM ${BASE_CUDA_RUN_CONTAINER} AS runtime +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y curl ffmpeg \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY --from=build /app /app +ENTRYPOINT [ "bash", "-c" ] diff --git a/.devops/main.Dockerfile b/.devops/main.Dockerfile new file mode 100644 index 0000000..f923a90 --- /dev/null +++ b/.devops/main.Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:22.04 AS build +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y build-essential \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY .. . +RUN make + +FROM ubuntu:22.04 AS runtime +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y curl ffmpeg \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY --from=build /app /app +ENTRYPOINT [ "bash", "-c" ] diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..c5a80f2 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,57 @@ +name: Publish Docker image + +on: + pull_request: + push: + branches: + - master + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + if: github.event.pull_request.draft == false + + runs-on: ubuntu-latest + env: + COMMIT_SHA: ${{ github.sha }} + strategy: + matrix: + config: + - { tag: "main", dockerfile: ".devops/main.Dockerfile", platform: "linux/amd64,linux/arm64" } + - { tag: "main-cuda", dockerfile: ".devops/main-cuda.Dockerfile", platform: "linux/amd64" } + + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - 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 Docker Hub + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image (versioned) + if: github.event_name == 'push' + uses: docker/build-push-action@v5 + with: + context: . + push: true + platforms: ${{ matrix.config.platforms }} + tags: "ghcr.io/${{ github.repository }}:${{ matrix.config.tag }}-${{ env.COMMIT_SHA }}" + file: ${{ matrix.config.dockerfile }} + + - name: Build and push Docker image (tagged) + uses: docker/build-push-action@v4 + with: + context: . + push: ${{ github.event_name == 'push' }} + platforms: ${{ matrix.config.platforms }} + tags: "ghcr.io/${{ github.repository }}:${{ matrix.config.tag }}" + file: ${{ matrix.config.dockerfile }} diff --git a/README.md b/README.md index 3407635..225d17c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Supported platforms: - [x] [WebAssembly](examples/whisper.wasm) - [x] Windows ([MSVC](https://github.com/ggerganov/whisper.cpp/blob/master/.github/workflows/build.yml#L117-L144) and [MinGW](https://github.com/ggerganov/whisper.cpp/issues/168)] - [x] [Raspberry Pi](https://github.com/ggerganov/whisper.cpp/discussions/166) +- [x] [docker](https://github.com/ggerganov/whisper.cpp/pkgs/container/whisper.cpp) The entire high-level implementation of the model is contained in [whisper.h](whisper.h) and [whisper.cpp](whisper.cpp). The rest of the code is part of the [ggml](https://github.com/ggerganov/ggml) machine learning library. @@ -448,6 +449,36 @@ make clean WHISPER_OPENBLAS=1 make -j ``` +## Docker + +### Prerequisites +* Docker must be installed and running on your system. +* Create a folder to store big models & intermediate files (ex. /whisper/models) + +### Images +We have two Docker images available for this project: + +1. `ghcr.io/ggerganov/whisper.cpp:main`: This image includes the main executable file as well as `curl` and `ffmpeg`. (platforms: `linux/amd64`, `linux/arm64`) +2. `ghcr.io/ggerganov/whisper.cpp:main-cuda`: Same as `main` but compiled with CUDA support. (platforms: `linux/amd64`) + +### Usage + +```shell +# download model and persist it in a local folder +docker run -it --rm \ + -v path/to/models:/models \ + whisper.cpp:main "./models/download-ggml-model.sh base /models" +# transcribe an audio file +docker run -it --rm \ + -v path/to/models:/models \ + -v path/to/audios:/audios \ + whisper.cpp:main "./main -m /models/ggml-base.bin -f /audios/jfk.wav" +# transcribe an audio file in samples folder +docker run -it --rm \ + -v path/to/models:/models \ + whisper.cpp:main "./main -m /models/ggml-base.bin -f ./samples/jfk.wav" +``` + ## Limitations - Inference only diff --git a/models/download-ggml-model.sh b/models/download-ggml-model.sh index 9c0119c..f4b611f 100755 --- a/models/download-ggml-model.sh +++ b/models/download-ggml-model.sh @@ -19,7 +19,7 @@ function get_script_path() { fi } -models_path="$(get_script_path)" +models_path="${2:-$(get_script_path)}" # Whisper models models=( @@ -56,8 +56,8 @@ function list_models { printf "\n\n" } -if [ "$#" -ne 1 ]; then - printf "Usage: $0 \n" +if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then + printf "Usage: $0 [models_path]\n" list_models exit 1 @@ -105,7 +105,7 @@ if [ $? -ne 0 ]; then exit 1 fi -printf "Done! Model '$model' saved in 'models/ggml-$model.bin'\n" +printf "Done! Model '$model' saved in '$models_path/ggml-$model.bin'\n" printf "You can now use it like this:\n\n" -printf " $ ./main -m models/ggml-$model.bin -f samples/jfk.wav\n" +printf " $ ./main -m $models_path/ggml-$model.bin -f samples/jfk.wav\n" printf "\n"