diff --git a/README.md b/README.md index 201d620..b484ae1 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This repository contains examples of Docker images that are valid custom images ### Examples - [echo-kernel-image](examples/echo-kernel-image) - This example uses the echo_kernel from Jupyter as a "Hello World" introduction into writing custom KernelGateway images. +- [beakerx](examples/beakerx-image) - This example uses the `BeakerX` kernel see [BeakerX](http://beakerx.com/) which allows you to use Java, Groovy, Scala, Kotlin, Clojure languages. - [jupyter-docker-stacks-julia-image](examples/jupyter-docker-stacks-julia-image) - This example leverages the Data Science image from Jupyter Docker Stacks to add a Julia kernel. - [r-image](examples/r-image) - This example contains the `ir` kernel and a selection of R packages, along with the AWS Python SDK (boto3) and the SageMaker Python SDK which can be used from R using `reticulate` - [rapids-image](examples/rapids-image) - This example uses the offical rapids.ai image from Dockerhub. Use with a GPU instance on Studio @@ -28,4 +29,4 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) ### License -This sample code is licensed under the MIT-0 License. See the LICENSE file. \ No newline at end of file +This sample code is licensed under the MIT-0 License. See the LICENSE file. diff --git a/examples/beakerx-image/Dockerfile b/examples/beakerx-image/Dockerfile new file mode 100644 index 0000000..a53e1a2 --- /dev/null +++ b/examples/beakerx-image/Dockerfile @@ -0,0 +1,96 @@ +# This project is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD), as follows: + +# Copyright (c) 2001-2015, IPython Development Team +# Copyright (c) 2015-, Jupyter Development Team + +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +# Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +# Neither the name of the Jupyter Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +FROM python:3.6 + +ARG NB_USER="sagemaker-user" +ARG NB_UID="1000" +ARG NB_GID="100" + +# Setup the "sagemaker-user" user with root privileges. +RUN \ + apt-get update && \ + apt-get install -y sudo && \ + useradd -m -s /bin/bash -N -u $NB_UID $NB_USER && \ + chmod g+w /etc/passwd && \ + echo "${NB_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ + # Prevent apt-get cache from being persisted to this layer. + rm -rf /var/lib/apt/lists/* + +USER $NB_UID + +# Make the default shell bash (vs "sh") for a better Jupyter terminal UX +ENV SHELL=/bin/bash \ + NB_USER=$NB_USER \ + NB_UID=$NB_UID \ + NB_GID=$NB_GID \ + HOME=/home/$NB_USER \ + MINICONDA_VERSION=4.6.14 \ + CONDA_VERSION=4.6.14 \ + MINICONDA_MD5=718259965f234088d785cad1fbd7de03 \ + CONDA_DIR=/opt/conda \ + PATH=$CONDA_DIR/bin:${PATH} + +# Heavily inspired from https://github.com/jupyter/docker-stacks/blob/master/r-notebook/Dockerfile + +USER root + +# R system library pre-requisites +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + fonts-dejavu \ + unixodbc \ + unixodbc-dev \ + r-cran-rodbc \ + gfortran \ + gcc && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir -p $CONDA_DIR && \ + chown -R $NB_USER:$NB_GID $CONDA_DIR && \ + # Fix for devtools https://github.com/conda-forge/r-devtools-feedstock/issues/4 + ln -s /bin/tar /bin/gtar + +USER $NB_UID + +ENV PATH=$CONDA_DIR/bin:${PATH} + +# Install conda via Miniconda +RUN cd /tmp && \ + curl --silent --show-error --output miniconda-installer.sh https://repo.anaconda.com/miniconda/Miniconda3-${MINICONDA_VERSION}-Linux-x86_64.sh && \ + echo "${MINICONDA_MD5} *miniconda-installer.sh" | md5sum -c - && \ + /bin/bash miniconda-installer.sh -f -b -p $CONDA_DIR && \ + rm miniconda-installer.sh && \ + conda config --system --prepend channels conda-forge && \ + conda config --system --set auto_update_conda false && \ + conda config --system --set show_channel_urls true && \ + conda install --quiet --yes conda="${CONDA_VERSION%.*}.*" && \ + conda update --all --quiet --yes && \ + conda clean --all -f -y && \ + rm -rf /home/$NB_USER/.cache/yarn + + +# beakerx +RUN conda install --quiet --yes \ + 'ipywidgets' \ + 'beakerx' \ + && \ + pip install --quiet --no-cache-dir \ + 'boto3>1.0<2.0' \ + 'sagemaker>2.0<3.0' && \ + conda clean --all -f -y + +WORKDIR $HOME +USER $NB_UID diff --git a/examples/beakerx-image/README.md b/examples/beakerx-image/README.md new file mode 100644 index 0000000..ace425f --- /dev/null +++ b/examples/beakerx-image/README.md @@ -0,0 +1,67 @@ +## R Image + +### Overview + +> NOTE: This Dockerfile installs dependencies that may be licensed under copyleft licenses such as GPLv3. You should review the license terms and make sure they are acceptable for your use case before proceeding and downloading this image. + +A BeakerX kernel that is a compatible as a Bring-Your-Own Image in SageMaker Studio.BeakerX permits you to use JVM kernels such as Java, Scala, Kotlin, Groovy, and SQL. + +The image contains a selection of BeakerX, along with the AWS Python SDK (boto3) and the SageMaker Python SDK. + +### Building the image + +Build the Docker image and push to Amazon ECR. +``` +# Modify these as required. The Docker registry endpoint can be tuned based on your current region from https://docs.aws.amazon.com/general/latest/gr/ecr.html#ecr-docker-endpoints +REGION= +ACCOUNT_ID= + + +# Build the image +IMAGE_NAME=custom-beakerx +aws --region ${REGION} ecr get-login-password | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/smstudio-custom +docker build . -t ${IMAGE_NAME} -t ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/smstudio-custom:${IMAGE_NAME} +``` + +``` +docker push ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/smstudio-custom:${IMAGE_NAME} +``` + +### Using with SageMaker Studio + +Create a SageMaker Image with the image in ECR. + +``` +# Role in your account to be used for the SageMaker Image +ROLE_ARN= + +aws --region ${REGION} sagemaker create-image \ + --image-name ${IMAGE_NAME} \ + --role-arn ${ROLE_ARN} + +aws --region ${REGION} sagemaker create-image-version \ + --image-name ${IMAGE_NAME} \ + --base-image "${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/smstudio-custom:${IMAGE_NAME}" + +# Verify the image-version is created successfully. Do NOT proceed if image-version is in CREATE_FAILED state or in any other state apart from CREATED. +aws --region ${REGION} sagemaker describe-image-version --image-name ${IMAGE_NAME} +``` + +Create a AppImageConfig for this image + +``` +aws --region ${REGION} sagemaker create-app-image-config --cli-input-json file://app-image-config-input.json + +``` + +Create a Domain, providing the SageMaker Image and AppImageConfig in the Domain creation. Replace the placeholders for VPC ID, Subnet IDs, and Execution Role in `create-domain-input.json` + +``` +aws --region ${REGION} sagemaker create-domain --cli-input-json file://create-domain-input.json +``` + +If you have an existing Domain, you can also use the `update-domain` + +``` +aws --region ${REGION} sagemaker update-domain --cli-input-json file://update-domain-input.json +``` diff --git a/examples/beakerx-image/app-image-config-input.json b/examples/beakerx-image/app-image-config-input.json new file mode 100644 index 0000000..53250d2 --- /dev/null +++ b/examples/beakerx-image/app-image-config-input.json @@ -0,0 +1,16 @@ +{ + "AppImageConfigName": "custom-beakerx-image-config", + "KernelGatewayImageConfig": { + "KernelSpecs": [ + { + "Name": "java", + "DisplayName": "java" + } + ], + "FileSystemConfig": { + "MountPath": "/home/sagemaker-user", + "DefaultUid": 1000, + "DefaultGid": 100 + } + } +} diff --git a/examples/beakerx-image/create-domain-input.json b/examples/beakerx-image/create-domain-input.json new file mode 100644 index 0000000..264ee4c --- /dev/null +++ b/examples/beakerx-image/create-domain-input.json @@ -0,0 +1,19 @@ +{ + "DomainName": "domain-with-custom-beakerx-image", + "VpcId": "", + "SubnetIds": [ + "" + ], + "DefaultUserSettings": { + "ExecutionRole": "", + "KernelGatewayAppSettings": { + "CustomImages": [ + { + "ImageName": "custom-beakerx", + "AppImageConfigName": "custom-beakerx-image-config" + } + ] + } + }, + "AuthMode": "IAM" +} diff --git a/examples/beakerx-image/update-domain-input.json b/examples/beakerx-image/update-domain-input.json new file mode 100644 index 0000000..d60edb9 --- /dev/null +++ b/examples/beakerx-image/update-domain-input.json @@ -0,0 +1,13 @@ +{ + "DomainId": "", + "DefaultUserSettings": { + "KernelGatewayAppSettings": { + "CustomImages": [ + { + "ImageName": "custom-beakerx", + "AppImageConfigName": "custom-beakerx-image-config" + } + ] + } + } +}