feat: cleanup Dockerfile and make final image a little smaller (#2146)

* feat: cleanup Dockerfile and make final image a little smaller

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

* fix: add build-essential to final stage

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

* fix: more GRPC cache misses

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

* fix: correct for another cause of GRPC cache misses

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

* feat: generate new GRPC cache automatically if needed

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

* fix: use new GRPC_MAKEFLAGS build arg in GRPC cache generation

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>

---------

Signed-off-by: Chris Jowett <421501+cryptk@users.noreply.github.com>
This commit is contained in:
cryptk 2024-04-27 12:48:20 -05:00 committed by GitHub
parent 164be58445
commit 9fc0135991
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 112 additions and 49 deletions

View File

@ -1,7 +1,10 @@
name: 'generate and publish GRPC docker caches' name: 'generate and publish GRPC docker caches'
on: on:
- workflow_dispatch workflow_dispatch:
push:
branches:
- master
concurrency: concurrency:
group: grpc-cache-${{ github.head_ref || github.ref }}-${{ github.repository }} group: grpc-cache-${{ github.head_ref || github.ref }}-${{ github.repository }}
@ -80,11 +83,12 @@ jobs:
# If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch. # If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch.
build-args: | build-args: |
GRPC_BASE_IMAGE=${{ matrix.grpc-base-image }} GRPC_BASE_IMAGE=${{ matrix.grpc-base-image }}
MAKEFLAGS=--jobs=4 --output-sync=target GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
GRPC_VERSION=v1.58.0 GRPC_VERSION=v1.58.0
context: . context: .
file: ./Dockerfile file: ./Dockerfile
cache-to: type=gha,ignore-error=true cache-to: type=gha,ignore-error=true
cache-from: type=gha
target: grpc target: grpc
platforms: ${{ matrix.platforms }} platforms: ${{ matrix.platforms }}
push: false push: false

View File

@ -210,7 +210,7 @@ jobs:
# If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch. # If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch.
build-args: | build-args: |
GRPC_BASE_IMAGE=${{ inputs.grpc-base-image || inputs.base-image }} GRPC_BASE_IMAGE=${{ inputs.grpc-base-image || inputs.base-image }}
MAKEFLAGS=--jobs=4 --output-sync=target GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
GRPC_VERSION=v1.58.0 GRPC_VERSION=v1.58.0
context: . context: .
file: ./Dockerfile file: ./Dockerfile
@ -225,6 +225,10 @@ jobs:
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
builder: ${{ steps.buildx.outputs.name }} builder: ${{ steps.buildx.outputs.name }}
# The build-args MUST be an EXACT match between the image cache and other workflow steps that want to use that cache.
# This means that even the MAKEFLAGS have to be an EXACT match.
# If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch.
# This is why some build args like GRPC_VERSION and MAKEFLAGS are hardcoded
build-args: | build-args: |
BUILD_TYPE=${{ inputs.build-type }} BUILD_TYPE=${{ inputs.build-type }}
CUDA_MAJOR_VERSION=${{ inputs.cuda-major-version }} CUDA_MAJOR_VERSION=${{ inputs.cuda-major-version }}
@ -232,6 +236,9 @@ jobs:
FFMPEG=${{ inputs.ffmpeg }} FFMPEG=${{ inputs.ffmpeg }}
IMAGE_TYPE=${{ inputs.image-type }} IMAGE_TYPE=${{ inputs.image-type }}
BASE_IMAGE=${{ inputs.base-image }} BASE_IMAGE=${{ inputs.base-image }}
GRPC_BASE_IMAGE=${{ inputs.grpc-base-image || inputs.base-image }}
GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
GRPC_VERSION=v1.58.0
MAKEFLAGS=${{ inputs.makeflags }} MAKEFLAGS=${{ inputs.makeflags }}
context: . context: .
file: ./Dockerfile file: ./Dockerfile

View File

@ -21,22 +21,22 @@ ENV EXTERNAL_GRPC_BACKENDS="coqui:/build/backend/python/coqui/run.sh,huggingface
ARG GO_TAGS="stablediffusion tinydream tts" ARG GO_TAGS="stablediffusion tinydream tts"
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y ca-certificates curl python3-pip unzip && apt-get clean apt-get install -y --no-install-recommends \
ca-certificates \
curl \
python3-pip \
unzip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install Go # Install Go
RUN curl -L -s https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz | tar -C /usr/local -xz RUN curl -L -s https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz | tar -C /usr/local -xz
ENV PATH $PATH:/usr/local/go/bin ENV PATH $PATH:/root/go/bin:/usr/local/go/bin
# Install grpc compilers # Install grpc compilers
ENV PATH $PATH:/root/go/bin
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \ RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Install protobuf (the version in 22.04 is too old)
RUN curl -L -s https://github.com/protocolbuffers/protobuf/releases/download/v26.1/protoc-26.1-linux-x86_64.zip -o protoc.zip && \
unzip -j -d /usr/local/bin protoc.zip bin/protoc && \
rm protoc.zip
# Install grpcio-tools (the version in 22.04 is too old) # Install grpcio-tools (the version in 22.04 is too old)
RUN pip install --user grpcio-tools RUN pip install --user grpcio-tools
@ -49,12 +49,21 @@ RUN echo "Target Variant: $TARGETVARIANT"
# CuBLAS requirements # CuBLAS requirements
RUN if [ "${BUILD_TYPE}" = "cublas" ]; then \ RUN if [ "${BUILD_TYPE}" = "cublas" ]; then \
apt-get install -y software-properties-common && \ apt-get update && \
apt-get install -y --no-install-recommends \
software-properties-common && \
curl -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb && \ curl -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb && \
dpkg -i cuda-keyring_1.1-1_all.deb && \ dpkg -i cuda-keyring_1.1-1_all.deb && \
rm -f cuda-keyring_1.1-1_all.deb && \ rm -f cuda-keyring_1.1-1_all.deb && \
apt-get update && \ apt-get update && \
apt-get install -y cuda-nvcc-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcurand-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcublas-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcusparse-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcusolver-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} && apt-get clean \ apt-get install -y --no-install-recommends \
cuda-nvcc-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} \
libcurand-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} \
libcublas-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} \
libcusparse-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} \
libcusolver-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* \
; fi ; fi
# Cuda # Cuda
@ -64,10 +73,12 @@ ENV PATH /usr/local/cuda/bin:${PATH}
ENV PATH /opt/rocm/bin:${PATH} ENV PATH /opt/rocm/bin:${PATH}
# OpenBLAS requirements and stable diffusion # OpenBLAS requirements and stable diffusion
RUN apt-get install -y \ RUN apt-get update && \
apt-get install -y --no-install-recommends \
libopenblas-dev \ libopenblas-dev \
libopencv-dev \ libopencv-dev && \
&& apt-get clean apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Set up OpenCV # Set up OpenCV
RUN ln -s /usr/include/opencv4/opencv2 /usr/include/opencv2 RUN ln -s /usr/include/opencv4/opencv2 /usr/include/opencv2
@ -82,21 +93,34 @@ RUN test -n "$TARGETARCH" \
FROM requirements-core AS requirements-extras FROM requirements-core AS requirements-extras
RUN apt install -y gpg && \ RUN apt-get update && \
apt-get install -y --no-install-recommends gpg && \
curl https://repo.anaconda.com/pkgs/misc/gpgkeys/anaconda.asc | gpg --dearmor > conda.gpg && \ curl https://repo.anaconda.com/pkgs/misc/gpgkeys/anaconda.asc | gpg --dearmor > conda.gpg && \
install -o root -g root -m 644 conda.gpg /usr/share/keyrings/conda-archive-keyring.gpg && \ install -o root -g root -m 644 conda.gpg /usr/share/keyrings/conda-archive-keyring.gpg && \
gpg --keyring /usr/share/keyrings/conda-archive-keyring.gpg --no-default-keyring --fingerprint 34161F5BF5EB1D4BFBBB8F0A8AEB4F8B29D82806 && \ gpg --keyring /usr/share/keyrings/conda-archive-keyring.gpg --no-default-keyring --fingerprint 34161F5BF5EB1D4BFBBB8F0A8AEB4F8B29D82806 && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" > /etc/apt/sources.list.d/conda.list && \ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" > /etc/apt/sources.list.d/conda.list && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" | tee -a /etc/apt/sources.list.d/conda.list && \ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" | tee -a /etc/apt/sources.list.d/conda.list && \
apt-get update && \ apt-get update && \
apt-get install -y conda && apt-get clean apt-get install -y --no-install-recommends \
conda && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV PATH="/root/.cargo/bin:${PATH}" ENV PATH="/root/.cargo/bin:${PATH}"
RUN apt-get install -y python3-pip && apt-get clean RUN apt-get update && \
RUN pip install --upgrade pip apt-get install -y --no-install-recommends \
python3-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
pip install --upgrade pip
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
RUN apt-get install -y espeak-ng espeak && apt-get clean RUN apt-get update && \
apt-get install -y --no-install-recommends \
espeak-ng \
espeak && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN if [ ! -e /usr/bin/python ]; then \ RUN if [ ! -e /usr/bin/python ]; then \
ln -s /usr/bin/python3 /usr/bin/python \ ln -s /usr/bin/python3 /usr/bin/python \
@ -107,15 +131,20 @@ RUN if [ ! -e /usr/bin/python ]; then \
FROM ${GRPC_BASE_IMAGE} AS grpc FROM ${GRPC_BASE_IMAGE} AS grpc
ARG MAKEFLAGS # This is a bit of a hack, but it's required in order to be able to effectively cache this layer in CI
ARG GRPC_MAKEFLAGS="-j4 -Otarget"
ARG GRPC_VERSION=v1.58.0 ARG GRPC_VERSION=v1.58.0
ENV MAKEFLAGS=${MAKEFLAGS} ENV MAKEFLAGS=${GRPC_MAKEFLAGS}
WORKDIR /build WORKDIR /build
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y build-essential cmake git && \ apt-get install -y --no-install-recommends \
ca-certificates \
build-essential \
cmake \
git && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
@ -123,8 +152,12 @@ RUN git clone --recurse-submodules --jobs 4 -b ${GRPC_VERSION} --depth 1 --shall
WORKDIR /build/grpc/cmake/build WORKDIR /build/grpc/cmake/build
RUN cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF ../.. && \ # We install GRPC to a different prefix here so that we can copy in only the build artifacts later
make # saves several hundred MB on the final docker image size vs copying in the entire GRPC source tree
# and running make install in the target container
RUN cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX:PATH=/opt/grpc ../.. && \
make && \
make install
################################### ###################################
################################### ###################################
@ -149,7 +182,10 @@ COPY .git .
RUN echo "GO_TAGS: $GO_TAGS" RUN echo "GO_TAGS: $GO_TAGS"
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y build-essential cmake git && \ apt-get install -y --no-install-recommends \
build-essential \
cmake \
git && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
@ -158,17 +194,24 @@ RUN make prepare
# If we are building with clblas support, we need the libraries for the builds # If we are building with clblas support, we need the libraries for the builds
RUN if [ "${BUILD_TYPE}" = "clblas" ]; then \ RUN if [ "${BUILD_TYPE}" = "clblas" ]; then \
apt-get update && \ apt-get update && \
apt-get install -y libclblast-dev && \ apt-get install -y --no-install-recommends \
apt-get clean \ libclblast-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* \
; fi ; fi
# We need protoc installed, and the version in 22.04 is too old. We will create one as part installing the GRPC build below
# but that will also being in a newer version of absl which stablediffusion cannot compile with. This version of protoc is only
# here so that we can generate the grpc code for the stablediffusion build
RUN curl -L -s https://github.com/protocolbuffers/protobuf/releases/download/v26.1/protoc-26.1-linux-x86_64.zip -o protoc.zip && \
unzip -j -d /usr/local/bin protoc.zip bin/protoc && \
rm protoc.zip
# stablediffusion does not tolerate a newer version of abseil, build it first # stablediffusion does not tolerate a newer version of abseil, build it first
RUN GRPC_BACKENDS=backend-assets/grpc/stablediffusion make build RUN GRPC_BACKENDS=backend-assets/grpc/stablediffusion make build
COPY --from=grpc /build/grpc ./grpc/ # Install the pre-built GRPC
COPY --from=grpc /opt/grpc /usr/local
WORKDIR /build/grpc/cmake/build
RUN make install
# Rebuild with defaults backends # Rebuild with defaults backends
WORKDIR /build WORKDIR /build
@ -203,18 +246,27 @@ ENV PIP_CACHE_PURGE=true
# Add FFmpeg # Add FFmpeg
RUN if [ "${FFMPEG}" = "true" ]; then \ RUN if [ "${FFMPEG}" = "true" ]; then \
apt-get install -y ffmpeg && apt-get clean \ apt-get update && \
apt-get install -y --no-install-recommends \
ffmpeg && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* \
; fi ; fi
# Add OpenCL # Add OpenCL
RUN if [ "${BUILD_TYPE}" = "clblas" ]; then \ RUN if [ "${BUILD_TYPE}" = "clblas" ]; then \
apt-get update && \ apt-get update && \
apt-get install -y libclblast1 && \ apt-get install -y --no-install-recommends \
apt-get clean \ libclblast1 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* \
; fi ; fi
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y cmake git && \ apt-get install -y --no-install-recommends \
build-essential \
cmake \
git && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
@ -227,9 +279,9 @@ WORKDIR /build
COPY . . COPY . .
COPY --from=builder /build/sources ./sources/ COPY --from=builder /build/sources ./sources/
COPY --from=grpc /build/grpc ./grpc/ COPY --from=grpc /opt/grpc /usr/local
RUN make prepare-sources && cd /build/grpc/cmake/build && make install && rm -rf /build/grpc RUN make prepare-sources
# Copy the binary # Copy the binary
COPY --from=builder /build/local-ai ./ COPY --from=builder /build/local-ai ./