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

Issue 96: Alpine Docker Image to support ML library packages #97

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
45 changes: 45 additions & 0 deletions host/2.0/alpine/amd64/samples/Dockerfile.dotnet-python
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
FROM mcr.microsoft.com/azure-functions/base:2.0 as runtime-image

# From a dotnet alpine image...
FROM microsoft/dotnet:2.2-aspnetcore-runtime-alpine

# Copy Azure Functions Host .NET Dependencies
COPY --from=runtime-image ["/azure-functions-host", "/azure-functions-host"]

# Install Python dependencies
ENV PYENV_ROOT=/root/.pyenv \
PATH=/root/.pyenv/shims:/root/.pyenv/bin:$PATH \
ASPNETCORE_URLS=http://+:80 \
DOTNET_RUNNING_IN_CONTAINER=true \
AzureWebJobsScriptRoot=/home/site/wwwroot \
HOME=/home \
FUNCTIONS_WORKER_RUNTIME=python \
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

# install python and your stuff here.
# libc6-compat needs to be installed https://github.com/grpc/grpc/issues/15605#issuecomment-393974529
RUN apk update && apk add --no-cache python3-dev gcc bash libc6-compat libnsl && \
ln -s /usr/lib/libnsl.so.2 /usr/lib/libnsl.so.1
RUN apk add --no-cache --virtual build-dependencies \
build-base
ENV WORKER_TAG=1.0.0a6 \
AZURE_FUNCTIONS_PACKAGE_VERSION=1.0.0a5 \
LANG=C.UTF-8 \
PYTHON_VERSION=3.6.8 \
PYTHON_PIP_VERSION=19.0 \
ACCEPT_EULA=Y \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN wget https://github.com/Azure/azure-functions-python-worker/archive/$WORKER_TAG.tar.gz && \
tar xvzf $WORKER_TAG.tar.gz && \
mv azure-functions-python-worker-* azure-functions-python-worker && \
cp -R /azure-functions-python-worker/python /azure-functions-host/workers/python && \
rm -rf $WORKER_TAG.tar.gz /azure-functions-python-worker && \
pip3 install azure-functions==$AZURE_FUNCTIONS_PACKAGE_VERSION azure-functions-worker==$WORKER_TAG && \
pip3 install numpy

COPY ./python-context/start.sh ./python-context/worker.config.json /azure-functions-host/workers/python/
RUN chmod +x /azure-functions-host/workers/python/start.sh

# Symlink python to python3
RUN ln -s /usr/bin/python3 /usr/bin/python
CMD [ "dotnet", "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost.dll" ]
85 changes: 85 additions & 0 deletions host/2.0/alpine/amd64/samples/Dockerfile.python-dotnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Stage 1
FROM mcr.microsoft.com/azure-functions/base:2.0 as runtime-image

# Stage 2: Build Wheels
FROM python:3.6-alpine as python-image
COPY --from=runtime-image ["/azure-functions-host", "/azure-functions-host"]
RUN mkdir /tmp/wheels && \
apk add --update --no-cache gcc bash libc6-compat && \
apk add --no-cache --virtual build-dependencies build-base && \
pip3 install wheel
ENV WORKER_TAG=1.0.0a6 \
AZURE_FUNCTIONS_PACKAGE_VERSION=1.0.0a5 \
LANG=C.UTF-8 \
PYTHON_VERSION=3.6.6 \
PYTHON_PIP_VERSION=18.0 \
ACCEPT_EULA=Y \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN wget https://github.com/Azure/azure-functions-python-worker/archive/$WORKER_TAG.tar.gz && \
tar xvzf $WORKER_TAG.tar.gz && \
mv azure-functions-python-worker-* azure-functions-python-worker && \
cp -R /azure-functions-python-worker/python /azure-functions-host/workers/python

# Install as wheels and install any ML libraries as wheels
RUN pip3 wheel --wheel-dir=/tmp/wheels azure-functions==$AZURE_FUNCTIONS_PACKAGE_VERSION azure-functions-worker==$WORKER_TAG numpy
#RUN pip3 wheel -r /home/site/wwwroot/requirements.txt --wheel-dir=/tmp/wheels

# Stage 3
FROM python:3.6-alpine
COPY --from=runtime-image ["/azure-functions-host", "/azure-functions-host"]
RUN mkdir /tmp/wheels
COPY --from=python-image /tmp/wheels /tmp/wheels

# Install libpng-dev freetype-dev openblas-dev to get scipy pandas to run properly.
RUN apk add --no-cache libc6-compat make automake gcc subversion python3-dev && \
pip3 install --no-index --find-links=/tmp/wheels azure-functions azure-functions-worker grpcio grpcio-tools protobuf setuptools six numpy && \
rm -r /tmp/wheels

# Install aspnetcore dotnet core 2.2
RUN apk add --no-cache \
ca-certificates \
\
# .NET Core dependencies
krb5-libs \
libgcc \
libintl \
libssl1.0 \
libstdc++ \
tzdata \
userspace-rcu \
zlib \
&& apk -X https://dl-cdn.alpinelinux.org/alpine/edge/main add --no-cache \
lttng-ust

