Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
Adds python docker image pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
perdasilva committed Oct 11, 2019
1 parent 6c0b108 commit 0dba0ad
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 346 deletions.
14 changes: 11 additions & 3 deletions cd/Jenkinsfile_cd_pipeline
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,17 @@ pipeline {
stage("Build") {
cd_utils.trigger_release_job("Build static libmxnet", "mxnet_lib/static", params.MXNET_VARIANTS)
}
stage("PyPI Release") {
echo "Building PyPI Release"
cd_utils.trigger_release_job("Release PyPI Packages", "python/pypi", params.MXNET_VARIANTS)
stage("Releases") {
cd_utils.error_checked_parallel([
"PyPI Release": {
echo "Building PyPI Release"
cd_utils.trigger_release_job("Release PyPI Packages", "python/pypi", params.MXNET_VARIANTS)
},
"Python Docker Release": {
echo "Building Python Docker Release"
cd_utils.trigger_release_job("Release Python Docker Images", "python/docker", params.MXNET_VARIANTS)
}
])
}
},

Expand Down
38 changes: 38 additions & 0 deletions cd/python/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- mode: dockerfile -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Python MXNet Dockerfile

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

ARG MXNET_COMMIT_ID
ENV MXNET_COMMIT_ID=${MXNET_COMMIT_ID}

RUN mkdir -p /mxnet
COPY wheel_build/dist/*.whl /mxnet/.

ARG PYTHON_CMD=python
RUN apt-get update && \
apt-get install -y wget ${PYTHON_CMD}-dev gcc && \
wget https://bootstrap.pypa.io/get-pip.py && \
${PYTHON_CMD} get-pip.py

WORKDIR /mxnet
RUN WHEEL_FILE=$(ls -t /mxnet | head -n 1) && pip install ${WHEEL_FILE} && rm -f ${WHEEL_FILE}

35 changes: 35 additions & 0 deletions cd/python/docker/Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- mode: dockerfile -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Python MXNet Dockerfile

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

ARG USER_ID=1001
ARG GROUP_ID=1001

# Install test dependencies
RUN pip install nose

RUN groupadd --gid $GROUP_ID --system jenkins_slave
RUN useradd -m --no-log-init --uid $USER_ID --gid $GROUP_ID --system jenkins_slave

RUN mkdir -p /mxnet && chown -R jenkins_slave /mxnet

WORKDIR /mxnet
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,46 @@ def get_pipeline(mxnet_variant) {
return cd_utils.generic_pipeline(mxnet_variant, this, node_type)
}

// Returns the (Docker) environment for the given variant
// The environment corresponds to the docker files in the 'docker' directory
def get_environment(mxnet_variant) {
def environment = "ubuntu_cpu"
if (mxnet_variant.startsWith('cu')) {
environment = "ubuntu_gpu_${mxnet_variant}".replace("mkl", "")
if (mxnet_variant.startsWith("cu")) {
// Remove 'mkl' suffix from variant to properly format test environment
return "ubuntu_gpu_${mxnet_variant.replace('mkl', '')}"
}
return environment
return "ubuntu_cpu"
}


def build(mxnet_variant) {
ws("workspace/python_pypi/${mxnet_variant}/${env.BUILD_NUMBER}") {
ws("workspace/python_docker/${mxnet_variant}/${env.BUILD_NUMBER}") {
ci_utils.init_git()
cd_utils.restore_artifact(mxnet_variant, 'static')

// create wheel file
def environment = get_environment(mxnet_variant)

// package wheel file
def nvidia_docker = mxnet_variant.startsWith('cu')
ci_utils.docker_run(environment, "cd_package_pypi ${mxnet_variant}", nvidia_docker, '500m', "RELEASE_BUILD='${env.RELEASE_BUILD}'")
def environment = get_environment(mxnet_variant)
ci_utils.docker_run(environment, "cd_package_pypi ${mxnet_variant}", nvidia_docker)

// build python docker images
sh "./cd/python/docker/python_images.sh build ${mxnet_variant} py3"
sh "./cd/python/docker/python_images.sh build ${mxnet_variant} py2"
}
}

def test(mxnet_variant) {
ws("workspace/python_pypi/${mxnet_variant}/${env.BUILD_NUMBER}") {
// test wheel file
def environment = get_environment(mxnet_variant)
def nvidia_docker = mxnet_variant.startsWith('cu')
ci_utils.docker_run(environment, "cd_integration_test_pypi python ${nvidia_docker}", nvidia_docker)
ci_utils.docker_run(environment, "cd_integration_test_pypi python3 ${nvidia_docker}", nvidia_docker)
ws("workspace/python_docker/${mxnet_variant}/${env.BUILD_NUMBER}") {
// test python docker images
sh "./cd/python/docker/python_images.sh test ${mxnet_variant} py3"
sh "./cd/python/docker/python_images.sh test ${mxnet_variant} py2"
}
}

def push(mxnet_variant) {
ws("workspace/python_pypi/${mxnet_variant}/${env.BUILD_NUMBER}") {
// publish package to pypi
sh "./ci/docker/runtime_functions.sh cd_pypi_publish"
ws("workspace/python_docker/${mxnet_variant}/${env.BUILD_NUMBER}") {
// push python docker images
sh "./cd/python/docker/python_images.sh push ${mxnet_variant} py3"
sh "./cd/python/docker/python_images.sh push ${mxnet_variant} py2"
}
}

Expand Down
125 changes: 125 additions & 0 deletions cd/python/docker/python_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/usr/bin/env bash

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Executes mxnet python images pipeline functions: build, test, publish
# Assumes script is run from the root of the mxnet repository
# Assumes script is being run within MXNet CD infrastructure

set -xe

usage="Usage: python_images.sh <build|test|publish> MXNET-VARIANT <py2|py3>"

command=${1:?$usage}
mxnet_variant=${2:?$usage}
python_version=${3:?usage}

cd_utils='cd/utils'

case ${python_version} in
py3)
python_cmd="python3"
;;
py2)
python_cmd="python"
;;
*)
echo "Error: specify python version with either 'py2' or 'py3'"
exit 1
;;
esac

docker_tags=($(./${cd_utils}/docker_tag.sh ${mxnet_variant}))
main_tag="${docker_tags[0]}_${python_version}"
base_image=$(./${cd_utils}/mxnet_base_image.sh ${mxnet_variant})
repository="python"
image_name="${repository}:${main_tag}"

resources_path='cd/python/docker'

if [ ! -z "${RELEASE_DOCKERHUB_REPOSITORY}" ]; then
image_name="${RELEASE_DOCKERHUB_REPOSITORY}/${image_name}"
fi

# Builds runtime image
build() {
docker build -t "${image_name}" --build-arg PYTHON_CMD=${python_cmd} --build-arg BASE_IMAGE="${base_image}" --build-arg MXNET_COMMIT_ID=${GIT_COMMIT} -f ${resources_path}/Dockerfile .
}

# Tests the runtime image by executing runtime_images/test_image.sh within the image
# Assumes image exists locally
test() {
local runtime_param=""
if [[ ${mxnet_variant} == cu* ]]; then
runtime_param="--runtime=nvidia"
fi
local test_image_name="${image_name}_test"

docker build -t "${test_image_name}" --build-arg USER_ID=`id -u` --build-arg GROUP_ID=`id -g` --build-arg BASE_IMAGE="${image_name}" -f ${resources_path}/Dockerfile.test .
docker run ${runtime_param} -u `id -u`:`id -g` -v `pwd`:/mxnet "${test_image_name}" ${resources_path}/test_python_image.sh "${mxnet_variant}" "${python_cmd}"
}

# Pushes the runtime image to the repository
# Assumes image exists locally
push() {
if [ -z "${RELEASE_DOCKERHUB_REPOSITORY}" ]; then
echo "Cannot publish image without RELEASE_DOCKERHUB_REPOSITORY environment variable being set."
exit 1
fi

./${cd_utils}/docker_login.py

# Push image
docker push "${image_name}"

# Iterate over remaining tags, if any
for ((i=1;i<${#docker_tags[@]};i++)); do
local docker_tag="${docker_tags[${i}]}"
local latest_image_name="${RELEASE_DOCKERHUB_REPOSITORY}/${repository}:${docker_tag}"

# latest and latest gpu should only be pushed for py3
if [[ ${docker_tag} == "latest" || ${docker_tag} == "latest_gpu" ]]; then
if [[ ${python_version} == "py2" ]]; then
continue
fi
else
latest_image_name="${latest_image_name}_${python_version}"
fi

docker tag "${image_name}" "${latest_image_name}"
docker push "${latest_image_name}"
done
}

case ${command} in
"build")
build
;;

"test")
test
;;

"push")
push
;;

*)
echo $usage
exit 1
esac
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,31 @@
# specific language governing permissions and limitations
# under the License.

# Calculates the base image to be used by an MXNet docker image tag given the mxnet variant
# Assumes script is run from root of mxnet repository

mxnet_variant=${1:?"Please specify the mxnet variant as the first parameter"}

case ${mxnet_variant} in
cu80*)
echo "nvidia/cuda:8.0-cudnn7-runtime-ubuntu16.04"
;;
cu90*)
echo "nvidia/cuda:9.0-cudnn7-runtime-ubuntu16.04"
;;
cu91*)
echo "nvidia/cuda:9.1-cudnn7-runtime-ubuntu16.04"
;;
cu92*)
echo "nvidia/cuda:9.2-cudnn7-runtime-ubuntu16.04"
;;
cu100*)
echo "nvidia/cuda:10.0-cudnn7-runtime-ubuntu16.04"
;;
cpu)
echo "ubuntu:16.04"
;;
mkl)
echo "ubuntu:16.04"
;;
*)
echo "Error: Unrecognized mxnet-variant: '${mxnet_variant}'"
# To be run _within_ a runtime image
# Tests the Runtime docker image
# Assumes the mxnet source directory is mounted on /mxnet and cwd is /mxnet

set -ex

# Variant parameter should be passed in
mxnet_variant=${1:?"Missing mxnet variant"}
python_cmd=${2:?"Missing python version (python or python3)"}

if [ -z "${MXNET_COMMIT_ID}" ]; then
echo "MXNET_COMMIT_ID environment variable is empty. Please rebuild the image with MXNET_COMMIT_ID build-arg specified."
exit 1
;;
esac
fi

# Execute tests
if [[ $mxnet_variant == cu* ]]; then
mnist_params="--gpu 0"
test_conv_params="--gpu"
fi

if [[ $mxnet_variant == *mkl ]]; then
${python_cmd} tests/python/mkl/test_mkldnn.py
fi

${python_cmd} tests/python/train/test_conv.py ${test_conv_params}
${python_cmd} example/image-classification/train_mnist.py ${mnist_params}

Loading

0 comments on commit 0dba0ad

Please sign in to comment.