diff --git a/README.md b/README.md index cf279cd..49ef56a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This decouples the app developers and data scientists, to make sure that their p Variation to this tutorial could be consuming the ML application as an endpoint instead of packaging it in the app. The goal is to show how easy it is do devops for an AI application. -For detailed instructions please refer to the [tutorial](https://github.com/Azure/DevOps-For-AI-Apps/blob/jainr-refactor/Tutorial.md) +For detailed instructions please refer to the [tutorial](./Tutorial.md) Details about the code repository * flaskwebapp - contains the application code. diff --git a/Tutorial.md b/Tutorial.md index a9f1126..4869c14 100644 --- a/Tutorial.md +++ b/Tutorial.md @@ -54,9 +54,9 @@ Go to your project homepage and click on "Build and Releases tab" from the menu. ![VSTS Empty Process Definition](images/vsts-emptyprocess.PNG?raw=true) -Name your build definition and select a agent from the agent queue, we select Hosted Linux queue since our app is Linix based and we want to run some Linux specific command in further steps. When you queue a build, VSTS provides you an agent to run your build definition on. +Name your build definition and select a agent from the agent queue,We will select Hosted Ubuntu 1604 as Linux hosted is depreciated in Azure DevOps Pipelines. When you queue a build, VSTS provides you an agent to run your build definition on. -![VSTS Empty Process Definition](images/vsts-build-agentselection.PNG?raw=true) +![VSTS Empty Process Definition](images/vsts-build-agentselectionV2.PNG?raw=true) Under Get-Sources option, you can link the VSTS Build to source control of your choice. In this tutorial we are using GitHub, you can authorize VSTS to access your repository and then select it from the drop down. You can also select the branch that you want to build your app from, we select master. @@ -85,29 +85,28 @@ Add a Docker task to run docker commands. We will use this task to build contain Within the Docker task, give it a name, select subscription and ACR from dropdown. For action select "Build an image" and then give it the path to dockerfile. For Image name, select the following format /:$Build.BuildId. BuildId is a VSTS agent parameter and gets updated for each build. +Make sure you have cloned the latest dockerfile from this repo when configuring this task. + ![VSTS Docker Task Details](images/vsts-dockertaskdetails.PNG?raw=true) -After building the container for our application, we want to test the container. To do so, we will first start the container using the command line task. Note that we are using version 2.* of this task that gives us the option to pass inlien script. We are doing something tricky here, VSTS agent that builds our code is a docker container itself. So basically we are trying to start a container within a container. This is not hard but we need to make sure that both the containers are running on same network so we can access the ports correctly. To do so we first get the container id of the vsts build agent, by running following command. -BUILD_CONTAINER_ID=$(docker ps --filter "ancestor=microsoft/vsts-agent" --filter "status=running" --format "{{.ID}}") +Now since we are building this image on a actual hosted Ubuntu VM and not depreciated Linux container build agent, we can remove the complexity of obtaining container id and network details. -Please Note that the image name of the VSTS agent (microsoft/vsts-agent) might change in future, which will break this command but you can run other docker specific commands to find the image name of the VSTS agent. +Next we start our model-api image that we created in previous step. -Next we start our model-api image that we created in previous step and passing the network parameter to run it on same network as build VSTS agent container. -docker run -d --network container:$BUILD_CONTAINER_ID acrforblog.azurecr.io/model-api:$(Build.BuildId) +docker run --name modelapp -d adpacr.azurecr.io/model-api:$(Build.BuildId) -![VSTS Starting container](images/vsts-startingcontainer.PNG?raw=true) +![VSTS Starting container](images/vsts-startingcontainerV2.PNG?raw=true) Once we have the container running, we are doing a simple API test to the version endpoint, to make sure the container started ok. We are sleeping for 10 seconds to wait for the container to come up. -![VSTS Simple API test](images/vsts-simpleAPItest.PNG?raw=true) +![VSTS Simple API test](images/vsts-simpleAPItestV2.PNG?raw=true) -Notice that we are making use of a variable here (MODEL_API_URL), you can define custom process variable for your builds. To see a list of pre-defined variables and add your own, click on the variables tab. +Notice that we are making use of a variable here ($containerip), since this api is getting build on Ubuntu VM, we are trying to get the ip address of created container and assign it in this variable so that we can access the api for testing. -![VSTS Defining process variable](images/vsts-processvariable.PNG?raw=true) Next, we pass an image to the API and get the score back from it. Our test script is in the test/integration folder. We are only doing simple tests here but you can add more sophisticated tests to your workflow. -![VSTS Anaconda test](images/vsts-anacondatest.PNG?raw=true) +![VSTS Anaconda test](images/vsts-anacondatestV2.PNG?raw=true) Finally, we push the image that we have built to a private repository in Azure container registry. diff --git a/flaskwebapp/dockerfile b/flaskwebapp/dockerfile index ee92044..d5ca026 100644 --- a/flaskwebapp/dockerfile +++ b/flaskwebapp/dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:16.04 -MAINTAINER Mathew Salvaris +MAINTAINER Ashish Raj RUN mkdir /code WORKDIR /code @@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ supervisor \ nginx && \ rm /etc/nginx/sites-enabled/default && \ + pip install wheel && \ cp /code/nginx/app /etc/nginx/sites-available/ && \ ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ && \ pip install -r /code/requirements.txt && \ diff --git a/flaskwebapp/driver.py b/flaskwebapp/driver.py index b80e120..97c9025 100644 --- a/flaskwebapp/driver.py +++ b/flaskwebapp/driver.py @@ -31,9 +31,9 @@ def init(): with open(LABEL_FILE, 'r') as f: labelLookup = [l.rstrip() for l in f] - # Load model and load the model from brainscript (3rd index) + # Load model and load the model from brainscript (2nd index and third item) trainedModel = load_model(MODEL_FILE) - trainedModel = combine([trainedModel.outputs[3].owner]) + trainedModel = combine([trainedModel.outputs[2].owner]) end = t.default_timer() loadTimeMsg = "Model loading time: {0} ms".format(round((end - start) * 1000, 2)) diff --git a/images/vsts-anacondatestV2.PNG b/images/vsts-anacondatestV2.PNG new file mode 100644 index 0000000..bffc7da Binary files /dev/null and b/images/vsts-anacondatestV2.PNG differ diff --git a/images/vsts-build-agentselectionV2.PNG b/images/vsts-build-agentselectionV2.PNG new file mode 100644 index 0000000..8fd8438 Binary files /dev/null and b/images/vsts-build-agentselectionV2.PNG differ diff --git a/images/vsts-simpleAPItestV2.PNG b/images/vsts-simpleAPItestV2.PNG new file mode 100644 index 0000000..4f4a84f Binary files /dev/null and b/images/vsts-simpleAPItestV2.PNG differ diff --git a/images/vsts-startingcontainerV2.PNG b/images/vsts-startingcontainerV2.PNG new file mode 100644 index 0000000..703ab8b Binary files /dev/null and b/images/vsts-startingcontainerV2.PNG differ