ARG REPO=microsoft/dotnet
# Configure web servers to bind to port 80 when present
ENV ASPNETCORE_URLS=http://+:80 \
# Enable detection of running in a container
DOTNET_RUNNING_IN_CONTAINER=true \
# Set the invariant mode since icu_libs isn't included (see https://github.com/dotnet/announcements/issues/20)
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

# Install ASP.NET Core
ENV ASPNETCORE_VERSION 2.2.2

RUN apk add --no-cache --virtual .build-deps \
openssl \
&& wget -O aspnetcore.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/$ASPNETCORE_VERSION/aspnetcore-runtime-$ASPNETCORE_VERSION-linux-musl-x64.tar.gz \
&& aspnetcore_sha512='59e2e0eb092d90ba53814c74259f59dcb8aa11b409b908e849aa0d851ec6cef7d1616e02c23d37e84901ca92fd9a6eb05c522ef8668da1fa6a518211532b41ab' \
&& echo "$aspnetcore_sha512 aspnetcore.tar.gz" | sha512sum -c - \
&& mkdir -p /usr/share/dotnet \
&& tar -zxf aspnetcore.tar.gz -C /usr/share/dotnet \
&& rm aspnetcore.tar.gz \
&& ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \
&& apk del .build-deps

ENV AzureWebJobsScriptRoot=/home/site/wwwroot

# Start functions host
CMD [ "dotnet", "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost.dll" ]

# Start python worker
COPY ./python-context/start.sh /azure-functions-host/workers/python/
RUN chmod +x /azure-functions-host/workers/python/start.sh
COPY ./python-context/worker.config.json /azure-functions-host/workers/python/
ENV workers:python:path /azure-functions-host/workers/python/start.sh
74 changes: 74 additions & 0 deletions host/2.0/alpine/amd64/samples/python-context/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#! /bin/bash

# Directory name for start.sh
DIR="$(dirname $0)"

export PYTHONPATH=/root/.pyenv/versions/3.6.6/lib/python3.6:/root/.pyenv/versions/3.6.6/lib/python3.6/site-packages:$PYTHONPATH

# If we're not in a virtual environment, check if either:
# $AZURE_FUNCTIONS_VIRTUAL_ENVIRONMENT is set, use it for venv
# if it's not set and there is a default venv, activate it
# else use the container python
if [ -z "$VIRTUAL_ENV"]
then
# Determining the virtual environment entry point
if [ -z "$AZURE_FUNCTIONS_VIRTUAL_ENVIRONMENT" ]
then
echo "using system python"
else
echo "activating virtual environment"
source $AZURE_FUNCTIONS_VIRTUAL_ENVIRONMENT
fi
fi
if [ -z "$SKIP_PYTHONPATH_UPDATE" ]
then
CUSTOM_PACKAGES="$HOME/site/wwwroot/.python_packages/lib/python3.7/site-packages"
if [ -d "$CUSTOM_PACKAGES" ]
then
echo "appending $CUSTOM_PACKAGES to PYTHONPATH"
export PYTHONPATH=$PYTHONPATH:$CUSTOM_PACKAGES
else
echo "path $CUSTOM_PACKAGES doesn't exist"
fi

CUSTOM_VENV_PACKAGES="$HOME/site/wwwroot/worker_venv/lib/python3.7/site-packages"
if [ -d "$CUSTOM_VENV_PACKAGES" ]
then
echo "appending $CUSTOM_VENV_PACKAGES to PYTHONPATH"
export PYTHONPATH=$PYTHONPATH:$CUSTOM_VENV_PACKAGES
else
echo "path $CUSTOM_VENV_PACKAGES doesn't exist"
fi

CUSTOM_PACKAGES="$HOME/site/wwwroot/.python_packages/lib/python3.6/site-packages"
if [ -d "$CUSTOM_PACKAGES" ]
then
echo "appending $CUSTOM_PACKAGES to PYTHONPATH"
export PYTHONPATH=$PYTHONPATH:$CUSTOM_PACKAGES
else
echo "path $CUSTOM_PACKAGES doesn't exist"
fi

CUSTOM_VENV_PACKAGES="$HOME/site/wwwroot/worker_venv/lib/python3.6/site-packages"
if [ -d "$CUSTOM_VENV_PACKAGES" ]
then
echo "appending $CUSTOM_VENV_PACKAGES to PYTHONPATH"
export PYTHONPATH=$PYTHONPATH:$CUSTOM_VENV_PACKAGES
else
echo "path $CUSTOM_VENV_PACKAGES doesn't exist"
fi
else
echo "SKIP_PYTHONPATH_UPDATE == $SKIP_PYTHONPATH_UPDATE"
fi

echo "python == $(which python)"
echo "PYTHONPATH == $PYTHONPATH"

echo "starting the python worker"
if [ -f $HOME/site/wwwroot/worker-bundle/worker-bundle ]
then
chmod +x $HOME/site/wwwroot/worker-bundle/worker-bundle
$HOME/site/wwwroot/worker-bundle/worker-bundle $@
else
python $DIR/worker.py $@
fi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"description":{
"language":"python",
"extensions":[".py"],
"defaultExecutablePath":"bash",
"defaultWorkerPath":"start.sh"
}
}