From edf0d862228fb69ed7aa25e6ac71a322494c3c29 Mon Sep 17 00:00:00 2001 From: felix-wang <35718120+numb3r3@users.noreply.github.com> Date: Wed, 11 May 2022 15:57:23 +0800 Subject: [PATCH] feat: add dockerfiles and cd workflow (#712) * feat: add dockerfiles and GH runer * fix: turn on docker build action * fix: docker push runner * fix: docker push runner * fix: docker push runner * fix: test cuda dockerfile * fix: test cuda dockerfile * fix: cuda * fix: cuda * fix: cuda * fix: cuda * fix: cuda * fix: cuda * fix: cuda * fix: cuda * fix: update runner --- .dockerignore | 4 + .github/workflows/force-docker-build.yml | 128 ++++++++++++++++++ Dockerfiles/base.Dockerfile | 40 ++++++ Dockerfiles/cuda.Dockerfile | 44 ++++++ Dockerfiles/tensorrt.Dockerfile | 34 +++++ docs/user-guides/server.md | 2 +- .../{clip_trt.py => clip_tensorrt.py} | 0 server/clip_server/tensorrt-flow.yml | 2 +- tests/conftest.py | 2 +- 9 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/force-docker-build.yml create mode 100644 Dockerfiles/base.Dockerfile create mode 100644 Dockerfiles/cuda.Dockerfile create mode 100644 Dockerfiles/tensorrt.Dockerfile rename server/clip_server/executors/{clip_trt.py => clip_tensorrt.py} (100%) diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..77f9cc755 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git +.github +scripts +docs \ No newline at end of file diff --git a/.github/workflows/force-docker-build.yml b/.github/workflows/force-docker-build.yml new file mode 100644 index 000000000..6ec6e3105 --- /dev/null +++ b/.github/workflows/force-docker-build.yml @@ -0,0 +1,128 @@ +name: Manual Docker Build + +on: + workflow_dispatch: + inputs: + release_token: + description: 'Your release token' + required: true + triggered_by: + description: 'CD | TAG | MANUAL' + required: false + default: MANUAL + +jobs: + token-check: + runs-on: ubuntu-latest + steps: + - run: echo "success!" + if: "${{ github.event.inputs.release_token }} == ${{ env.release_token }}" + env: + release_token: ${{ secrets.CAS_RELEASE_TOKEN }} + + regular-release: + needs: token-check + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + pip_tag: [ "", "onnx"] # default: "" = torch + engine_tag: ["", "cuda"] # default: "" = cpu + steps: + - uses: actions/checkout@v2 + - name: Set envs and versions + run: | + VCS_REF=${{ github.ref }} + echo "VCS_REF=$VCS_REF" >> $GITHUB_ENV + echo "Will build $VCS_REF" + echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV + echo "BUILD_TARGET=clip_executor" >> $GITHUB_ENV + + CAS_VERSION=$(sed -n '/^__version__/p' ./server/clip_server/__init__.py | cut -d \' -f2) + V_CAS_VERSION=v${CAS_VERSION} + CAS_MINOR_VERSION=${CAS_VERSION%.*} + CAS_MAJOR_VERSION=${CAS_MINOR_VERSION%.*} + + ENGINE_TAG=${{matrix.engine_tag}} + if [ -n "${ENGINE_TAG}" ]; then + ENGINE_TAG=-${ENGINE_TAG//./} + fi + + PIP_TAG=${{ matrix.pip_tag }} + if [ -n "${PIP_TAG}" ]; then + PIP_TAG=-${PIP_TAG} + fi + + if [[ "${{ github.event.inputs.triggered_by }}" == "CD" ]]; then + # on every CD release + echo "TAG_ALIAS=\ + jinaai/clip_executor:master${PIP_TAG}${ENGINE_TAG}" \ + >> $GITHUB_ENV + + elif [[ "${{ github.event.inputs.triggered_by }}" == "TAG" ]]; then + # on every tag release + echo "TAG_ALIAS=\ + jinaai/clip_executor:latest${PIP_TAG}${ENGINE_TAG}, \ + jinaai/clip_executor:${CAS_VERSION}${PIP_TAG}${ENGINE_TAG}, \ + jinaai/clip_executor:${CAS_MINOR_VERSION}${PIP_TAG}${ENGINE_TAG}, \ + jinaai/clip_executor:${CAS_MAJOR_VERSION}${PIP_TAG}${ENGINE_TAG} \ + " >> $GITHUB_ENV + + elif [[ "${{ github.event.inputs.triggered_by }}" == "MANUAL" ]]; then + # on every manual release + echo "TAG_ALIAS=\ + jinaai/clip_executor:${CAS_VERSION}${PIP_TAG}${ENGINE_TAG} \ + " >> $GITHUB_ENV + else + # test + echo "Debugging Workflow!" + echo "TAG_ALIAS=\ + jinaai/clip_executor:${CAS_VERSION}${PIP_TAG}${ENGINE_TAG} \ + " >> $GITHUB_ENV + fi + + echo "CAS_VERSION=${CAS_VERSION}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_DEVBOT_USER }} + password: ${{ secrets.DOCKERHUB_DEVBOT_TOKEN }} + - run: | + # https://github.com/docker/buildx/issues/464#issuecomment-741507760 + # https://github.com/kubernetes-sigs/azuredisk-csi-driver/pull/808/files + docker run --privileged --rm tonistiigi/binfmt --uninstall qemu-aarch64 + docker run --rm --privileged tonistiigi/binfmt --install all + - name: CPU Build and push + uses: docker/build-push-action@v2 + if: ${{ matrix.engine_tag }} == '' + with: + context: . + file: Dockerfiles/base.Dockerfile + platforms: linux/amd64 + push: true + tags: ${{env.TAG_ALIAS}} + build-args: | + BUILD_DATE=${{env.BUILD_DATE}} + CAS_VERSION=${{env.CAS_VERSION}} + VCS_REF=${{env.VCS_REF}} + PIP_TAG=${{matrix.pip_tag}} + - name: CUDA Build and push + uses: docker/build-push-action@v2 + if: ${{ matrix.engine_tag }} == 'cuda' + with: + context: . + file: Dockerfiles/cuda.Dockerfile + platforms: linux/amd64 + push: true + tags: ${{env.TAG_ALIAS}} + build-args: | + BUILD_DATE=${{env.BUILD_DATE}} + CAS_VERSION=${{env.CAS_VERSION}} + VCS_REF=${{env.VCS_REF}} + PIP_TAG=${{matrix.pip_tag}} diff --git a/Dockerfiles/base.Dockerfile b/Dockerfiles/base.Dockerfile new file mode 100644 index 000000000..8ad9f87d7 --- /dev/null +++ b/Dockerfiles/base.Dockerfile @@ -0,0 +1,40 @@ +# !!! An ARG declared before a FROM is outside of a build stage, so it can’t be used in any instruction after a FROM +ARG JINA_VERSION=3.3.25 + +FROM jinaai/jina:${JINA_VERSION}-py38-standard + +ARG PIP_TAG + +# constant, wont invalidate cache +LABEL org.opencontainers.image.vendor="Jina AI Limited" \ + org.opencontainers.image.licenses="Apache 2.0" \ + org.opencontainers.image.title="Clip-As-Service" \ + org.opencontainers.image.description="Embed images and sentences into fixed-length vectors with CLIP" \ + org.opencontainers.image.authors="hello@jina.ai" \ + org.opencontainers.image.url="clip-as-service" \ + org.opencontainers.image.documentation="https://clip-as-service.jina.ai/" + +RUN pip3 install --no-cache-dir torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cpu + +# copy will almost always invalid the cache +COPY . /clip-as-service/ + +RUN echo '\ +jtype: CLIPEncoder\n\ +with:\n\ + name: ${{ env.MODEL_NAME }}\n\ + device: ${{ env.DEVICE }}\n\ + minibatch_size: ${{ env.MINIBATCH_SIZE }}\n\ +metas:\n\ + py_modules:\n\ + - server/clip_server/executors/clip_${{ env.ENGINE }}.py\n\ +' > /tmp/config.yml + +RUN cd /clip-as-service && \ + if [ -n "$PIP_TAG" ]; then pip3 install --no-cache-dir server/"[$PIP_TAG]" ; fi && \ + pip3 install --no-cache-dir "server/" + +WORKDIR /clip-as-service + + +ENTRYPOINT ["jina", "executor", "--uses", "/tmp/config.yml"] diff --git a/Dockerfiles/cuda.Dockerfile b/Dockerfiles/cuda.Dockerfile new file mode 100644 index 000000000..c7265d045 --- /dev/null +++ b/Dockerfiles/cuda.Dockerfile @@ -0,0 +1,44 @@ +ARG CUDA_VERSION=11.4.2 + +FROM nvcr.io/nvidia/cuda:${CUDA_VERSION}-cudnn8-runtime-ubuntu20.04 +ENV DEBIAN_FRONTEND=noninteractive + +ARG JINA_VERSION=3.3.25 +ARG PIP_TAG + +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3-setuptools python3-wheel python3-pip \ + && apt-get clean && rm -rf /var/lib/apt/lists/*; + +RUN python3 -m pip install --default-timeout=1000 --no-cache-dir torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113 +RUN python3 -m pip install --default-timeout=1000 --no-cache-dir "jina[standard]==${JINA_VERSION}" + +RUN python3 -m pip install nvidia-pyindex + +# copy will almost always invalid the cache +COPY . /clip-as-service/ + + +RUN echo '\ +jtype: CLIPEncoder\n\ +with:\n\ + name: ${{ env.MODEL_NAME }}\n\ + device: ${{ env.DEVICE }}\n\ + minibatch_size: ${{ env.MINIBATCH_SIZE }}\n\ +metas:\n\ + py_modules:\n\ + - server/clip_server/executors/clip_${{ env.ENGINE }}.py\n\ +' > /tmp/config.yml + +RUN cd /clip-as-service && \ + if [ -n "${PIP_TAG}" ]; then python3 -m pip install --no-cache-dir server/"[${PIP_TAG}]" ; fi && \ + python3 -m pip install --no-cache-dir "server/" + +WORKDIR /clip-as-service + +ENTRYPOINT ["jina", "executor", "--uses", "/tmp/config.yml"] + + + + + diff --git a/Dockerfiles/tensorrt.Dockerfile b/Dockerfiles/tensorrt.Dockerfile new file mode 100644 index 000000000..190ac9db1 --- /dev/null +++ b/Dockerfiles/tensorrt.Dockerfile @@ -0,0 +1,34 @@ +# Dockerfile to run Clip-as-Service with TensorRT, CUDA integration + +ARG TENSORRT_VERSION=22.04 + +FROM nvcr.io/nvidia/tensorrt:${TENSORRT_VERSION}-py3 + +ARG JINA_VERSION=3.3.25 +ARG PIP_VERSION + +RUN pip3 install --default-timeout=1000 --no-cache-dir torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113 +RUN pip3 -m pip install --default-timeout=1000 --no-cache-dir "jina[standard]==${JINA_VERSION}" + + +# copy will almost always invalid the cache +COPY . /clip-as-service/ + +RUN pip3 install --no-cache-dir "server/[tensorrt]" + +RUN echo '\ +jtype: CLIPEncoder\n\ +with:\n\ + name: ${{ env.MODEL_NAME }}\n\ + device: cuda\n\ + minibatch_size: ${{ env.MINIBATCH_SIZE }}\n\ +metas:\n\ + py_modules:\n\ + - server/clip_server/executors/clip_${{ env.ENGINE }}.py\n\ +' > /tmp/config.yml + + +WORKDIR /clip-as-service + +ENTRYPOINT ["jina", "executor", "--uses", "/tmp/config.yml"] + diff --git a/docs/user-guides/server.md b/docs/user-guides/server.md index 03ee3ef72..fd87bbdac 100644 --- a/docs/user-guides/server.md +++ b/docs/user-guides/server.md @@ -132,7 +132,7 @@ executors: jtype: CLIPEncoder metas: py_modules: - - executors/clip_trt.py + - executors/clip_tensorrt.py ``` ```` diff --git a/server/clip_server/executors/clip_trt.py b/server/clip_server/executors/clip_tensorrt.py similarity index 100% rename from server/clip_server/executors/clip_trt.py rename to server/clip_server/executors/clip_tensorrt.py diff --git a/server/clip_server/tensorrt-flow.yml b/server/clip_server/tensorrt-flow.yml index 3f37763e1..fb1910981 100644 --- a/server/clip_server/tensorrt-flow.yml +++ b/server/clip_server/tensorrt-flow.yml @@ -8,5 +8,5 @@ executors: jtype: CLIPEncoder metas: py_modules: - - executors/clip_trt.py + - executors/clip_tensorrt.py diff --git a/tests/conftest.py b/tests/conftest.py index 078d24985..b847b2789 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,7 +39,7 @@ def make_torch_flow(port_generator, request): @pytest.fixture(scope='session', params=['torch']) def make_trt_flow(port_generator, request): - from clip_server.executors.clip_trt import CLIPEncoder + from clip_server.executors.clip_tensorrt import CLIPEncoder f = Flow(port=port_generator()).add(name=request.param, uses=CLIPEncoder) with f: