<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>All things container - Bruno Terkaly</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/allthingscontainer/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/feed.xml</link>
    <description>Deep technical guidance around containers</description>
    <lastBuildDate>Tue, 23 Jan 2018 22:47:03 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>A Clear and Concise Hands-on Demo of Containerization on Kubernetes</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/a-clear-and-concise-hands-on-demo-of-containerization-on-kubernetes</link>
      <pubDate>Thu, 08 Jun 2017 01:01:26 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=13185</guid>
      <description><![CDATA[Description This video has been used in public presentation throughout the world. It very...]]></description>
      <content:encoded><![CDATA[<table style="border-top: medium none;font-size: '14';font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid"> <tbody> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><b>Description</b></td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">This video has been used in public presentation throughout the world. It very efficiently encapsulates the most core lessons in dealing with running containerized workloads in a Kubernetes cluster. It illustrates how to deploy pods and services in a Kubernetes cluster. It demonstrates how to build custom Docker images that can be uploaded to hub.docker.com and used in a Kubernetes cluster. It provides a practical example of building out a Python based web application that leverages MySQL and REDIS caching.</td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><b>Hands-On Lab Walk Through</b></td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://bit.ly/k8s-1">Hands-on written walkthrough</a></td></tr>  <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><b>Youtube Video</b></td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://bit.ly/k8s-2">Video</a></td></tr>  </tbody></table>]]></content:encoded>
    </item>
    <item>
      <title>Lab guide: Step-by-Step - Building a Web Service backed by a REDIS cache and MySQL Database on Kubernetes</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/lab-guide-step-by-step-building-a-web-service-backed-by-a-redis-cache-and-mysql-database-on-kubernetes</link>
      <pubDate>Mon, 13 Mar 2017 14:03:22 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12865</guid>
      <description><![CDATA[This is a step-by-step lab that will guide you to building out a web service that runs on...]]></description>
      <content:encoded><![CDATA[<ul> <li>This is a step-by-step lab that will guide you to building out a web service that runs on Kubernetes.  <li>The technologies for the web service includes Python and Flask.  <li>A REDIS caching layer is employed in addition to a MySQL database </li></ul> <p><strong>Video Presentations of this lab can be found here:</strong></p> <p>https://www.youtube.com/channel/UCsBCIVK2c_YqxRQFX6xfYJw/videos?shelf_id=0&amp;view=0&amp;sort=dd</p> <p>You can see in the diagram below that VM is represented by an agent, both agent 1 and agent 2. Notice further that on each agent a pod is running.</p> <p>The first pod is running both the <strong>web service</strong>, represented by Python and flask, as well as the <strong>caching service</strong> (REDIS). It makes sense to <strong>bundle those two together</strong> on the same pod so as to minimize latency.</p> <p>The caching service saves round-trips to the database. if the data is in the cache, then the database does not need to get involved.</p> <p>Notice that the user will come in on <strong>Port 80</strong> when accessing the web service from the outside world. But the actual requests get routed to port 5000 in the Python flask web service, which is listening really on port 5000.</p> <p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes1001.png" target="_blank"><img title="kubernetes100" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes100" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes100_thumb1.png" width="737" height="345"></a></p> <p><em>Figure 1: Overview</em></p> <h2 style="color: darkblue">Part 1 - Introduction</h2> <p>Let's recap the technology stack used in these labs:</p> <p>This service will have some core characteristics.</p> <ul> <li>The application will run in the Azure Container Service (ACS) as a K8s cluster  <li>ACS + Kubernetes will host a web service (Python + Flask)  <li>There is:  <ul> <li>A caching layer (Redis)  <li>A backend database of MySQL  <li>Two pods  <ul> <li>The first pod will have both the web service and the caching layer  <li>The second pod will have a MySQL database </li></ul></li></ul></li></ul> <h3 style="color: darkblue">Prerequisites</h3> <p>Before getting started, make sure that you have a Kubernetes cluster created. You will also need to verify that the <strong>kubectl</strong> utility works correctly. You will need to download the <strong>config</strong> file, which is what allows the <strong>kubectl</strong> to properly connect up to the Kubernetes cluster.</p> <p>You will not need to specifically SSH into the Kubernetes cluster. But you will need a development machine that has the appropriate SSH keys that allows communication with the Kubernetes cluster.</p> <p>I have created a couple of videos to illustrate how to get that set up. There is some overlap in these videos, but taken together they show you how to install all the necessary tooling to get up and running, even provisioning the cluster itself within Azure.</p> <table style="border-top: medium none;font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid"> <tbody> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video 1</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=qW6mzCJg4tI" target="_blank">Click Here</a></td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video 2</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=2316KyERwvg" target="_blank">Click Here</a></td></tr></tbody></table> <hr>  <h3 style="color: darkblue">Test your knowledge</h3> <p><em>Do you know what a Kubernetes pod is?</em></p> <blockquote> <p>**Pod: ** A pod (as in a pod of whales or pea pod) is a group of one or more containers (such as Docker containers), the shared storage for those containers, and options about how to run the containers. </p> <p><strong>Pods</strong> are always <strong>co-located and co-scheduled</strong>, and run in a shared context. </p> <p>A pod models an application-specific “logical host” - it contains one or more application containers which are relatively tightly coupled — in a pre-container world, they would have executed on the same physical or virtual machine.</p> <p>While Kubernetes supports more container runtimes than just Docker, Docker is the most commonly known runtime, and it helps to describe pods in Docker terms.</p> <p>The shared context of a pod is a set of Linux namespaces, cgroups, and potentially other facets of isolation - the same things that isolate a Docker container. Within a pod’s context, the individual applications may have further sub-isolations applied.</p> <p>Containers within a pod share an IP address and port space, and can find each other via localhost. They can also communicate with each other using standard inter-process communications like SystemV semaphores or POSIX shared memory. Containers in different pods have distinct IP addresses and can not communicate by IPC.</p></blockquote> <hr>  <h2 style="color: darkblue">Part 2 - Getting the code</h2> <p>The prerequisite to this session is the fact that you have a Kubernetes cluster already provisioned.</p> <table style="border-top: medium none;font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid"> <tbody> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">There are numerous videos around this lab here:</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/channel/UCsBCIVK2c_YqxRQFX6xfYJw/videos?shelf_id=0&amp;view=0&amp;sort=dd" target="_blank">Click Here</a></td></tr></tbody></table> <h3 style="color: darkblue">Downloading the source code</h3> <table style="border-top: medium none;font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid"> <tbody> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">You can download all the source code here:</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://github.com/brunoterkaly/k8s-multi-container" target="_blank">Click Here</a></td></tr></tbody></table> <h4 style="color: darkblue">Lab Instructions</h4> <ol> <li>Download the source code for this lab. </li></ol> <p>The command download is:</p><pre><code>git clone https://github.com/brunoterkaly/k8s-multi-container.git
</code></pre>
<p>Here is the output:</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00041.png" target="_blank"><img title="kubernetes0004" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0004" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0004_thumb1.png" width="914" height="268"></a></p>
<p><em>Figure 2: Cloning the source code</em></p>
<p>You will notice that there are three folders:</p>
<ul>
<li><strong>Build</strong> (contains the Python code to build out our web service) 
<li><strong>Deploy</strong> (Contains the YML definition file that lets us set up our pods, services, and our containers in Kubernetes) 
<li><strong>Run</strong> (contains the commands to deploy, operate, and manage our Kubernetes cluster) </li></ul>
<p>Below you will find the folder structure that was addressed above.</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00031.png" target="_blank"><img title="kubernetes0003" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0003" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0003_thumb1.png" width="492" height="645"></a></p>
<p><em>Figure 3: The files and folders used in this lab</em></p>
<hr>

<h2 style="color: darkblue">Part 3 - Building the web service</h2>
<p>In this section we will focus on building out the web service, focusing on the Python code. We will also build out the docker image that will run in the agents of the Kubernetes cluster. We will review the Python file, Flask and some other pieces.</p>
<ul>
<li>The <strong>web service</strong> is a combination of Python and Flask 
<li><strong>Python</strong> represents the main programming paradigm and <strong>Flask</strong> as the necessary libraries to expose endpoints as web services 
<li><strong>dockerfile</strong> is used to build out our image, which will then be uploaded to hub.docker.com 
<li><strong>app.py</strong> represents the Python application that implements web services 
<li><strong>buildpush.sh</strong> is some script code to do both the building of the image, as well as the uploading of the image to hub.docker.com </li></ul>
<hr>

<h3 style="color: darkblue">Test your knowledge</h3>
<p><em>Do you know what Flask is?</em></p>
<blockquote>
<p>Flask is a web framework. This means flask provides you with tools, libraries and technologies that allow you to build a web application. This web application can be some web pages, a blog, a wiki or go as big as a web-based calendar application or a commercial website.</p>
<p>Flask is part of the categories of the micro-framework. Micro-framework are normally framework with little to no dependencies to external libraries. This has pros and cons. Pros would be that the framework is light, there are little dependency to update and watch for security bugs, cons is that some time you will have to do more work by yourself or increase yourself the list of dependencies by adding plugins.</p></blockquote>
<p>The Python application is a web service that listens on port 5000.a number of URLs with differing endpoints will map to specific methods within the <strong>app.py</strong> file.</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00061.png" target="_blank"><img title="kubernetes0006" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0006" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0006_thumb1.png" width="647" height="450"></a></p>
<p><em>Figure 4: Working on the Python App</em></p>
<hr>

<h4 style="color: darkblue">Test your knowledge</h4>
<p><em>Do you know what a Dockerfile is?</em></p>
<blockquote>
<p>**Dockerfile: ** Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession</p></blockquote>
<h4 style="color: darkblue">The Dockerfile</h4>
<p>Before diving into the details of the app.py, let's talk about the environment in which it will run.</p>
<p>It all wrong inside of a docker container. Docker containers is the execution of a docker image.</p>
<ul>
<li>Represents the image blueprint for our docker container 
<li>Listening on port 5000 
<li>Starts up running <strong>app.py</strong> </li></ul>
<p><strong>Dockerfile</strong></p><pre><code>FROM python:2.7-onbuild
EXPOSE 5000
CMD [ "python", "app.py" ]
</code></pre>
<p>Notice of the docker file above that <strong>FROM python:2.7-onbuild</strong> represents the base image that comes preconfigured with all the Python dependencies that are needed. That is the beauty of the docker ecosystem. You can start with an existing Python image that has flask installed.</p>
<p>There are a few things to notice: - Port 5000 was exposed for the container so that incoming requests can be serviced - CMD [ "python", "app.py" ] tells the system to run the <strong>ap.py</strong> file when the container starts.</p>
<h4 style="color: darkblue">Lab Instructions</h4>
<ol>
<li>Go to the Build directory 
<li>Open <strong>Dockerfile</strong> 
<li>Make sure that you understand the contents of the <strong>Dockerfile</strong> </li></ol>
<p>Type these commands:</p><pre><code>cd Build
vim Dockerfile
</code></pre>
<p><strong>app.py</strong> represents the main web service. It imports a variety of libraries. Let's present the code then review it.</p>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>Here is how to view <strong>app.py</strong>.</p>
<ol>
<li>Go to the <strong>Build</strong> directory 
<li>Open <strong>Dockerfile</strong> 
<li>
<p>Make sure that you understand the contents of the <strong>app.py</strong></p>
<p>cd Build vim app.py</p></li></ol>
<hr>

<h4 style="color: darkblue">Test your knowledge</h4>
<p><em>Do you know what a Flask route is?</em></p>
<blockquote>
<p>**Flask Route: ** As you wil see below, the route() decorator is used to bind a function to a URL. Here is a basic examples:</p></blockquote><pre><code>@app.route('/hello')
def hello():
 return 'Hello, World'
</code></pre>
<hr>

<p>Notice that our example below for Flask has many more routes:</p>
<p><strong>app.py</strong></p><pre><code>from flask import Flask
from flask import Response
from flask import request
from redis import Redis
from datetime import datetime
import MySQLdb
import sys
import redis 
import time
import hashlib
import os
import json

app = Flask(__name__)
startTime = datetime.now()
R_SERVER = redis.Redis(host=os.environ.get('REDIS_HOST', 'redis'), port=6379)
db = MySQLdb.connect("mysql","root","password")
cursor = db.cursor()

@app.route('/init')
def init():
    cursor.execute("DROP DATABASE IF EXISTS AZUREDB")
    cursor.execute("CREATE DATABASE AZUREDB")
    cursor.execute("USE AZUREDB")
    sql = """CREATE TABLE courses(id INT, coursenumber varchar(48), 
                  coursetitle varchar(256), notes varchar(256));  
     """
    cursor.execute(sql)
    db.commit()
    return "DB Initialization done\n" 

@app.route("/courses/add", methods=['POST'])
def add_courses():

    req_json = request.get_json()   
    cursor.execute("INSERT INTO courses (id, coursenumber, coursetitle, notes) VALUES (%s,%s,%s,%s)", 
          (req_json['uid'], req_json['coursenumber'], req_json['coursetitle'], req_json['notes']))
    db.commit()
    return Response("Added", status=200, mimetype='application/json')

@app.route('/courses/&lt;uid&gt;')
def get_courses(uid):
    hash = hashlib.sha224(str(uid)).hexdigest()
    key = "sql_cache:" + hash

    returnval = ""
    if (R_SERVER.get(key)):
        return R_SERVER.get(key) + "(from cache)" 
    else:
        cursor.execute("select coursenumber, coursetitle, notes from courses where ID=" + str(uid))
        data = cursor.fetchall()
        if data:
            R_SERVER.set(key,data)
            R_SERVER.expire(key, 36)
            return R_SERVER.get(key) + "\nSuccess\n"
        else:
            return "Record not found"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
</code></pre>
<h4 style="color: darkblue">Understanding app.py</h4>
<p>There are 3 endpoints that the web service responds to: - https://[Kubernetes Cluster IP Address]/<strong>init</strong> - https://[Kubernetes Cluster IP Address]/<strong>add</strong> - https://[Kubernetes Cluster IP Address]/<strong>courses/{course id}</strong> - The user passes in the {course id}</p>
<p>The code is self explanatory, but here are some high level tips.</p>
<p>Expose the "init" endpoint - The user will hit https://[Kubernetes Cluster IP Address]/<strong>init</strong> - The result is to setup the database (create database, tables, etc) - Initially, we will use an internal IP address, later moving to a public IP address</p>
<p>Expose the "add" endpoint - The user will hit https://[Kubernetes Cluster IP Address]/courses/<strong>add</strong> - Performs an insert into the database using the data posted by the user - POST is the HTTP verb being used</p>
<p>Expose the "courses/{course id}" endpoint - The user will hit https://[Kubernetes Cluster IP Address]/<strong>courses</strong>/<strong>{course id}</strong> - This allows the user to query the endpoint - It will return records from either the cache or the database - If the data is not in the cache, it will be retrieved from the database, put into the cache, and returned to the client</p>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>Let's build the Docker image and upload to hub.docker.com.</p>
<ol>
<li>Go to hub.docker.com and establish an account. You will need it to upload docker images. The account used in these demos is <strong>brunoterkaly</strong>. See "Example Account" below. 
<li>Go to the Build directory 
<li>Open <strong>buildpush.sh</strong> 
<ol>
<li>This is a shell script that builds the docker image and pushes image to hub.docker.com </li></ol>
<li>Make sure that you understand the contents of the <strong>buildpush.sh</strong> 
<li>Run buildpush.sh </li></ol>
<p>Commands to view and run buildpush.sh</p><pre><code># View buildpush.sh
cd Build
vim buildpush.sh
# Run buildpush.sh
bash buildpush.sh
</code></pre>
<p>Remember to go to hub.docker.com and create your own account. As you can see, I chose "brunoterkaly" as the owner of my repos on hub.docker.com. </p>
<p>So you will then edit "brunoterkaly" below to reflect YOUR hub.docker.com account.</p>
<h4 style="color: darkblue">buildpush.sh</h4><pre><code># Make sure to run as "root" or use "sudo"
# Don't forget "brunoterkaly" will not work for you
# Use the one you created at hub.docker.com
sudo docker build . -t brunoterkaly/py-red
# You may need to do a "docker login" command for the command below to work
sudo docker push brunoterkaly/py-red
</code></pre>
<h4 style="color: darkblue">Run <strong>buildpush.sh</strong></h4><pre><code>bash buildpush.sh
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00071.png" target="_blank"><img title="kubernetes0007" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0007" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0007_thumb1.png" width="396" height="323"></a></p>
<p><em>Figure 5: Example Account</em></p>
<h4 style="color: darkblue">Output of buildpush.sh</h4>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00081.png" target="_blank"><img title="kubernetes0008" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0008" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0008_thumb1.png" width="1190" height="366"></a></p>
<p><em>Figure 6: Example of running buildpush.sh</em></p>
<p>You should be able to see the the image available on hub.docker.com.</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00091.png" target="_blank"><img title="kubernetes0009" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0009" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0009_thumb1.png" width="500" height="247"></a></p>
<p><em>Figure 7: hub.docker.com - Our image is ready for download</em></p>
<hr>

<h2 style="color: darkblue">Part 4 - Understanding the YAML files</h2>
<p>Kubernetes uses a declarative markup language inside of YAML file to define the way containers run inside of pods as well as how these containers are exposed to the outside world through a service layer, which exposes either private or public IP address. There will be three categories of the YAML files. The first while YAML file will define a pod in which the both the Python application as well as the REDIS cache. The second YAML file is used to define how the MySQL database will run in its own pod. And the third YAML file will be used to expose the endpoint in the Python web service with either private or public IP address.</p>
<p>Before you get here, make sure you have issued the "docker build" and "docker push" commands reflected above.</p>
<p>Here is some information about pods and containers. Some of this reiterates what was just said above.</p>
<ul>
<li>These YAML files define the way our containers will run in the Kubernetes cluster 
<li>They also define how the containers are organized within pods 
<li>Pods group together containers in the same host 
<li>This provides efficiency in that the containers are running close together 
<li>As described, there are two pods 
<li>On the first pod there will be two containers, the Python web service and the Redis Cache 
<li>On the second pod there will be the MySQL database 
<li>YML files just text file that define the pods and the services 
<li>The first part is called the 'web' pod </li></ul>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>We will now go and opened the three YAML files and look inside of them to see how they are constructed.</p>
<ol>
<li>Change directory to the <strong>Deploy</strong> directory (<strong>cd Deploy</strong>) 
<li>Execute <strong>vim web-pod-1.yml</strong>. 
<li>Review the contents. 
<ol>
<li>You will notice that there are two images that make up the pod 
<ol>
<li>REDIS (using the one already built and available at hub.docker.com) 
<li>py-red (the one we just built in a prior section of this lab) 
<li>understand the other metadata that you see there, such as the container port, the labels and names used. </li></ol></li></ol></li></ol>
<h4 style="color: darkblue">web-pod-1.yml</h4>
<p>Defines the pod for the web part of the application.</p>
<p>Anytime you see "brunoterkaly," you need to replace that with your own account name at hub.docker.com.</p><pre><code>apiVersion: "v1"
kind: Pod
metadata:
  name: web1
  labels:
    name: web
    app: demo
spec:
  containers:
    - name: redis
      image: redis
      ports:
        - containerPort: 6379
          name: redis
          protocol: TCP
    - name: python
      image: brunoterkaly/py-red
      env:       
        - name: "REDIS_HOST"
          value: "localhost"
      ports:
        - containerPort: 5000
          name: http
          protocol: TCP                    
</code></pre>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>In this section we will understand the database layer. Once again, you will notice that we are using one of the images of at hub.docker.com that is specific for MySQL. Let's note that when we use these YAML files, those images will be downloaded automatically onto our Kubernetes cluster from hub.docker.com.</p>
<p>When we complete this section you will now understand the two pods that are running inside of the Kubernetes cluster. It makes sense that we would want to group the Python web service with the REDIS cache on the same pod to minimize latency.</p>
<ol>
<li>Change directory to the <strong>Deploy</strong> directory(<strong>cd Deploy</strong>) 
<li>Execute <strong>vim db-pod.yml</strong>. 
<li>Review the contents. 
<ol>
<li>You will notice that there is just one image that is included in this pod 
<li>It is the MySQL database </li></ol>
<li>Execute <strong>vim db-svc.yml</strong>. 
<li>Review the contents. 
<ol>
<li>There are no references to images in this YAML file as its main purpose is to simply expose the pods and map incoming ports to the container 
<li>Notice that when an incoming request comes on port 3306, it gets routed to port 3306 for the MySQL database </li></ol></li></ol>
<h4 style="color: darkblue">db-pod.yml</h4><pre><code>apiVersion: "v1"
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
    app: demo
spec:
  containers:
    - name: mysql
      image: mysql:latest
      ports:
        - containerPort: 3306         
          protocol: TCP
      env: 
        - 
          name: "MYSQL_ROOT_PASSWORD"
          value: "password"
</code></pre>
<h4 style="color: darkblue">db-svc.yml</h4><pre><code>apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    name: mysql
    app: demo  
spec:
  ports:
  - port: 3306
    name: mysql
    targetPort: 3306
  selector:
    name: mysql
    app: demo
</code></pre>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>In this third section of YAML files. We will discuss how we would make the web service pod accessible through the use of a <strong>service</strong>. You have probably notice that there is a YAML entry called <strong>kind</strong>, which indicates the type of Kubernetes object. We would like to instantiate. There are several, but for this lab we are focusing on <strong>pod</strong> in-<strong>service</strong>.</p>
<ol>
<li>Change directory to the <strong>Deploy</strong> directory (<strong>cd Deploy</strong>) 
<li>Execute <strong>vim web-svc.yml</strong>. 
<li>Review the contents. 
<ol>
<li>There are no references to images in this YAML file as its main purpose is to simply expose the pods and map incoming ports to the container 
<li>notice that when an incoming request comes on port 80, it gets routed to port 5000 for the Python and REDIS pod </li></ol></li></ol>
<blockquote>
<p><strong>NodePort:</strong> Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting :. 
<p></p></blockquote>
<h4 style="color: darkblue">web-svc.yml</h4><pre><code>apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    name: web
    app: demo
spec:
  selector:
    name: web 
  type: NodePort
  ports:
   - port: 80
     name: http
     targetPort: 5000
     protocol: TCP
</code></pre>
<h4 style="color: darkblue">db-svc.yml</h4><pre><code>apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    name: mysql
    app: demo  
spec:
  ports:
  - port: 3306
    name: mysql
    targetPort: 3306
  selector:
    name: mysql
    app: demo
</code></pre>
<hr>

<h2 style="color: darkblue">Part 6 - Getting started with kubectl</h2>
<p>Previously we discussed some videos to help you get set up. As part of that set up process. We need to get a configuration file onto a developer computer so that it can appropriately communicate with the Kubernetes cluster. That is done through a <strong>config</strong> file.</p>
<p>For the sake of completeness, here are some commands to get that done.</p>
<h3 style="color: darkblue">Getting the 'config' file</h3>
<ul>
<li>We will use the Python and Azure SDK's to retrieve this file 
<li>It will put it in a special folder from which we will copy it into the current directory </li></ul>
<p>The videos outlined at the beginning of this document describe how to set up your Kubernetes cluster on Azure. The videos also cover: - Getting the <strong>config</strong> file - Getting the <strong>kubectl</strong> command</p>
<p>Here are some examples of commands to create the Kubernetes cluster using Python. You do not need to do these commands as this lab assumes you have a Kubernetes cluster.</p><pre><code>az login
az account set --subscription "c884f[your subscription ID goes here]2fa28"
# See Output 1
az ad sp create-for-rbac --role="Owner" --scopes="/subscriptions/c884f3c[your subscription ID goes here]42fa28"
# See Output 2
RESOURCE_GROUP=ascend-k8s-rg
DNS_PREFIX=ascend-k8s
SERVICE_NAME=ascend-k8s-svc
az group create \
        --name $RESOURCE_GROUP \
            --location "centralus"
RESOURCE_GROUP=ascend-k8s-rg
DNS_PREFIX=ascend-k8s
CLUSTER_NAME=btk8s
az acs create --orchestrator-type=kubernetes \
         --resource-group $RESOURCE_GROUP \
         --name=$CLUSTER_NAME --dns-prefix=$DNS_PREFIX
az acs kubernetes get-credentials --resource-group=$RESOURCE_GROUP --name=$CLUSTER_NAME
</code></pre>
<p>Note that you will need to substitute your own information for what you see above. For example, the subscription ID you see will need to be your own.</p>
<p>Anytime you see the commands include, "az acs" you should realize that this involves the Azure and Python SDK to be installed on your developer computer.</p>
<p>You will also need to take special note with some of the environment variables you see above, substituting your own names as indicated below.</p>
<h4 style="color: darkblue">Notes about the code snippet above</h4>
<p>You can get more information about provisioning your own Kubernetes cluster here in addition to the videos previously presented:</p>
<p>https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough</p>
<h3 style="color: darkblue">Setting environment variable (KUBECONFIG) and getting kubectl</h3>
<p>This environment variable is used by kubectl to know where to retrieve the config file.</p>
<h4 style="color: darkblue">Lab Instructions</h4>
<ol>
<li>Run the <strong>export</strong> command as seen below for KUBECONFIG 
<ol>
<li>You can add this to <strong>~/.bashrc</strong> for a more permanent solution </li></ol>
<li>Run the <strong>az acs kubernetes install-cli</strong> as seen below, in addition to the test specified 
<li>Review the following URLs for more information: 
<ol>
<li>https://www.youtube.com/watch?v=qW6mzCJg4tI 
<li>https://www.youtube.com/watch?v=2316KyERwvg </li></ol></li></ol>
<p>Here is the command that allows the system to find your <strong>config</strong> file</p><pre><code>export KUBECONFIG=`pwd`/config
</code></pre>
<p>We will also want to get the <strong>kubectl</strong> utility, which is the mechanism we can use to communicate with their Kubernetes cluster. It works in conjunction with the <strong>config</strong> file just addressed.</p><pre><code># obtain the kubectl utility
az acs kubernetes install-cli
# test the utility
kubectl cluster-info
</code></pre>
<p>You can see the config file below being copied to the current working directory. You probably want to think about a more permanent location for the config file longer-term, but for now let's just copy it to a local directory for ease of use.</p>
<p>It's important to note that it's this config file that will enable us to communicate with the Kubernetes cluster from our Linux VM.</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00101.png" target="_blank"><img title="kubernetes0010" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0010" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0010_thumb1.png" width="940" height="266"></a></p>
<p><em>Figure 8: Verifying config</em></p>
<hr>

<h2 style="color: darkblue">Part 7 - Using kubectl to run containers, provision pods, and provision services</h2>
<p>We have now laid the groundwork for using kubectl. This means that we can begin to communicate with the cluster and indicate to the cluster which containers we wish to run in which pods and how to expose the pods through services.</p>
<p>So that I do not have to type <strong>kubectl</strong> over and over, I have run this following command in Linux to create an alias:</p><pre><code>alias k=kubectl
</code></pre>
<p>This means I can just use <strong>k</strong> instead of <strong>kubectl</strong>. </p>
<p>To test that things are working correctly you can use the kubectl command to get information about the cluster, as follows:</p><pre><code>kubectl cluster-info
#or
k cluster-info
</code></pre>
<p>If everything is working correctly, you should see the following:</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00111.png" target="_blank"><img title="kubernetes0011" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0011" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0011_thumb1.png" width="1078" height="173"></a></p>
<p><em>Figure 9: Information about your cluster</em></p>
<h3 style="color: darkblue">Running the pods and services</h3>
<p>At this point we are going to run the pods and services. You will find a file called <strong>run.sh</strong>. this file is simply encapsulating the running of four YAML files with the kubectl utility. They can be run in any order. But you can see that we are running a pod, then a service, one set of commands for the web layer and one set of commands for the database layer. </p>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>The next step is to run our pods in our services, leveraging the <strong>kubectl</strong> utility.</p>
<ol>
<li>Change directory to the <strong>Deploy</strong> directory (<strong>cd Deploy</strong>) 
<li>Execute <strong>vim run.sh</strong>. 
<li>Validate that it resembles the script defined below. 
<li>Exit out of <strong>run.sh</strong>. 
<li>At the command prompt, issue a <strong>bash run.sh</strong> command. </li></ol>
<h4 style="color: darkblue">run.sh</h4><pre><code>kubectl create -f db-pod.yml
kubectl create -f db-svc.yml
kubectl create -f web-pod-1.yml
kubectl create -f web-svc.yml
</code></pre>
<p>The output of the command should look something like this:</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00121.png" target="_blank"><img title="kubernetes0012" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0012" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0012_thumb1.png" width="834" height="102"></a></p>
<p><em>Figure 10: Running run.sh</em></p>
<p>Once all the pods and services are running in the cluster, you can issue other commands to actually see the running pods and services.</p>
<p>Command to list running pods:</p><pre><code>kubectl get pods
</code></pre>
<p>Command to list running services:</p><pre><code>kubectl get svc
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00131.png" target="_blank"><img title="kubernetes0013" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0013" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0013_thumb1.png" width="828" height="182"></a></p>
<p><em>Figure 11: Viewing the pods and services at the command line</em></p>
<h3 style="color: darkblue">Exposing the web service through an external IP address</h3>
<p>Let's imagine that we want to open up this web service so that others can access it. This requires us to open up an external IP address. Notice that in the diagram, "Viewing the pods and services at the command line," the external address for the <strong>web</strong> component reads <strong></strong>. </p>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>What will do in the next step is actually create a real external IP address that allows us to get access to the Python web service.</p>
<ol>
<li>At the command line, type in <strong>kubectl edit svc/web</strong> 
<li>Navigate down two line 28 where you will see the <strong>type</strong> field, and replace <strong>NodePort</strong> with <strong>LoadBalancer</strong>. 
<ol>
<li>See figure, "Exposing an external IP address" </li></ol></li></ol>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00141.png" target="_blank"><img title="kubernetes0014" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0014" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0014_thumb1.png" width="500" height="469"></a></p>
<p><em>Figure 12: Exposing an external IP address</em></p>
<p>Command to expose an external IP address for our Web service:</p><pre><code>kubectl edit svc/web
</code></pre>
<p>Editing the web service file should look like this. nnotice that we did switch the **type ** element to <strong>LoadBalancer</strong>.</p><pre><code># Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2017-02-15T22:00:51Z
  labels:
    app: demo
    name: web
  name: web
  namespace: default
  resourceVersion: "149793"
  selfLink: /api/v1/namespaces/default/services/web
  uid: 36eee4e7-f3ca-11e6-a3cd-000d3a9203fe
spec:
  clusterIP: 10.0.73.141
  ports:
  - name: http
    nodePort: 30189
    port: 80
    protocol: TCP
    targetPort: 5000
  selector:
    name: web
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 13.89.230.209
</code></pre>
<h2 style="color: darkblue">Part 8 - Testing the application</h2>
<p>Our application is now running in the Kubernetes cluster. In this next section we will run some commands to test it out. First, we will initialize the database. second, we will add some data to the database. And in the third section, we will actually test the queries and make sure that they leverage the REDIS cache, before actually hitting the underlying MySQL database.</p>
<p><strong>Understanding the three Python routes</strong></p>
<ul>
<li>In the last section we even exposed an external IP address, allowing us to pretty much access web service from anywhere. 
<li>As you recall, there are three endpoints that we can use to access the web service. 
<li>
<p>The three routes:</p>
<ul>
<li>init 
<li>couses/add 
<li>courses/{course id} </li></ul>
<p>https://XXX/init https://XXX/courses/add https://XXX/courses/{course id} 
<p></p></li></ul>
<h4 style="color: darkblue">Lab Instructions</h4>
<p>The testing process starts by initializing the database. </p>
<ol>
<li>Return back to the Linux command prompt. 
<li>Type in <strong>curl https://[public IP address the service]/init</strong> 
<ol>
<li>See the command below for details </li></ol></li></ol>
<hr>

<h4 style="color: darkblue">kubectl get svc</h4>
<p>In order to retrieve the external IP address, type:</p><pre><code>kubectl get svc
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00321.png" target="_blank"><img title="kubernetes0032" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0032" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0032_thumb1.png" width="858" height="156"></a></p>
<p><em>Figure 13: Requesting a list of running services</em></p>
<p>Once we have this at IP address, we can begin to write requests into our Python web service. you will notice the response from the system, saying, <strong>DB Initialization done</strong>.</p><pre><code>curl 40.69.141.235/init
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00331.png" target="_blank"><img title="kubernetes0033" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0033" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0033_thumb1.png" width="905" height="209"></a></p>
<p><em>Figure 14: Initializing the database with the curl command</em></p>
<p>As you recall, we setup a route within the Python and flask code to drop the database and re-created table.</p>
<p>Notice that, as a result of the user hitting the endpoint (https://..../init), a series of database related commands get executed. A database is created along with the table called, "courses".</p>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00381.png" target="_blank"><img title="kubernetes0038" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0038" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0038_thumb1.png" width="950" height="297"></a></p>
<p><em>Figure 15: The Python script that initializes the database and creates a table</em></p>
<p>Notice that, as a result of the user hitting the endpoint (https://..../init), a series of database related commands get executed. A database is created along with the table called, “courses”.</p>
<p>We now need to insert some data. Notice the shell script displayed below, called <strong>app.sh.</strong> Notice that it uses <strong>curl</strong> to post JSON data to the web service. It essentially inserts 3 records into the MySQL database. Notice the various fields that get POSTED (UID, course number, course title, and notes).</p><pre><code>cd ../Run
cat add.sh
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00341.png" target="_blank"><img title="kubernetes0034" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0034" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0034_thumb1.png" width="1086" height="376"></a></p>
<p><em>Figure 16: Viewing the script code to insert data</em></p>
<p>Notice that during execution of the script, the system returns back HTTP 200 OK, indicating that the records were successfully processed and inserted into the MySQL database</p><pre><code>bash add.sh
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00351.png" target="_blank"><img title="kubernetes0035" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0035" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0035_thumb1.png" width="720" height="470"></a></p>
<p><em>Figure 17: Executing the code to insert data</em></p>
<p>The important activity that remains is to query the database. Take note of the file called, query.sh, which simply hits the web service with the query based on UID. Notice that we had passed in UID of “1”, “2”, or “3”. </p><pre><code>cat query.sh
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00361.png" target="_blank"><img title="kubernetes0036" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0036" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0036_thumb1.png" width="712" height="141"></a></p>
<p><em>Figure 18: Viewing the code to query the data</em></p>
<p>Now we simply go request those records. An important note here is that on the first call the MySQL database will retrieve the data. At that point, the REDIS cash will get a copy of that data, meaning that subsequent queries will actually get retrieve from the REDIS cash, sitting a trip to the database, which would be slower and represent additional network traffic.</p><pre><code>bash query.sh
</code></pre>
<p><br><a href="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes00371.png" target="_blank"><img title="kubernetes0037" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="kubernetes0037" src="https://msdnshared.blob.core.windows.net/media/2017/03/kubernetes0037_thumb1.png" width="732" height="186"></a></p>
<p><em>Figure 19: Executing the code to query the data</em></p>
<h1 style="color: darkblue">Summary</h1>
<p>This lab has taught some important lessons. First, is a description about how containers and pods can work together to define an application. From there, we took a look at setting up a kubernetes SVC to these pods. Along the way we learned about the importance of kubectl, which is a commandline tool that allows us to interact with the Kubernetes cluster.</p>
<p><br>We also studied the use of YAML files, which provide a declarative syntax, allowing us to define the way we want to define our topology for our application. For example, we were able to define the containers that make up pods as well as the services that expose pods to the outside world for public IP or external IP address.</p>]]></content:encoded>
    </item>
    <item>
      <title>Starting from nothing and running applications in Kubernetes (K8s) clusters</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/building-a-restful-web-service-using-kubernetes-k8s</link>
      <pubDate>Wed, 15 Feb 2017 19:36:04 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12535</guid>
      <description><![CDATA[You are at Learn Kubernetes. Please help spread the word. If you don't mind, tweet this...]]></description>
      <content:encoded><![CDATA[<p>You are at Learn Kubernetes. <font color="#9b00d3">Please </font>help spread the word. If you don't mind, <font color="#9b00d3">tweet this </font><font color="#0000ff">https://bit.ly/learn-kubernetes</font> </p> <p>Technologies include:</p> <ul> <li>Kubernetes running in Azure Container Service  <li>Python + Flask = Web API  <li>Redis is the caching layer  <li>MySQL is a data store  <li>Everything runs in a Docker container  <li>Connecting to Kubernetes from Windows </li></ul> <p>This content is 95%+ hands-on and does not include much conceptual discussion.</p> <p>The assumption here is that you already know you want to learn Kubernetes and that you just want to setup a cluster and start with a simple web application.</p> <p>This is a very comprehensive soup-to-nuts set of demos that start with nothing and ends with a 2-pod Kubernetes workload with a caching layer (REDIS) and a persistent relational data store (MySQL).</p>  <a href="https://www.youtube.com/channel/UCsBCIVK2c_YqxRQFX6xfYJw/videos?shelf_id=0&amp;view=0&amp;sort=dd" target="_blank">Bruno Terkaly Kubernetes YouTube Channel</a>  <table style="border-top: medium none;font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid"> <tbody> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Step-by-step: Provision Kubernetes Cluster</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Document</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://github.com/brunoterkaly/provision-kubernetes" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Step-by-step: Provision Kubernetes Cluster</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/qW6mzCJg4tI" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Kubernetes Step-by-step: Python, Flask, Redis, MySQL</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Document</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://github.com/brunoterkaly/intro-kubernetes-tutorial" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 1: Kubernetes Step-by-step: Python, Flask, Redis, MySQL</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/MOQ-BeNDY9Y" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 2: Kubernetes Step-by-step: Python, Flask, Redis, MySQL</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/SRp4mAG9LcU" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 3: Kubernetes Step-by-step: Python, Flask, Redis, MySQL</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/WbNoEbP1n_k" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 4: Kubernetes Step-by-step: Python, Flask, Redis, MySQL</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/-_AwqIzDjBw" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 5: Kubernetes Step-by-step: Python, Flask, Redis, MySQL </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/6ehwBM75id0" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 6: Kubernetes Step-by-step: Python, Flask, Redis, MySQL </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=WfILMQFCD0o" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Part 7: Kubernetes Step-by-step: Connecting From a Windows Computer and Leveraging the Kubernetes UI to see the cluster internals</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://youtu.be/DedJurmMKC0" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Hands-On: Part 1 - Build a containerized restful service using Java with Spring/Eclipse </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=4SBxtWZ8eEE" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Hands-On: Part 2 - Build a containerized restful service using Java with Spring/Eclipse</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=HbvpZL3ryOU" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Hands-On: Part 3 - Build a containerized restful service using Java with Spring/Eclipse </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=Lbf7ZXQsaH0" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Hands-On Kubernetes - Part 1- Big Little Challenge running in Kubernetes (Java/Python/Flask) </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video</td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=lniJHXllOGw" target="_blank">Click Here</a> </td></tr> <tr> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Hands-On Kubernetes - Part 2 - Big Little Challenge running in Kubernetes (Java/Python/Flask) </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px">Video </td> <td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><a href="https://www.youtube.com/watch?v=S_etfZxlO5s" target="_blank">Click Here</a> </td></tr></tbody></table> <h2 id="video-1" style="color: darkblue">Video 1</h2> <p>This service will have some core characteristics.</p> <ul> <li>The application will run in the Azure container service as a K8s cluster  <li>It will host a web service (Python + Flask)  <li>It will include a caching layer (Redis)  <li>It will have a backend database of MySQL  <li>It will run in two pods  <ul> <li>the first pod will have both the web service and the caching layer  <li>the second pod will have a MySQL database </li></ul></li></ul> <p>The prerequisite to this session is the fact that you have a Kubernetes cluster already provisioned.</p> <p>That lab can be found here: <a href="https://www.youtube.com/watch?v=GnMdiTuU_lI">https://www.youtube.com/watch?v=GnMdiTuU_lI&amp;t=94s</a> </p> <h4 id="downloading-the-source-code" style="color: darkblue">Downloading the source code</h4> <p>You can download all the source code here:</p> <p><a href="https://github.com/brunoterkaly/k8s-multi-container">https://github.com/brunoterkaly/k8s-multi-container</a> </p> <p>The command download is:</p><pre>											<code>git clone https://github.com/brunoterkaly/k8s-multi-container.git
</code>
										</pre>
<p>You will notice that there are three folders:</p>
<ul>
<li>Build (contains the Python code to build out our web service) 
<li>Deploy (Contains the YML definition file that lets us set up our pods, services, and our containers in Kubernetes) 
<li>Run (contains the commands to deploy, operate, and manage our Kubernetes cluster) </li></ul>
<h2 id="video-2" style="color: darkblue">Video 2</h2>
<p>In this second video we are building out the web service and focusing on the Python code. We will also build out the docker image that will run in the agents of the Kubernetes cluster. We will review the Python file, Flask and some other pieces.</p>
<ul>
<li>The web service is a combination of Python and Flask 
<li>Python represents the main programming paradigm and flask as the necessary libraries to expose endpoints as web services 
<li>dockerfile is used to build out our image, which will then be uploaded to hub.docker.com 
<li>app.py represents the Python application that implements web services 
<li>buildpush.sh is some script code to do both the building of the image, as well as the uploading of the image to hub.docker.com </li></ul>
<h4 id="code-summary" style="color: darkblue">Code summary</h4>
<h4 id="dockerfile" style="color: darkblue">dockerfile</h4>
<ul>
<li>Represents the image blueprint for our docker container 
<li>Listening on port 5000 
<li>Starts up running app.py </li></ul>
<p>Dockerfile</p><pre>																			<code>FROM python:2.7-onbuild
EXPOSE 5000
CMD [ "python", "app.py" ]
</code>
																		</pre>
<h4 id="app-py" style="color: darkblue">app.py</h4>
<ul>
<li>The web service application 
<li>Imports a variety of libraries </li></ul>
<p>Expose the "init" endpoint</p>
<ul>
<li>The user will hit <a href="https://ourwebservice/init">https://ourwebservice/init</a> 
<li>And all this database code will execute 
<li></li></ul>
<p>Expose the "add" endpoint</p>
<ul>
<li>The user will hit <a href="https://ourwebservice/courses/add">https://ourwebservice/courses/add</a> 
<li>Performs an insert into the database using the data posted by the user 
<li>POST is the HTTP verb being used </li></ul>
<p>Expose the "courses/{course id}" endpoint</p>
<ul>
<li>The user will hit <a href="https://ourwebservice/courses/{course">https://ourwebservice/courses/{course</a> id} 
<li>This allows the user to query the endpoint 
<li>It will return records from either the cache or the database 
<li>If the data is not in the cache, it will be retrieved from the database, put into the cache, and returned to the client </li></ul>
<p>app.py</p><pre>																											<code>from flask import Flask
from flask import Response
from flask import request
from redis import Redis
from datetime import datetime
import MySQLdb
import sys
import redis 
import time
import hashlib
import os
import json
app = Flask(__name__)
startTime = datetime.now()
R_SERVER = redis.Redis(host=os.environ.get('REDIS_HOST', 'redis'), port=6379)
db = MySQLdb.connect("mysql","root","password")
cursor = db.cursor()
@app.route('/init')
def init():
    cursor.execute("DROP DATABASE IF EXISTS AZUREDB")
    cursor.execute("CREATE DATABASE AZUREDB")
    cursor.execute("USE AZUREDB")
    sql = """CREATE TABLE courses(id INT, coursenumber varchar(48), 
                  coursetitle varchar(256), notes varchar(256));  
     """
    cursor.execute(sql)
    db.commit()
    return "DB Initialization done\n" 
@app.route("/courses/add", methods=['POST'])
def add_courses():
    req_json = request.get_json()   
    cursor.execute("INSERT INTO courses (id, coursenumber, coursetitle, notes) VALUES (%s,%s,%s,%s)", 
          (req_json['uid'], req_json['coursenumber'], req_json['coursetitle'], req_json['notes']))
    db.commit()
    return Response("Added", status=200, mimetype='application/json')
@app.route('/courses/&lt;uid&gt;')
def get_courses(uid):
    hash = hashlib.sha224(str(uid)).hexdigest()
    key = "sql_cache:" + hash
    returnval = ""
    if (R_SERVER.get(key)):
        return R_SERVER.get(key) + "(from cache)" 
    else:
        cursor.execute("select coursenumber, coursetitle, notes from courses where ID=" + str(uid))
        data = cursor.fetchall()
        if data:
            R_SERVER.set(key,data)
            R_SERVER.expire(key, 36)
            return R_SERVER.get(key) + "\nSuccess\n"
        else:
            return "Record not found"
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
</code>
																										</pre>
<h4 id="buildpush-sh" style="color: darkblue">buildpush.sh</h4>
<p>buildpush.sh</p><pre>																											<code>docker build . -t brunoterkaly/py-red
docker push brunoterkaly/py-red
</code>
																										</pre>
<h2 id="video-3" style="color: darkblue">Video 3</h2>
<p>In this third video we will start looking at some YML files.</p>
<ul>
<li>These files define the way our containers will run in the Kubernetes cluster 
<li>They also define how the containers are organized within pods 
<li>Pods group together containers in the same host 
<li>This provides efficiency in that the containers are running close together 
<li>As described, there are two pods 
<li>On the first pod there will be two containers, the Python web service and the Redis Cache 
<li>On the second pod there will be the MySQL database 
<li>YML files just text file that define the pods and the services 
<li>The first part is called the 'web' pod </li></ul>
<table style="border-top: medium none;font-family: calibri, 'Segoe UI', tahoma, geneva, verdana, sans-serif;border-right: #b4b4b4 1px solid;border-collapse: collapse;border-bottom: #b4b4b4 1px solid;float: none;color: #000000;text-align: left;border-left: #b4b4b4 1px solid">
<tbody>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>run.sh </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>A custom script to execute all the necessary commands for the deployment </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>script file </td></tr>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>clean.sh </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>Shuts down all the pods and services in a cluster </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>script file </td></tr>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>db-pod.yml </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>The definition of the pod for the MySQL database </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>yml file </td></tr>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>db-svc.yml </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>The service layer that provides the interface to the underlying pod </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>yml file </td></tr>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>web-pod-1.yml </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>The definition of the pod for the Web Service and the Redis Cache database </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>yml file </td></tr>
<tr>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>web-svc.yml </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>The service layer that provides the interface to the underlying pod </td>
<td style="border-top: #b4b4b4 1px solid;padding-bottom: 5px;padding-top: 5px;padding-left: 10px;border-left: #b4b4b4 1px solid;padding-right: 10px"><br>yml file </td></tr></tbody></table>
<h4 id="web-pod-1-yml" style="color: darkblue">web-pod-1.yml</h4>
<p>Defines the pod for the web part of the application</p>
<p>web-pod-1.yml</p><pre>																																																					<code>apiVersion: "v1"
kind: Pod
metadata:
  name: web1
  labels:
    name: web
    app: demo
spec:
  containers:
    - name: redis
      image: redis
      ports:
        - containerPort: 6379
          name: redis
          protocol: TCP
    - name: python
      image: brunoterkaly/py-red
      env:       
        - name: "REDIS_HOST"
          value: "localhost"
      ports:
        - containerPort: 5000
          name: http
          protocol: TCP                    
</code>
																																																				</pre>
<h4 id="db-pod-yml" style="color: darkblue">db-pod.yml</h4>
<p>db-pod.yml</p><pre>																																																					<code>apiVersion: "v1"
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
    app: demo
spec:
  containers:
    - name: mysql
      image: mysql:latest
      ports:
        - containerPort: 3306         
          protocol: TCP
      env: 
        - 
          name: "MYSQL_ROOT_PASSWORD"
          value: "password"
</code>
																																																				</pre>
<h4 id="web-svc-yml" style="color: darkblue">web-svc.yml</h4>
<p>web-svc.yml</p><pre>																																																					<code>apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    name: web
    app: demo
spec:
  selector:
    name: web 
  type: NodePort
  ports:
   - port: 80
     name: http
     targetPort: 5000
     protocol: TCP
</code>
																																																				</pre>
<h4 id="db-svc-yml" style="color: darkblue">db-svc.yml</h4>
<p>db-svc.yml</p><pre>																																																					<code>apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    name: mysql
    app: demo  
spec:
  ports:
  - port: 3306
    name: mysql
    targetPort: 3306
  selector:
    name: mysql
    app: demo
</code>
																																																				</pre>
<h3 id="getting-the-config-file" style="color: darkblue">Getting the 'config' file</h3>
<p>We will need the config file to communicate with the cluster. Getting it is pretty easy.</p>
<ul>
<li>We will use the Python and Azure SDK's to retrieve this file 
<li>It will put it in a special folder from which we will copy it into the current directory </li></ul>
<p>The commands</p><pre>																																																						<code>az acs kubernetes get-credentials --resource-group=ascend-k8s-rg --name=ascend-k8s-svc
cp ~/.kube/config .
</code>
																																																					</pre>
<h3 id="setting-environment-variable-kubeconfig-and-getting-kubectl" style="color: darkblue">Setting environment variable (KUBECONFIG) and getting kubectl</h3>
<p>This environment variable is used by kubectl to know where to retrieve the config file.</p>
<p>Command looks like this:</p><pre>																																																						<code>export KUBECONFIG=`pwd`/config
</code>
																																																					</pre>
<p>We will also want to get the kubectl utility, which is the mechanism we can use to communicate with their Kubernetes cluster. It works in conjunction with the config file just addressed.</p><pre>																																																						<code>az acs kubernetes install-cli
kubectl cluster-info
</code>
																																																					</pre>
<h3 id="running-the-pods-and-services" style="color: darkblue">Running the pods and services</h3>
<p>At this point we are going to run the pods and services.</p>
<ul>
<li>We will run the file 'run.sh' 
<li>It will use the YML files 
<li>It will create pods and services </li></ul>
<p>run.sh</p><pre>																																																								<code>kubectl create -f db-pod.yml
kubectl create -f db-svc.yml
kubectl create -f web-pod-1.yml
kubectl create -f web-svc.yml
</code>
																																																							</pre>
<p>Command to list running pods:</p><pre>																																																								<code>kubectl get pods
</code>
																																																							</pre>
<p>Command to list running services:</p><pre>																																																								<code>kubectl get svc
</code>
																																																							</pre>
<p>Command to expose an external IP address for our Web service:</p><pre>																																																								<code>kubectl edit svc/web
</code>
																																																							</pre>
<p>Editing the web service file should look like this. nnotice that we did switch the <strong>type </strong>element to <strong>LoadBalancer</strong>. </p><pre>																																																								<code># Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2017-02-15T22:00:51Z
  labels:
    app: demo
    name: web
  name: web
  namespace: default
  resourceVersion: "149793"
  selfLink: /api/v1/namespaces/default/services/web
  uid: 36eee4e7-f3ca-11e6-a3cd-000d3a9203fe
spec:
  clusterIP: 10.0.73.141
  ports:
  - name: http
    nodePort: 30189
    port: 80
    protocol: TCP
    targetPort: 5000
  selector:
    name: web
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 13.89.230.209
</code>
																																																							</pre>
<h2 id="testing-the-cluster" style="color: darkblue">Testing the cluster</h2>
<p>At this point we can start testing the cluster. The pods and services are already running.</p>
<ul>
<li>In the last section we even exposed an external IP address, allowing us to pretty much access web service from anywhere 
<li>
<p>As you recall, there are three endpoints that we can use to access the web service</p>
<p>http ://XXX/init <br>http ://XXX/courses/add <br>http ://XXX/courses/{course id} 
<p></p></li></ul>
<h2 id="video-4" style="color: darkblue">Video 4</h2>
<h3 id="testing-the-application" style="color: darkblue">Testing the application</h3>
<p>We will initialize the database by hitting that endpoint using the following syntax:</p><pre>																																																												<code>curl https://13.89.230.209/init
</code>
																																																											</pre>
<p>Inserting data into the application ccan be done as follows. Be sure to remember that that public IP address gets change the public IP address that relates to your web service..</p><pre>																																																												<code>curl -i -H "Content-Type: application/json" -X POST -d '{"uid": "1", "coursenumber" : "401" , "coursetitle" : "K8s", "notes" : "An orchestrator"}' https://13.89.230.209/courses/add
curl -i -H "Content-Type: application/json" -X POST -d '{"uid": "2", "coursenumber" : "402" , "coursetitle" : "DC/OS", "notes" : "for big workloads"}' https://13.89.230.209/courses/add
curl -i -H "Content-Type: application/json" -X POST -d '{"uid": "3", "coursenumber" : "403" , "coursetitle" : "Docker Swarm", "notes" : "Easy to use"}' https://13.89.230.209/courses/add
</code>
																																																											</pre>
<p>And finally, to actually query by UID you will issue the following commands:</p><pre>																																																												<code>curl https://13.89.230.209/courses/1
curl https://13.89.230.209/courses/2
curl https://13.89.230.209/courses/3
</code>
																																																											</pre>
<p>And if you were to do it a second time. You would get information coming back from the cache rather than from the database itself.</p>]]></content:encoded>
    </item>
    <item>
      <title>Screencast/Video: Building a Java-based RESTful Service and Running it in a Docker Linux Container using the Azure Container Service</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/screencastvideo-building-a-java-based-restful-service-and-running-it-in-a-docker-linux-container-using-the-azure-container-service</link>
      <pubDate>Sun, 22 Jan 2017 13:27:17 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12515</guid>
      <description><![CDATA[Published on Jan 22, 2017  Figure 1: 1 Hour Presentation Session Abstract This session is really...]]></description>
      <content:encoded><![CDATA[<p>Published on Jan 22, 2017</p> <p><a href="https://www.youtube.com/watch?v=QsmX-_bemi0&amp;t=16s"><br><a href="https://www.youtube.com/watch?v=QsmX-_bemi0" target="_blank"><img title="introscreen0001" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="introscreen0001" src="https://msdnshared.blob.core.windows.net/media/2017/01/introscreen00011.png" width="1216" height="802"></a></a></p> <p><em>Figure 1: 1 Hour Presentation</em></p> <h3 style="color: darkblue">Session Abstract</h3> <p>This session is really about the future of computing and how web-based applications will be run at scale on large clusters that provide built-in scalability, failure recovery, and optimal price performance characteristics.</p> <p>This presentation will provide both conceptual and concrete, hands-on guidance on taking a Java-based (could be PHP, Node, etc) restful application, packaging it up to run inside of the container and ultimately on a large, cloud-based Mesosphere DC/OS Cluster. The presentation will begin with a brief overview of the history of containerization and cluster orchestration technologies, and will conclude a soup to nuts live demonstration of all the steps required to containerizing a web-based application and running it at scale in a fault-tolerant and vendor neutral (100% OSS).</p> <p>The demos will include cluster management automation, including Marathon and Mesos (DC/OS).<br>You can see my work here: <a href="https://blogs.msdn.microsoft.com/allth">https://blogs.msdn.microsoft.com/allth</a>...</p> <p>This presentation will help new and existing developers better understand how companies such as Twitter, AirBnB, Netflix run web-based applications that massive scale, leveraging containerization and cluster orchestration technologies. Participants will better understand the trends and future direction of the large public and private clouds.</p> <p>This session is about automatic scaling, failure recovery, and optimal utilization of compute, storage, and networking. Participants will walk away with a very hands-on and concrete understanding through live presentations about how all the pieces fit together.</p> <p><strong>OBJECTIVE #1</strong>: Discuss the role of containers and the value they provide for building and deploying applications, citing the work I did with McDonald's to help them design their next point-of-sale software system to run in 34,000 stores worldwide</p> <p><strong>OBJECTIVE #2</strong>: Illustrate how to take a Java-based Restful service (Spring) and create a Tomcat-based container, encapsulating the dependencies within the container</p> <p><strong>OBJECTIVE #3</strong>: Discuss and illustrate the role of container orchestration and large distributed clusters, using the Azure Container Service as the example and the Data Center Operating System (DC/OS)</p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12</link>
      <pubDate>Tue, 27 Dec 2016 09:22:36 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12485</guid>
      <description><![CDATA[The Final Countdown - Testing the application in staging We are nearing the end goal. A lot has...]]></description>
      <content:encoded><![CDATA[<h2 style="color: darkblue">The Final Countdown - Testing the application in staging</h2> <h4 style="color: darkblue">We are nearing the end goal. A lot has happened already.</h4> <p><strong>On the Jenkins Host - abbreviated steps</strong></p> <table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table> <ol> <li>We have downloaded both the app and all this devops code  <li>The app has been compiled and tested  <li>It has been placed into a docker container  <li>The app was tested inside of the docker container  <li>A tunnel was setup so we can run the container in staging  <li>The app is running in staging  <li>And at every stage - everything ran WITHOUT error  <li>We are ready for the final step - <strong>test in staging</strong> </li></ol> <h4 style="color: darkblue">This is final post for this series - but not the last post overall :-)</h4> <p>I could theoretically continue and incorporate the human approval stage.</p> <p>You could extend this example to automatically deploy to the production environment based on a human approval process, perhaps using some type of web interface. Another extension point for the series of posts is to notify developers if the build breaks, if any aspect of the pipeline breaks.</p> <p>These are aspects that will be added in the coming days.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap110.png" target="_blank"><img title="snap1" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb9.png" width="1920" height="1080"></a></p></a> <p><em>Figure 1: The big picture</em></p> <h3 style="color: darkblue">The Completed Pipeline</h3> <p>This is what the finished pipeline looks like. When we set out to build that our pipeline, the point is that it will be DevOps as code. And that’s exactly what we accomplished – we built out the entire pipeline using Python code.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00021.png" target="_blank"><img title="blog0002" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0002" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0002_thumb1.png" width="903" height="794"></a></a></p> <p><em>Figure 2: Configuring our pipeline</em></p> <h4 style="color: darkblue">The finished pipeline</h4> <p>You can see the steps below from 7 to 26 represents the entire execution pipeline.</p> <p><br>We are building out line 25 now and will represent the last piece of work necessary to complete this series of posts around Jenkins pipelines.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00031.png" target="_blank"><img title="blog0003" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0003" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0003_thumb1.png" width="1134" height="648"></a></p></a> <p><em>Figure 3: The finished Pipeline in Jenkins</em></p> <h4 style="color: darkblue">The goal of all of this work (All 12 posts)</h4> <p>What you see below is the execution of the successful bill throughout the entire pipeline without any mistakes.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00041.png" target="_blank"><img title="blog0004" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0004" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0004_thumb1.png" width="641" height="309"></a></a></p> <p><em>Figure 4: Successfully completed pipeline</em></p> <h4 style="color: darkblue">Understanding TestDockerContainerInStaging.py</h4> <table> <tbody> <tr> <td width="83">17-41</td> <td width="778">This is the method of the WebTest class that will test our application in the staging environment, which is the DC/OS cluster running in Azure data center.</td></tr> <tr> <td width="83">23-32</td> <td width="778">Error trapping code that will record an error if testing and staging fails.</td></tr> <tr> <td width="83">34-41</td> <td width="778">This is where we parse the resulting JSON string that comes back and validate that “Mesos” is returned to indicate we have successfully executed the unit test.</td></tr></tbody></table> <p><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00051.png" target="_blank"><img title="blog0005" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0005" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0005_thumb1.png" width="961" height="984"></a></a></p> <p><em>Figure 5: TestDockerContainerInStaging.py</em></p> <h4 style="color: darkblue">Validation of the app in staging</h4> <p>This is proof that the entire pipeline did its job. You can see here that the ultimate test is to go to the agents in a cluster and access the myapp application.</p> <p>Sure enough, the correct JSON string was returned to the browser.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00061.png" target="_blank"><img title="blog0006" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0006" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0006_thumb1.png" width="608" height="125"></a></a></p> <p><em>Figure 6: Validation that our pipeline worked correctly</em></p> <h3 style="color: darkblue">Conclusion</h3> <p>We achieved our goal of building out an entire pipeline that runs in Jenkins, leveraging Python script to do so. Many people argue that a DevOps pipeline is basically automated execution of code, which is exactly what we achieved here.</p> <p>I hope this post provided a concrete example on how to implement a DevOps pipeline which put applications into a DC/OS cluster running in Azure.</p> <p>I will make some modifications in the future to have this code work with Kubernetes and Docker Swarm<br>And because this is a cross-platform kit, I have a fair bit of work to get this all the work in a Windows environment.</p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11</link>
      <pubDate>Tue, 27 Dec 2016 07:53:06 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12325</guid>
      <description><![CDATA[My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1 		Click Here 		My Take on an...]]></description>
      <content:encoded><![CDATA[<table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table><h2 style="color: darkblue">Running the image in staging</h2> <h4 style="color: darkblue">We are nearing the end goal. A lot has happened already.</h4> <p><strong>On the Jenkins Host - abbreviated steps</strong></p> <ol> <li>We have downloaded both the app and all this devops code  <li>The app has been compiled and tested  <li>It has been placed into a docker container  <li>The app was tested inside of the docker container  <li>A tunnel was setup so we can run the container in staging  <li>And at every stage - everything ran WITHOUT error </li></ol> <h4 style="color: darkblue">This post - run the container in staging. And in the last post, test it in staging</h4> <p>We are moving from step 5 to 6 - running the app in staging.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap19.png" target="_blank"><img title="snap1" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb8.png" width="1920" height="1080"></a></p> <p><img title="pipeline" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="pipeline" src="https://msdnshared.blob.core.windows.net/media/2016/12/pipeline2.png" width="1357" height="992"></p></a> <p><em>Figure 1: The big picture</em></p> <h4 style="color: darkblue">The curl command to push our image to staging</h4><pre><code>curl –X POST https://localhost/marathon/v2/apps -d @marathon.json –H “Content-type: application/json”
</code></pre>
<p>Notice on the command line a json file called <strong>marathon.json</strong> is passed. This file contains all the metadata to indicate how we wish to run the app in the cluster.</p>
<p>There are a few things to notice:</p>
<ol>
<li>You can see the id of <strong>myapp</strong> 
<li>The image type is <strong>docker</strong> 
<li>Notice the hub.docker.com entry (brunoterkaly/myapp:ApacheCon-2.0). In the previous step we upload our image there 
<li><strong>BRIDGE</strong> - the DC/OS virtual network uses Linux bridge devices on agents to connect Mesos and Docker containers to the virtual network. Services can run in isolation from other traffic coming from any other virtual network or host in the cluster. 
<li><strong>portMappings</strong> - We will connect from a browser to port 80. But internally that gets mapped to 8080, which is the port that Apache (and our web app) will listen on. <br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/marathon-json.png" target="_blank"><img title="marathon-json" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="marathon-json" src="https://msdnshared.blob.core.windows.net/media/2016/12/marathon-json_thumb.png" width="1806" height="984"></a></a></li></ol>
<p><em>Figure 2: marathon.json</em></p>
<h4 style="color: darkblue">RunContainerInStaging.py</h4>
<table>
<tbody>
<tr>
<td>13-17</td>
<td>Validate that no previous errors occurred</td></tr>
<tr>
<td>25-33</td>
<td>The http POST command that deploys our app to the cluster using **marathon.json**. The image is run as a container using the image at hub.docker.com. This command assumes a **tunnel or port forwarding** has been setup.</td></tr>
<tr>
<td>40-61</td>
<td>Verifies that our app is running correctly in the cluster.</td></tr>
<tr>
<td>65-68</td>
<td>Record success or failure in MySQL</td></tr></tbody></table>
<p><a href="./images/RunContainerInStaging.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/runcontainerinstaging.png" target="_blank"><img title="runcontainerinstaging" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="runcontainerinstaging" src="https://msdnshared.blob.core.windows.net/media/2016/12/runcontainerinstaging_thumb.png" width="979" height="1341"></a></a></p>
<p><em>Figure 3: RunContainerInStaging.py</em></p>
<h4 style="color: darkblue">Conclusions</h4>
<p>Our app has been on a long journey to get to this point. It has been compiled twice and test 3 times. The next and final step is to test that app in the staging environment. We are almost finished!<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog00012.png" target="_blank"><img title="blog0001" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0001" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0001_thumb2.png" width="616" height="264"></a></a></p>
<p><em>Figure 4: App successfully in staging</em></p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10</link>
      <pubDate>Mon, 26 Dec 2016 20:25:01 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12255</guid>
      <description><![CDATA[My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1 		Click Here 		My Take on an...]]></description>
      <content:encoded><![CDATA[<table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table><h2 style="color: darkblue">Tagging and Pushing Image to <a href="https://hub.docker.com">https://hub.docker.com</a></h2> <p>Before we can run our container in the DC/OS cluster, we need to first <strong>tag</strong> it and <strong>push</strong> it to <a href="https://hub.docker.com">https://hub.docker.com</a>.</p> <p>Docker Hub is a cloud hosted service from Docker that provides registry capabilities for public and private content. Collaborate effortlessly with the broader Docker community or within your team on key content, or automate your application building workflows.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap18.png" target="_blank"><img title="snap1" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb7.png" width="1920" height="1080"></a></a></p> <p><em>Figure 1: The big picture</em></p> <h4 style="color: darkblue">Images at hub.docker.com</h4> <p>Below you can see that my image is already there. We'll as part of the devops pipeline, we need to automate this step. We will present some python code that does just that.</p> <p>This image is available for anyone right now. That is because it is in a public repo. In a future post we will show how to run this image on a DC/OS cluster as part of the pipeline execution.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap0005.png" target="_blank"><img title="snap0005" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap0005" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap0005_thumb.png" width="1071" height="736"></a></a></p> <p><em>Figure 2: brunoterkaly/myapp:ApacheCon-2.0 at hub.docker.com</em></p> <h4 style="color: darkblue">The current state of the pipeline</h4> <p>As you can see, we need to <strong>tag</strong> then <strong>push</strong> the image to hub.docker.com. Tagging is simply a way to provide the appropriate name <strong>brunoterkaly/myapp:ApacheCon-2.0</strong>. It says "<strong>ApacheCon-2.0</strong>" because I recently did a talk in Sevilla, Spain at ApacheCon Europe.<img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image595.png" width="1088" height="571"><br></a></p> <p><em>Figure 3: The current pipeline - DockerTagAndPush.py</em></p> <h4 style="color: darkblue">How to build an image (tag and push to hub.docker.com)</h4> <p>Here is some context about what we are doing. There’s a couple of steps here. The first step is to actually copy our image up to hub.docker.com.</p> <p>Once that is done, it can then be deployed to work cluster and run as a container.</p> <p><strong>This must all occur automatically as part of the pipeline</strong></p> <p>The main point here is that all of this must happen automatically as part of the pipeline execution. So in this post I will present the code that will tag and push our image up to the registry (hub.docker.com).<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap31.png" target="_blank"><img title="snap31" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap31" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap31_thumb.png" width="1885" height="1034"></a></a></p> <p><em>Figure 4: Image = Tomcat + myapp.war</em></p> <h4 style="color: darkblue">ACS Clusters</h4> <p>The Azure DC/OS cluster can be anywhere in the world. We can deploy multiple clusters as needed. For any given cluster we can easily deploy our application there, directly from hub.docker.com.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap0002.png" target="_blank"><img title="snap0002" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap0002" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap0002_thumb.png" width="1728" height="955"></a></a></p> <p><em>Figure 5: Azure's Global Footprint</em></p> <h4 style="color: darkblue">Image = "Dockerfile" + "docker build"</h4> <p>This is a quick review of how our docker image is built. We kind of glossed over this in a previous post. But here I will make it clear. Our containerized application, stored on disk as an image, is created with the <strong>Dockerfile</strong> and the <strong>Docker build</strong> command. The <strong>Dockerfile</strong> is simply a text file that takes our war file and copies it into another pre-built image, which has Java and Tomcat installed already.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap0003.png" target="_blank"><img title="snap0003" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap0003" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap0003_thumb.png" width="1809" height="1026"></a></a></p> <p><em>Figure 6: High level steps to build a docker image</em></p> <h4 style="color: darkblue">Concepts in Image Building</h4> <p>The image below demonstrates how simple it is for us to take our myapp.war and hosted inside of the container that has tomcat and Java preinstalled. Online for which starting with another image already built for us, containing tomcat and Java. Line 7 shows how simple it is to take our war file and copy it into the appropriate Web server folder for Tomcat.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap0004.png" target="_blank"><img title="snap0004" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap0004" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap0004_thumb.png" width="1835" height="1010"></a></a></p> <p><em>Figure 7: How to build our image</em></p> <h4 style="color: darkblue">DockerTagAndPush.py</h4> <table> <tbody> <tr> <td>11-21</td> <td>Issues the <strong>docker images</strong> command to get a list of images that are present on the Jenkins Host.</td></tr> <tr> <td>52-61</td> <td>Performs a search across all images on the Jenkins host. Hopefully, we will find **<strong>myapp</strong>**, which we built in previous steps. If we do find it, **<strong>tag</strong>** it and **<strong>push</strong>** to hub<strong>.docker.com</strong>.</td></tr> <tr> <td>69-71</td> <td>Verify no previous error in pipeline. If errors found, exit immediately.</td></tr> <tr> <td>73-77</td> <td>High level search for **<strong>myapp</strong>**. If not found record error and exit.</td></tr> <tr> <td>83-89</td> <td>Tag the image appropriately. It probably makes sense to generalize this and increment version numbers. We will implement this improvement later. A tag is a way to name and version your image. After tagging our image, we can then push it to <strong>hub.docker.com</strong> using the <strong>docker push</strong> command.</td></tr> <tr> <td>91-96</td> <td>This is what physically pushes the image to <strong>hub.docker.com</strong>. It essentially uploads the image. This is the core step to make the image available to run as a container in our DC/OS cluster.</td></tr></tbody></table> <p><a href="./images/dockertagandpush.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/dockertagandpush.png" target="_blank"><img title="dockertagandpush" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="dockertagandpush" src="https://msdnshared.blob.core.windows.net/media/2016/12/dockertagandpush_thumb.png" width="726" height="1848"></a></a></p> <p><em>Figure 8: Source code: DockerTagAndPush.py</em></p> <h4 style="color: darkblue">Testing DockerTagAndPush.py</h4> <p><a href="./images/snap0006.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap0006.png" target="_blank"><img title="snap0006" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap0006" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap0006_thumb.png" width="750" height="782"></a></a></p> <p><em>Figure 9: Testing DockerTagAndPush.py</em></p> <h4 style="color: darkblue">Conclusion</h4> <p>We covered a lot of ground in this post. We talked about the high-level concepts of building out our docker image. From there we described the process of building the image using the docker build command in combination with the dockerfile. We then went into some details on how one might tag, then push the image up to hub.docker.com.</p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9</link>
      <pubDate>Mon, 26 Dec 2016 09:11:47 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=12085</guid>
      <description><![CDATA[My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1 		Click Here 		My Take on an...]]></description>
      <content:encoded><![CDATA[<table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table> <h2 style="color: darkblue">Setting up a tunnel</h2> <p>Before we can talk to our <strong>DC/OS cluster</strong> running in <strong>Azure</strong>, we need to setup a <strong>tunnel</strong>. This <strong>tunnel</strong> will leverage the <strong>SSH</strong> <strong>keys</strong>. This is explained here: <a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/08/25/containerizing-java-applications-in-azure-using-dcos-and-the-azure-container-service/">https://blogs.msdn.microsoft.com/allthingscontainer/2016/08/25/containerizing-java-applications-in-azure-using-dcos-and-the-azure-container-service/</a></p> <p>Between steps 5 and 6 <strong>we need to setup a tunnel to communicate with the master node of our DC/OS cluster.</strong></p> <p>This post is about setting up that <strong>tunnel</strong>. This is often called <strong>port forwarding</strong> as well.</p> <p>The <strong>master</strong> <strong>nodes control the running of containers in the cluster.</strong></p> <p><a href="./images/Snap1.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap17.png" target="_blank"><img title="snap1" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb6.png" width="1920" height="1080"></a></a></p> <p><em>Figure 1: The big picture</em></p> <h3 style="color: darkblue">Setting up the tunnel. Running our myapp in the DC/OS cluster</h3> <p>As mentioned,<strong> our Jenkins host needs a tunnel to connect up to the DC/OS cluster running in Azure</strong>.</p> <p>Notice <strong>the tunnel connects the Jenkins host to the master nodes of the DC/OS cluster</strong>.</p> <p>You can see the <strong>ssh</strong> command to create the tunnel. You can also see the <strong>curl</strong> command. The <strong>curl</strong> command is used to run our containerized application. We'll cover that in the next post.</p> <p><a href="./images/tunnel.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/tunnel.png" target="_blank"><img title="tunnel" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="tunnel" src="https://msdnshared.blob.core.windows.net/media/2016/12/tunnel_thumb.png" width="1895" height="1024"></a></a></p> <p><em>Figure 2: Setting up tunnels</em></p> <h4 style="color: darkblue">Creating a DC/OS cluster</h4> <p>I illustrate how to do this here:</p> <p><a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/08/25/containerizing-java-applications-in-azure-using-dcos-and-the-azure-container-service/">https://blogs.msdn.microsoft.com/allthingscontainer/2016/08/25/containerizing-java-applications-in-azure-using-dcos-and-the-azure-container-service/</a></p> <p>The key takeaway is getting the <strong>MASTERFQDN</strong> and <strong>AGENTFQDN</strong>.</p> <p>The <strong>master</strong> nodes are used to run, view, delete applications in/from the cluster. The <strong>agents</strong> are what will actually run the containers (myapp).</p> <table> <tbody> <tr> <td>Developer (go to master)</td> <td>Communicates with the Master nodes</td></tr> <tr> <td>End users (go to agents)</td> <td>Get access to running applications in Agents</td></tr></tbody></table> <p><a href="./images/tunnel0001.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/tunnel0001.png" target="_blank"><img title="tunnel0001" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="tunnel0001" src="https://msdnshared.blob.core.windows.net/media/2016/12/tunnel0001_thumb.png" width="661" height="636"></a></a></p> <p><em>Figure 3: The Azure portal showing our cluster details (DC/OS)</em></p> <h3 style="color: darkblue">Python code to setup tunnel - SetupTunnelToStaging.py</h3> <p>The code below sets up a tunnel from our Jenkins host to a DC/OS cluster in Azure.</p> <table> <tbody> <tr> <td width="74">9-45</td> <td width="788">The class <strong>TunnelManager</strong> which allows us to manage the tunnel/port forwarding</td></tr> <tr> <td width="74">14-26</td> <td width="788">The <strong>netstat</strong> command which can look for tunnels already defined. We are working with port <strong>8092</strong>. It will retrieve the process id of the <strong>ssh</strong> process which manages the tunnel. We will kill this process as we will always re-establish the tunnel, removing the old one if necessary.</td></tr> <tr> <td width="74">29-36</td> <td width="788">Kill the process which controls the tunnel for port <strong>8092</strong></td></tr> <tr> <td width="74">41-45</td> <td width="788"><strong>Establish the tunnel</strong>. That means if the <strong>Jenkins host</strong> sends http commands to local host, they will end up going through the local port of <strong>8092</strong> on the Jenkins host and connecting to port <strong>2200</strong> (the listening port of the master node in the <strong>DC/OS cluster</strong>)</td></tr></tbody></table> <p><a href="https://msdnshared.blob.core.windows.net/media/2016/12/setuptunnel.png" target="_blank"><img title="setuptunnel" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="setuptunnel" src="https://msdnshared.blob.core.windows.net/media/2016/12/setuptunnel_thumb.png" width="838" height="1422"></a></a></p> <p><em>Figure 4: Source code for SetupTunnelToStaging.py</em></p> <p>Notice we are setting up the tunnel in Jenkins. Special note is that we had to use "sudo" to be able to have enough privileges to setup the tunnel.</p> <p><a href="./images/tunnel2.png" target="_blank"><br></a><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image596.png" width="1124" height="642"></a></p> <p><em>Figure 5: The current pipeline</em></p> <h4 style="color: darkblue">Successful run of the current pipeline</h4> <p>This is the Jenkins pipeline console output.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap30.png" target="_blank"><img title="snap30" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap30" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap30_thumb.png" width="822" height="544"></a></a></p> <p><em>Figure 6: Console output of the Jenkins Pipeline</em></p> <h3 style="color: darkblue">Conclusion</h3> <p>In order for us to run containers on the DC/OS cluster, we need to setup a <strong>tunnel</strong> or <strong>port forwarding</strong>, so that we can communicate with the <strong>master</strong> nodes. The code above solves some of these difficult problems.</p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8</link>
      <pubDate>Sun, 25 Dec 2016 10:05:21 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=11965</guid>
      <description><![CDATA[My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1 		Click Here 		My Take on an...]]></description>
      <content:encoded><![CDATA[<table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table><h2 style="color: darkblue">Testing Docker Image/Container</h2> <p>As we pass through step 4 we will now begin to think about testing the running container. This is a little bit tricky in that we first need to run the container, and then perform some HTTP requests upon it to verify that the appropriate return JSON string comes back.</p> <h4 style="color: darkblue">Stopping the old container</h4> <p>But what if the old containers is still running? We need code to shut it down. We can use the "<strong>docker stop</strong>" command to do so.</p> <h4 style="color: darkblue">The Unit Tests</h4> <p>Our unit tests hit an http endpoint and expect a JSON response with the string "<strong>Mesos</strong>" that ultimately comes from our MySQL Database.</p> <p>So in truth, this is testing quite a few different components all working together. It's a great sanity check before actually running the container in the staging environment and doing yet more tests.</p><a href="./images/Snap1.png" target="_blank"> <p><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap16.png" target="_blank"><img title="snap1" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb5.png" width="1920" height="1080"></a></p> <p><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image565.png" width="1118" height="522"></p></a> <p><em>Figure 1: The big picture</em></p> <p>Notice that on line 13 we begin the actual testing of our container. The test will take place on the Jenkins docker host.</p> <h4 style="color: darkblue">Running the stopped container</h4> <p>Here is some explanation of the code:</p> <table> <tbody> <tr> <td>Line(s)</td> <td>Explanation</td></tr> <tr> <td>10-48</td> <td>Two classes (explained in previous posts) that used to represent running containers. We need them to verify that our "<strong>docker run</strong>" command is working correctly here.</td></tr> <tr> <td>59-60</td> <td>The syntax for our "<strong>docker run</strong>" command. Notice that we can connect through port <strong>8090</strong> from a browser. But we are really hitting our <strong>Java application (web-based)</strong> running in <strong>Tomcat</strong> that listening on port <strong>8080</strong>.</td></tr> <tr> <td>68-82</td> <td>Verify that the container is running.</td></tr> <tr> <td>90-93</td> <td>The typical recording of state of the pipeline execution.</td></tr></tbody></table> <p><a href="./images/RunLatestDockerBuildLocally.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/runlatestdockerbuildlocally.png" target="_blank"><img title="runlatestdockerbuildlocally" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="runlatestdockerbuildlocally" src="https://msdnshared.blob.core.windows.net/media/2016/12/runlatestdockerbuildlocally_thumb.png" width="954" height="1869"></a></a></p> <p><em>Figure 2: RunLatestDockerBuildLocally.py</em></p> <h4 style="color: darkblue">Let us run RunLatestDockerBuildLocally.py</h4> <p>We have already stopped the running container from the last post. It is time to run the new one.</p> <p>We can begin testing on the command line, outside of Jenkins. The command line is an easy way to test correct operation of our Python script before incorporating it into our pipeline.</p> <p>Notice:</p> <ul> <li>We run RunLatestDockerBuildLocally.py  <li>We call ShowPipelineState.py to verify RunLatestDockerBuildLocally.py ran correctly  <li>We verify with a "docker ps" command </li></ul> <h4 style="color: darkblue">Verifying correct operation (again)</h4> <p>You can see that once we run our two Python scripts, the expected behavior results.</p> <table> <tbody> <tr> <td>python3 RunLatestDockerBuildLocally.py</td> <td>Starts our container using myapp.war</td></tr> <tr> <td>python3 ShowPipelineState.py</td> <td>Displays the messages table</td></tr> <tr> <td>docker ps</td> <td>Proves that the container is running</td></tr></tbody></table> <p><a href="./images/blog0014.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog0014.png" target="_blank"><img title="blog0014" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="blog0014" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0014_thumb.png" width="855" height="505"></a></a></p> <p><em>Figure 3: Validating RunLatestDockerBuildLocally.py</em></p> <p>Let's review the code below:</p> <h4 style="color: darkblue">TestDockerContainerLocally.py</h4> <table> <tbody> <tr> <td>Lines</td> <td>Explanation</td></tr> <tr> <td>1-10</td> <td>A few new import statements were introduced. these packages helped with the execution of an HTTP request that we are using to test our service. In addition, we will parse the JSON data that comes back from our Java-based service running inside of our container.</td></tr> <tr> <td>12-41</td> <td>The <strong>WebTest</strong> class that does our unit test using Python</td></tr> <tr> <td>23-32</td> <td>Error trapping code in the event the Web server is not available or the container is not properly exposing our application. If an error is encountered, we store that in the database.</td></tr> <tr> <td>34-41</td> <td>This is where we read the JSON response and parse it using a JSON library/package. Notice that on line 35 are looking for the magic string of "<strong>Mesos</strong>." <strong>InsertPipelineState</strong> is called appropriately throughout the script</td></tr> <tr> <td>43-45</td> <td>This is the same courtesy and all of our scripts, to verify that an error has not occurred in a previous step. we abort the script if an error was found previously.</td></tr> <tr> <td>47</td> <td>Needed for timing purposes, giving the previously executed <strong>docker run</strong> command a chance to start</td></tr> <tr> <td>49</td> <td>This is the URL which allows us to test our running container. I omitted here is the public IP address of the virtual machine where the container is running. This is the Jenkins server running in Azure. You can get the public IP of a virtual machine running in Azure from the Azure portal.</td></tr></tbody></table> <p><a href="./images/runtest.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/runtest.png" target="_blank"><img title="runtest" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="runtest" src="https://msdnshared.blob.core.windows.net/media/2016/12/runtest_thumb.png" width="841" height="884"></a></a></p> <p><em>Figure 4: TestDockerContainerLocally.py</em></p> <h4 style="color: darkblue">Testing everything</h4> <p>Notice the commands used to verify correct operation</p> <table> <tbody> <tr> <td>1</td> <td>docker ps</td> <td>Validate that container is running</td></tr> <tr> <td>2</td> <td>python3 TestDockerContainerLocally.py</td> <td>Verifying correct execution of unit test</td></tr> <tr> <td>3</td> <td>python3 ShowPipelineState.py</td> <td>Illustrate pipeline state is going well</td></tr></tbody></table> <p><a href="./images/proof.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/proof.png" target="_blank"><img title="proof" style="max-width: 100%;border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="proof" src="https://msdnshared.blob.core.windows.net/media/2016/12/proof_thumb.png" width="1583" height="612"></a></a></p> <p><em>Figure 5: Testing our Unit Test</em></p> <h4 style="color: darkblue">Conclusions</h4> <p>In this post we were looking to accomplish two tasks. The first task is to actually run our container, after making sure that the previous, old version was not running. Once we establish that our container was running, the next task was to actually run the unit test and verify correct operation.</p>  <p><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image566.png" width="638" height="242"></p>]]></content:encoded>
    </item>
    <item>
      <title>My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</title>
      <link>https://docs.microsoft.com/archive/blogs/allthingscontainer/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued</link>
      <pubDate>Fri, 23 Dec 2016 13:56:01 GMT</pubDate>
      <dc:creator><![CDATA[BrunoTerkaly]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/allthingscontainer/?p=11526</guid>
      <description><![CDATA[My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1 		Click Here 		My Take on an...]]></description>
      <content:encoded><![CDATA[<table style="width: 600px;float: none;border-bottom: #4e95f4 1px solid;text-align: left;border-left : #4e95f4 1px solid;border-collapse: collapse;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #000000;border-top: medium none;border-right: #4e95f4 1px solid"><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 1</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/17/my-take-on-an-azure-open-source-cross-platform-devops-toolkit/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 2</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/18/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-2/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 3</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/22/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-3/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 4</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-4/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 5</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-5/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 6</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 7</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/23/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-6-to-be-continued/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 8</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/25/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-8/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 9</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-9/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 10</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/26/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-10/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 11</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-11/" target="_blank">Click Here</a></td></tr><tr><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		My Take on an Azure Open Source Cross-Platform DevOps Toolkit–Part 12</td><td style="padding: 5px 10px;border-left: 1px solid #4e95f4;border-top: 1px solid #4e95f4;height: 26px"> 		<a href="https://blogs.msdn.microsoft.com/allthingscontainer/2016/12/27/my-take-on-an-azure-open-source-cross-platform-devops-toolkit-part-12/" target="_blank">Click Here</a></td></tr></table><h2 style="color: darkblue">Stopping the previously running container (myapp)</h2> <p>As we enter step 5 we will now begin to think about testing the running container.</p> <p>But before we can do that we have to make sure that firstly stop all running containers. Once we're sure that all containers are stopped, we can run the container we just built. So this post is about stopping the container.</p> <p>So between steps 3 and 4 we will stop the old running container and run the new one.<br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/snap15.png" target="_blank"><img title="snap1" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="snap1" src="https://msdnshared.blob.core.windows.net/media/2016/12/snap1_thumb4.png" width="1920" height="1080"></a></a></p> <p><em>Figure 1: The big picture</em></p> <h4 style="color: darkblue">Jenkins Pipeline Definition</h4> <p>The next 2 sections of our pipeline that need to be built.<br><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image597.png" width="1114" height="504"></a></p> <p><em>Figure 2: The current work for our pipeline</em></p> <h4 style="color: darkblue">Explanation for StopRunningContainersLocally.py</h4> <table> <tbody> <tr> <td width="90"><strong>Line(s)</strong></td> <td width="772"><strong>Explanation</strong></td></tr> <tr> <td width="90">23-64</td> <td width="772">Two objects. <strong>DockerResultList</strong> maintains a list of <strong>DockerResult</strong> objects. Each <strong>DockerResult</strong> object is a running container.</td></tr> <tr> <td width="90">9-21</td> <td width="772">Top level function that issues "<strong>docker ps</strong>" to get list of running containers. Each running container is stored as <strong>DockerResult</strong> object.</td></tr> <tr> <td width="90">55-64</td> <td width="772">Looks for an instance of a container. In our case we are looking for myapp (Container Name) to see if it is running. <strong>findContainer</strong>() returns a <strong>DockerResult</strong> object if found, else returns None. <strong>Docker</strong> result contains all the attributes of our running container, such as <strong>container id</strong>.</td></tr> <tr> <td width="90">66-69</td> <td width="772">Check pipeline for previous failures. If found, abort this Python script (<strong>StopRunningContainersLocally.py</strong>).</td></tr> <tr> <td width="90">73</td> <td width="772">Calls the high level function to kick off the whole process of discovering locally running containers.</td></tr> <tr> <td width="90">81-86</td> <td width="772">If "<strong>myapp</strong>" is running as container, issue "<strong>docker stop</strong>" command to terminate it.</td></tr> <tr> <td width="90">88-91</td> <td width="772">As always, record the state of this running container. </td></tr></tbody></table> <h4 style="color: darkblue">Source code for StopRunningContainersLocally.py</h4> <p><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2016/12/image564.png" width="872" height="1961"><a href="./images/stopcontainer.png" target="_blank"><br></a></a></p> <p><em>Figure 3: Source code for StopRunningContainersLocally.py</em></p> <h4 style="color: darkblue">Validating correct operation of StopRunningContainersLocally.py</h4> <p>The <strong>docker ps</strong> command reveals that <strong>myapp</strong> is running. Then, <strong>python3 StopRunningContainersLocally.py</strong> successfully stop <strong>myapp</strong> from running. Finally, we run <strong>ShowPipelineState.py</strong> to validate that the state is correctly being recorded.</p> <p><a href="./images/blog0012.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog0012.png" target="_blank"><img title="blog0012" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0012" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0012_thumb.png" width="981" height="457"></a></a></p> <p><em>Figure 4: Testing StopRunningContainersLocally.py</em></p> <p>Let's run a <strong>docker ps</strong> to make sure that the container is not running (myapp).</p> <p><a href="./images/blog0013.png" target="_blank"><br><a href="https://msdnshared.blob.core.windows.net/media/2016/12/blog0013.png" target="_blank"><img title="blog0013" style="border-left-width: 0px;max-width: 100%;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="blog0013" src="https://msdnshared.blob.core.windows.net/media/2016/12/blog0013_thumb.png" width="679" height="71"></a></a></p> <p><em>Figure 5: Proof that the container is not running</em></p> <h3 style="color: darkblue">Conclusion</h3> <p>We finished the work for stopping our running container. This important because our pipeline needs to do these steps:</p> <ol> <li>Build a new container  <li>Stop the old container that is running  <li>Run the new container </li></ol> <p>In the next post we will illustrate how to start the container that is freshly built.</p>]]></content:encoded>
    </item>
  </channel>
</rss>