├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Linux ├── container-dns-sample │ ├── README.md │ ├── SimpleContainerApp │ │ ├── ApplicationManifest.xml │ │ ├── nodejsfrontendPkg │ │ │ ├── ServiceManifest.xml │ │ │ ├── code │ │ │ │ └── Dummy.txt │ │ │ └── config │ │ │ │ └── Settings.xml │ │ └── pythonbackendPkg │ │ │ ├── ServiceManifest.xml │ │ │ ├── code │ │ │ └── Dummy.txt │ │ │ └── config │ │ │ └── Settings.xml │ ├── SimpleContainerAppV2 │ │ ├── ApplicationManifest.xml │ │ ├── nodejsfrontendPkg │ │ │ ├── ServiceManifest.xml │ │ │ ├── code │ │ │ │ └── Dummy.txt │ │ │ └── config │ │ │ │ └── Settings.xml │ │ └── pythonbackendPkg │ │ │ ├── ServiceManifest.xml │ │ │ ├── code │ │ │ └── Dummy.txt │ │ │ └── config │ │ │ └── Settings.xml │ ├── backend │ │ ├── Dockerfile │ │ ├── app.py │ │ └── requirements.txt │ ├── frontend │ │ ├── Dockerfile │ │ └── app.js │ ├── install.sh │ └── uninstall.sh └── container-tutorial │ ├── LICENSE │ ├── README.md │ ├── Voting │ ├── Voting │ │ ├── ApplicationManifest.xml │ │ ├── azurevotebackPkg │ │ │ ├── ServiceManifest.xml │ │ │ └── config │ │ │ │ └── Settings.xml │ │ └── azurevotefrontPkg │ │ │ ├── ServiceManifest.xml │ │ │ └── config │ │ │ └── Settings.xml │ ├── install.sh │ └── uninstall.sh │ ├── azure-vote │ ├── Dockerfile │ └── azure-vote │ │ ├── config_file.cfg │ │ ├── main.py │ │ ├── static │ │ └── default.css │ │ └── templates │ │ └── index.html │ └── docker-compose.yml ├── README.md ├── Volume ├── Application │ ├── Linux │ │ ├── ApplicationManifest.xml │ │ └── VolumeTestServicePkg │ │ │ └── ServiceManifest.xml │ └── Windows │ │ ├── ApplicationManifest.xml │ │ └── VolumeTestServicePkg │ │ └── ServiceManifest.xml ├── README.md └── src │ ├── Program.cs │ ├── VolumeTestApp.csproj │ ├── VolumeTestApp.dockerfile │ ├── build.Linux.sh │ └── build.Windows.cmd └── Windows ├── README.md └── src ├── Container.Application.sln ├── Container.Application ├── ApplicationPackageRoot │ ├── ApplicationManifest.xml │ ├── BackEndServicePkg │ │ ├── Config │ │ │ └── Settings.xml │ │ └── ServiceManifest.xml │ └── FrontEndServicePkg │ │ ├── Config │ │ └── Settings.xml │ │ └── ServiceManifest.xml ├── ApplicationParameters │ ├── Cloud.xml │ ├── Local.1Node.xml │ └── Local.5Node.xml ├── Container.Application.sfproj ├── PublishProfiles │ ├── Cloud.xml │ ├── Local.1Node.xml │ └── Local.5Node.xml ├── Scripts │ └── Deploy-FabricApplication.ps1 └── packages.config ├── Deploy ├── Build │ └── dockerbuild.bat ├── DeployContainerApplication.ps1 ├── RemoveContainerApplication.ps1 ├── ScaleoutBackendService.ps1 └── ScaleoutFrontendService.ps1 ├── FrontEndService ├── App.config ├── FrontEndService.dockerfile ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── _FrontEndService.csproj ├── GuestExe.Application ├── ApplicationPackageRoot │ ├── ApplicationManifest.xml │ ├── BackEndServicePkg │ │ ├── Config │ │ │ └── Settings.xml │ │ └── ServiceManifest.xml │ └── FrontEndServicePkg │ │ ├── Config │ │ └── Settings.xml │ │ └── ServiceManifest.xml ├── ApplicationParameters │ ├── Cloud.xml │ ├── Local.1Node.xml │ └── Local.5Node.xml ├── GuestExe.Application.sfproj ├── PublishProfiles │ ├── Cloud.xml │ ├── Local.1Node.xml │ └── Local.5Node.xml ├── Scripts │ └── Deploy-FabricApplication.ps1 └── packages.config └── NodejsBackEndService ├── BackEndService.dockerfile ├── BackEndService.js ├── README.md ├── _NodejsBackEndService.njsproj ├── index.html ├── jslocation └── index.html ├── package.json └── typings ├── globals └── node │ ├── index.d.ts │ └── typings.json └── index.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /Windows/src/Container.Application/Container.Application.sfproj.user 6 | /Windows/src/GuestExe.Application/GuestExe.Application.sfproj.user 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Azure samples 2 | 3 | Thank you for your interest in contributing to Azure samples! 4 | 5 | ## Ways to contribute 6 | 7 | You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways: 8 | 9 | - Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/service-fabric-dotnet-getting-started/) whether it was helpful or not. 10 | - Submit issues through [issue tracker](https://github.com/Azure-Samples/service-fabric-dotnet-getting-started/issues) on GitHub. We are actively monitoring the issues and improving our samples. 11 | - If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Linux/container-dns-sample/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: service-fabric 3 | platforms: Linux 4 | author: suhuruli 5 | --- 6 | 7 | # Service Fabric Container Samples 8 | This repository contains a sample project to help you get started with Service Fabric and Containers on Linux. 9 | 10 | # Linux Ubuntu 16.04 Container Sample 11 | The solution has three folders. The frontend and backend folders contain the NodeJS and Python services respectively along with their Dockerfile's. The SimpleContainerApp is the Service Fabric application that is used to deploy the containerized services. 12 | 13 | ## Prerequisites for development machine 14 | 1. Get a physical machine or Azure VM with "Ubuntu 16.04" for your development machine. 15 | 2. [Set up the developer environment](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-linux) 16 | 3. Create a Service Fabric Linux cluster on Azure with a minimum of five nodes. 17 | NOTE: The Linux demo requires a cluster running on Azure. For the purposes of this sample, you can use the [party cluster](https://try.servicefabric.azure.com/). 18 | 4. Clone or download this container solution into a directory from here onwards called **[mydirectory]** 19 | 20 | ## How to Build and Deploy the container application 21 | 1. Build the solution using gradle inside **[mydirectory]** 22 | 2. Connect to your Service Fabric cluster by running the following command 23 | 24 | ```sfctl cluster select --endpoint http://:``` 25 | 3. Use the install script provided in the directory to copy the application package to your cluster's image store, register the application type and create an instance of the application. 26 | 27 | ```./install.sh``` 28 | 4. Open a browser and browse to **http://[my.azurecluster.name]:4000** and you should see a web page with the names of the nodes the backend and frontend services are running on. 29 | 5. To remove the application from your cluster, run the uninstall script provided in the directory. Note that this command may take some time to run. 30 | 31 | ```./uninstall.sh``` 32 | 33 | ## More information 34 | The [Service Fabric container documentation](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-linux-overview) provides details on the container features and scenarios. 35 | 36 | The following are other useful links which contain more in depth information 37 | - [Create a Linux Container Application](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-containers-linux) 38 | 39 | ## MSFT OSS Code Of Conduct Notice 40 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 41 | 42 | 43 | 44 | [service-fabric-docs]: http://aka.ms/servicefabricdocs 45 | [service-fabric-containers-overview]: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-containers-overview/ 46 | [service-fabric-samples]: http://aka.ms/servicefabricsamples 47 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | /> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | /> 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/nodejsfrontendPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | suhuruli/demolinuxjs:latest 14 | 15 | 16 | 17 | 18 |       19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/nodejsfrontendPkg/code/Dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerApp/nodejsfrontendPkg/code/Dummy.txt -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/nodejsfrontendPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerApp/nodejsfrontendPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/pythonbackendPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | suhuruli/demolinux:latest 14 | 15 | 16 | 17 | 18 |       19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/pythonbackendPkg/code/Dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerApp/pythonbackendPkg/code/Dummy.txt -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerApp/pythonbackendPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerApp/pythonbackendPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | /> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | /> 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/nodejsfrontendPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | suhuruli/demolinuxjs:v2 14 | 15 | 16 | 17 | 18 |       19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/nodejsfrontendPkg/code/Dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerAppV2/nodejsfrontendPkg/code/Dummy.txt -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/nodejsfrontendPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerAppV2/nodejsfrontendPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/pythonbackendPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | suhuruli/demolinux:latest 14 | 15 | 16 | 17 | 18 |       19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/pythonbackendPkg/code/Dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerAppV2/pythonbackendPkg/code/Dummy.txt -------------------------------------------------------------------------------- /Linux/container-dns-sample/SimpleContainerAppV2/pythonbackendPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-dns-sample/SimpleContainerAppV2/pythonbackendPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-dns-sample/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Python runtime as a base image 2 | FROM python:2.7-slim 3 | 4 | # Set the working directory to /app 5 | WORKDIR /app 6 | 7 | # Copy the current directory contents into the container at /app 8 | ADD . /app 9 | 10 | # Install any needed packages specified in requirements.txt 11 | RUN pip install -r requirements.txt 12 | 13 | # Make port 80 available outside this container 14 | EXPOSE 80 15 | 16 | # Run app.py when the container launches 17 | CMD ["python", "app.py"] -------------------------------------------------------------------------------- /Linux/container-dns-sample/backend/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route("/") 7 | def retNodeName(): 8 | 9 | return os.environ.get('Fabric_NodeName') 10 | 11 | if __name__ == "__main__": 12 | app.run(host='0.0.0.0', port=80) -------------------------------------------------------------------------------- /Linux/container-dns-sample/backend/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask -------------------------------------------------------------------------------- /Linux/container-dns-sample/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Node runtime as a base image 2 | FROM node:6 3 | 4 | # Set the working directory to /app 5 | WORKDIR /app 6 | 7 | # Copy the current directory contents into the container at /app 8 | ADD . /app 9 | 10 | # Make port 8000 available outside this container 11 | EXPOSE 8000 12 | 13 | # Define environment variable 14 | ENV NAME World 15 | 16 | # Run app.js when the container launches 17 | CMD ["node", "app.js"] 18 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/frontend/app.js: -------------------------------------------------------------------------------- 1 | // Load the http module to create an http server. 2 | var http = require('http'); 3 | var dns = require('dns'); 4 | 5 | var server = http.createServer(function (request, response) { 6 | var nodeName = process.env.Fabric_NodeName; 7 | var ipAddress = ''; 8 | var port = 80; 9 | 10 | dns.resolve("pythonbackend.simplecontainerapp", function(errors, ipAddresses){ 11 | if (errors){ 12 | response.end(errors.message); 13 | } else { 14 | 15 | //extract ip address of an instance of the backend service 16 | ipAddress = ipAddresses[0]; 17 | 18 | //build options JSON for the http request 19 | var options = { 20 | host: ipAddress, 21 | port: port 22 | }; 23 | 24 | //define the callback of the backend http request 25 | callback = function(res) { 26 | var str = 'Python backend is running on: '; 27 | 28 | //chunk of data received, append to str 29 | res.on('data', function (chunk) { 30 | str += chunk; 31 | }); 32 | 33 | //the whole response has been recieved, so we just print it out here 34 | res.on('end', function () { 35 | str += " \nNodeJS frontend is running on: "; 36 | str += nodeName; 37 | response.end(str); 38 | }); 39 | } 40 | 41 | //make the http request to the backend 42 | var req = http.request(options, callback); 43 | 44 | //error received while making http request to backend 45 | req.on("error", (err) => { 46 | response.end(err.message); 47 | }); 48 | 49 | req.end(); 50 | } 51 | }); 52 | 53 | //error received so display error 54 | request.on('error', (err)=>{ 55 | response.end(err.message); 56 | }); 57 | 58 | }); 59 | 60 | // Listen on port 8000, IP defaults to 127.0.0.1 61 | server.listen(8000); 62 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | create_app() 4 | { 5 | sfctl application create --app-name fabric:/ContainerApplication --app-type SimpleContainerAppType --app-version 1.0.0 6 | sfctl service create --name fabric:/ContainerApplication/nodejsFrontEnd --service-type nodejsfrontendType --stateless --instance-count $1 --app-id ContainerApplication --singleton-scheme 7 | sfctl service create --name fabric:/ContainerApplication/pythonBackEnd --service-type pythonbackendType --stateless --instance-count $2 --app-id ContainerApplication --dns-name pythonbackend.simplecontainerapp --singleton-scheme 8 | } 9 | 10 | print_help() 11 | 12 | { 13 | echo "Additional Options" 14 | echo "-onebox (Default): If you are deploying application on one box cluster" 15 | echo "-multinode: If you are deploying application on a multi node cluster" 16 | 17 | } 18 | 19 | 20 | if [ "$1" = "--help" ] 21 | then 22 | print_help 23 | exit 0 24 | fi 25 | 26 | sfctl application upload --path SimpleContainerApp --show-progress 27 | sfctl application provision --application-type-build-path SimpleContainerApp 28 | 29 | 30 | if [ $# -eq 0 ] 31 | then 32 | echo "No arguments supplied, proceed with default instance counts" 33 | create_app 1 1 34 | elif [ $1 = "-onebox" ] 35 | then 36 | echo "Onebox environment, proceed with default instanceCount of 1 for both front and back ends." 37 | create_app 1 1 38 | elif [ $1 = "-multinode" ] 39 | then 40 | echo "MultiNode environment proceed with instanceCount of -1 for front end and 3 instance count for back end" 41 | create_app -1 3 42 | 43 | fi 44 | -------------------------------------------------------------------------------- /Linux/container-dns-sample/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sfctl application delete --application-id ContainerApplication 4 | sfctl application unprovision --application-type-name SimpleContainerAppType --application-type-version 1.0.0 5 | sfctl store delete --content-path SimpleContainerApp 6 | -------------------------------------------------------------------------------- /Linux/container-tutorial/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Linux/container-tutorial/README.md: -------------------------------------------------------------------------------- 1 | # Service Fabric Container Samples 2 | This repository contains a sample project to help you get started with Service Fabric and Containers on Linux. 3 | 4 | # Linux Ubuntu 16.04 Container Sample 5 | The solution contains two folders and a 'docker-compose.yml' file. The 'azure-vote' folder contains the Python frontend service along with the Dockerfile used to build the image. The 'Voting' directory contains the Service Fabric application package that is deployed to the cluster. Service Fabric clusters require applications to follow an application package structure and the 'Voting' directory defines that structure for this project. Alternatively, to deploy a container based solution to Service Fabric, Docker compose can be used and the 'docker-compose.yml' is the compose file used to define this project. 6 | 7 | ## Instructions to Deploy this Project 8 | Please follow the instructions on the [Service Fabric Quickstart](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-quickstart-containers-linux) to deploy this project to a Service Fabric cluster. 9 | 10 | ## More information 11 | The [Service Fabric container tutorial](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-tutorial-create-container-images) provides a more in depth walk through of how to build, package and deploy this project to a Service Fabric cluster. 12 | 13 | The following are other useful links which contain more in depth information 14 | - [Docker Compose on Service Fabric](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-docker-compose) 15 | 16 | ## MSFT OSS Code Of Conduct Notice 17 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 18 | 19 | 20 | 21 | [service-fabric-docs]: http://aka.ms/servicefabricdocs 22 | [service-fabric-containers-overview]: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-containers-overview/ 23 | [service-fabric-samples]: http://aka.ms/servicefabricsamples 24 | -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/Voting/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/Voting/azurevotebackPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | redis:alpine 14 | 15 | 16 | 17 | 18 |       19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/Voting/azurevotebackPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-tutorial/Voting/Voting/azurevotebackPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/Voting/azurevotefrontPkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | mcr.microsoft.com/azuredocs/azure-vote-front:v1 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/Voting/azurevotefrontPkg/config/Settings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Linux/container-tutorial/Voting/Voting/azurevotefrontPkg/config/Settings.xml -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export filePath=Voting 5 | export appName=Voting 6 | 7 | echo Uploading Application Files 8 | sfctl application upload --path ${filePath} --show-progress 9 | 10 | echo Provisioning Application Type 11 | sfctl application provision --application-type-build-path ${filePath} 12 | 13 | echo Creating Application 14 | sfctl application create --app-name fabric:/${appName} --app-type ${appName}Type --app-version 1.0.0 15 | -------------------------------------------------------------------------------- /Linux/container-tutorial/Voting/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sfctl application delete --application-id Voting 3 | sfctl application unprovision --application-type-name VotingType --application-type-version 1.0.0 4 | sfctl store delete --content-path Voting 5 | -------------------------------------------------------------------------------- /Linux/container-tutorial/azure-vote/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.6 2 | 3 | RUN pip install redis 4 | 5 | ADD /azure-vote /app 6 | 7 | WORKDIR /app 8 | 9 | ENV REDIS redisbackend.testapp 10 | 11 | EXPOSE 80 12 | -------------------------------------------------------------------------------- /Linux/container-tutorial/azure-vote/azure-vote/config_file.cfg: -------------------------------------------------------------------------------- 1 | # UI Configurations 2 | TITLE = 'Azure Voting App' 3 | VOTE1VALUE = 'Cats' 4 | VOTE2VALUE = 'Dogs' 5 | SHOWHOST = 'false' -------------------------------------------------------------------------------- /Linux/container-tutorial/azure-vote/azure-vote/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, render_template 2 | import os 3 | import random 4 | import redis 5 | import socket 6 | import sys 7 | 8 | app = Flask(__name__) 9 | 10 | # Load configurations 11 | app.config.from_pyfile('config_file.cfg') 12 | button1 = app.config['VOTE1VALUE'] 13 | button2 = app.config['VOTE2VALUE'] 14 | title = app.config['TITLE'] 15 | 16 | # Redis configurations 17 | redis_server = os.environ['REDIS'] 18 | 19 | @app.route('/', methods=['GET', 'POST']) 20 | def index(): 21 | 22 | if request.method == 'GET': 23 | # Redis Connection 24 | try: 25 | 26 | r = redis.StrictRedis(host=redis_server, port=6379, db=0) 27 | r.ping() 28 | 29 | # Init Redis 30 | if (r.exists(button1)): 31 | r.set(button1, r.get(button1)) 32 | else: 33 | r.set(button1,0) 34 | 35 | if (r.exists(button2)): 36 | r.set(button2, r.get(button2)) 37 | else: 38 | r.set(button2, 0) 39 | except redis.ConnectionError: 40 | exit('Failed to connect to Redis, terminating.') 41 | 42 | # Get current values 43 | vote1 = r.get(button1).decode('utf-8') 44 | vote2 = r.get(button2).decode('utf-8') 45 | 46 | # Return index with values 47 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 48 | 49 | elif request.method == 'POST': 50 | try: 51 | r = redis.StrictRedis(host=redis_server, port=6379, db=0) 52 | except redis.ConnectionError: 53 | exit('Failed to connect to Redis, terminating.') 54 | 55 | if request.form['vote'] == 'reset': 56 | 57 | # Empty table and return results 58 | r.set(button1,0) 59 | r.set(button2,0) 60 | vote1 = r.get(button1).decode('utf-8') 61 | vote2 = r.get(button2).decode('utf-8') 62 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 63 | 64 | else: 65 | 66 | # Insert vote result into DB 67 | vote = request.form['vote'] 68 | r.incr(vote,1) 69 | 70 | # Get current values 71 | vote1 = r.get(button1).decode('utf-8') 72 | vote2 = r.get(button2).decode('utf-8') 73 | 74 | # Return results 75 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 76 | 77 | if __name__ == "__main__": 78 | app.run() -------------------------------------------------------------------------------- /Linux/container-tutorial/azure-vote/azure-vote/static/default.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color:#F8F8F8; 3 | } 4 | 5 | div#container { 6 | margin-top:5%; 7 | } 8 | 9 | div#space { 10 | display:block; 11 | margin: 0 auto; 12 | width: 500px; 13 | height: 10px; 14 | 15 | } 16 | 17 | div#logo { 18 | display:block; 19 | margin: 0 auto; 20 | width: 500px; 21 | text-align: center; 22 | font-size:30px; 23 | font-family:Helvetica; 24 | /*border-bottom: 1px solid black;*/ 25 | } 26 | 27 | div#form { 28 | padding: 20px; 29 | padding-right: 20px; 30 | padding-top: 20px; 31 | display:block; 32 | margin: 0 auto; 33 | width: 500px; 34 | text-align: center; 35 | font-size:30px; 36 | font-family:Helvetica; 37 | border-bottom: 1px solid black; 38 | border-top: 1px solid black; 39 | } 40 | 41 | div#results { 42 | display:block; 43 | margin: 0 auto; 44 | width: 500px; 45 | text-align: center; 46 | font-size:30px; 47 | font-family:Helvetica; 48 | } 49 | 50 | .button { 51 | background-color: #4CAF50; /* Green */ 52 | border: none; 53 | color: white; 54 | padding: 16px 32px; 55 | text-align: center; 56 | text-decoration: none; 57 | display: inline-block; 58 | font-size: 16px; 59 | margin: 4px 2px; 60 | -webkit-transition-duration: 0.4s; /* Safari */ 61 | transition-duration: 0.4s; 62 | cursor: pointer; 63 | width: 250px; 64 | } 65 | 66 | .button1 { 67 | background-color: white; 68 | color: black; 69 | border: 2px solid #008CBA; 70 | } 71 | 72 | .button1:hover { 73 | background-color: #008CBA; 74 | color: white; 75 | } 76 | .button2 { 77 | background-color: white; 78 | color: black; 79 | border: 2px solid #555555; 80 | } 81 | 82 | .button2:hover { 83 | background-color: #555555; 84 | color: white; 85 | } 86 | 87 | .button3 { 88 | background-color: white; 89 | color: black; 90 | border: 2px solid #f44336; 91 | } 92 | 93 | .button3:hover { 94 | background-color: #f44336; 95 | color: white; 96 | } -------------------------------------------------------------------------------- /Linux/container-tutorial/azure-vote/azure-vote/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |
{{button1}} - {{ value1 }} | {{button2}} - {{ value2 }}
25 | 26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /Linux/container-tutorial/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | redisbackend.testapp: 4 | deploy: 5 | replicas: 1 6 | image: redis:alpine 7 | ports: 8 | - "6379:6379" 9 | 10 | azure-vote-front: 11 | image: mcr.microsoft.com/azuredocs/azure-vote-front:v1 12 | deploy: 13 | replicas: 1 14 | ports: 15 | - "80:80" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | languages: 3 | - csharp 4 | - javascript 5 | products: 6 | - azure 7 | - azure-container-instances 8 | - azure-service-fabric 9 | page_type: sample 10 | description: "Sample projects to help you get started with Service Fabric and Containers both on Windows and Linux." 11 | --- 12 | 13 | # Service Fabric Container Samples 14 | This repository contains sample projects to help you get started with Service Fabric and Containers both on Windows and Linux. 15 | 16 | ## Windows Server 2016 Container Sample 17 | This sample shows containers running on Windows Server 2016. The solution has a frontend service written in C# that listens for web requests on port 80 and 18 | a backend service written in nodejs that serves up a web page with information about the node it is running on. 19 | 20 | ## Linux Container Sample 21 | This folder contains two samples showing containers running on Ubuntu 16.04. 22 | 23 | The 'container-dns-sample' shows multiple containers running in Service Fabric communicating over the DNS portal. It has a frontend service written in NodeJS that listens to web requests and uses DNS resolution to request information from a backend service written in Python. The containers are built using Dockerfiles and the Service Fabric application is deployed using the traditional Service Fabric Application Package structure. 24 | 25 | The 'container-tutorial' has a frontend service in Python which communicates with a Redis data store to render a Voting UI to the user. In this example, deployments of applications using docker-compose and Service Fabric Command Line Interface are demonstrated. 26 | 27 | ## Microsoft OSS Code Of Conduct 28 | 29 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 30 | 31 | [service-fabric-docs]: http://aka.ms/servicefabricdocs 32 | [service-fabric-containers-overview]: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-containers-overview/ 33 | [service-fabric-samples]: http://aka.ms/servicefabricsamples 34 | -------------------------------------------------------------------------------- /Volume/Application/Linux/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Volume/Application/Linux/VolumeTestServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Volume/Application/Windows/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Volume/Application/Windows/VolumeTestServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Volume/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: service-fabric 3 | platforms: dotnet 4 | author: abhishekram 5 | --- 6 | # Container volume sample 7 | This sample illustrates the use of a volume, provided by an [Azure Files](https://docs.microsoft.com/azure/storage/files/storage-files-introduction) file share, in a Service Fabric container application. The volume is mounted to a specific location within the container. This is specified in the application manifest as shown below: 8 | 9 | 10 | 11 | In the above example, the volume is mounted in the path "c:\VolumeTest\Data" in the container. The sample application that runs inside the container writes a text file under this path. 12 | 13 | More information about specifying a volume for a container in a Service Fabric application is available [here](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-containers-volume-logging-drivers). 14 | 15 | ## Prerequisites 16 | ### Windows operating system 17 | This sample depends on the [Azure Files volume plugin](http://download.microsoft.com/download/C/0/3/C0373AA9-DEFA-48CF-9EBE-994CA2A5FA2F/AzureFilesVolumePlugin.6.255.389.9494.zip). The Windows version of this plugin is supported only on [Windows Server version 1709](https://docs.microsoft.com/en-us/windows-server/get-started/whats-new-in-windows-server-1709), [Windows 10 version 1709](https://docs.microsoft.com/en-us/windows/whats-new/whats-new-windows-10-version-1709) or later operating systems. Therefore this sample also works only on those operating systems. 18 | 19 | _Note:_ For Linux, the Azure Files volume plugin - and hence this sample too - works on all operating system versions supported by Service Fabric. 20 | 21 | ### Azure Files volume plugin 22 | Deploy the Azure Files volume plugin to the cluster by following the instructions in its [documentation](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-containers-volume-logging-drivers#deploy-the-service-fabric-azure-files-application). 23 | 24 | ### Create the Azure Files file share 25 | Follow the instructions in the [Azure Files documentation](https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-create-file-share) to create a file share for the application to use. 26 | 27 | ## Build the application and Docker container image 28 | The application can be built by running the _src\build.Windows.cmd_ script on Windows and the _src/build.Linux.sh_ script on Linux. Running these scripts results in the creation of the _src\pkg\Windows_ and _src/pkg/Linux_ folders which contain the application binaries for Windows and Linux respectively. They also contain the _dockerfile_ that can be used to build the Docker container image for the application. 29 | 30 | After building the application, build the Docker container image and push it to a Docker repository. An example for building a Docker container image and pushing it to a repository can be found [here](https://github.com/Azure-Samples/service-fabric-containers/tree/master/Windows#how-to-build-and-deploy-the-containerapplication). When building the Docker container image for Windows, use version 1709 or later of Windows, as per the operating system requirements mentioned [above](#windows-operating-system). 31 | 32 | ## Deploy the sample application 33 | The sample application packages for Windows and Linux can be found in the _Application\Windows_ and _Application/Linux_ folders respectively. The application can be deployed to the cluster via [PowerShell](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-deploy-remove-applications), [CLI](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-application-lifecycle-sfctl) or [FabricClient APIs](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-deploy-remove-applications-fabricclient). 34 | 35 | As an example, the steps for deploying the sample application via PowerShell are shown below. 36 | 37 | ### 1. Update the application package 38 | #### Container image information 39 | In ServiceManifest.xml, provide the path to the container image in the Docker repository. For more information, please see [above](#build-the-application-and-docker-container-image). 40 | 41 | 42 | 43 | In ApplicationManifest.xml, provide the account name and password for the repository where the Docker image is present. If the repository is public and does not require a user name and password to access, then remove the line below from the application manifest. 44 | 45 | 46 | 47 | #### Azure Files file share information 48 | In ApplicationManifest.xml, provide the storage account name, storage account key and file share name for the Azure Files file share that provides the volume for the container. 49 | 50 | 51 | 52 | 53 | 54 | ### 2. Copy the application package to the image store 55 | Run the command below with the appropriate value for [ApplicationPackagePath] and [ImageStoreConnectionString]: 56 | 57 | Copy-ServiceFabricApplicationPackage -ApplicationPackagePath [ApplicationPackagePath] -ImageStoreConnectionString [ImageStoreConnectionString] -ApplicationPackagePathInImageStore VolumeTest 58 | 59 | ### 3. Register the application type 60 | 61 | Register-ServiceFabricApplicationType -ApplicationPathInImageStore VolumeTest 62 | 63 | ### 4. Create the application 64 | 65 | New-ServiceFabricApplication -ApplicationName fabric:/VolumeTestApp -ApplicationTypeName VolumeTestAppType -ApplicationTypeVersion 1.0.0 66 | 67 | ## Verify that the application is able to use the volume 68 | As mentioned [earlier](#container-volume-sample), the sample application creates a file named _data.txt_ in the file share (if it does not exist already). The content of this file is a number that is incremented every 30 seconds by the application. To verify that the example works correctly, open the _data.txt_ file periodically and verify that the number is being updated. 69 | 70 | The file may be downloaded using any tool that enables browsing an Azure Files file share. The [Microsoft Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/) is an example of such a tool. 71 | 72 | ## Docker Hub rate limits 73 | 74 | Effective November 2, 2020, download rate limits apply to anonymous and authenticated requests to Docker Hub from Docker Free plan accounts. 75 | 76 | This sample pulls the following public images from Docker Hub. Please note that you may be rate limited. 77 | 78 | | Source | Image | 79 | | -------------|-------------| 80 | | src\VolumeTestApp.dockerfile | microsoft/dotnet:2.0-runtime | 81 | 82 | For more details, see [Authenticate with Docker Hub](https://docs.microsoft.com/en-us/azure/container-registry/buffer-gate-public-content#authenticate-with-docker-hub). 83 | -------------------------------------------------------------------------------- /Volume/src/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace AzureFilesVolumeTestApp 7 | { 8 | using System; 9 | using System.IO; 10 | using System.Threading; 11 | using System.Reflection; 12 | 13 | class Program 14 | { 15 | private const string DataFileName = "data.txt"; 16 | private const string DataFolderName = "Data"; 17 | private const int PauseBetweenUpdatesMillisec = 30000; 18 | 19 | static void Main(string[] args) 20 | { 21 | var codeFolderFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 22 | var volumeTestFolderFullPath = Path.GetDirectoryName(codeFolderFullPath); 23 | var dataFileFullPath = Path.Combine(volumeTestFolderFullPath, DataFolderName, DataFileName); 24 | 25 | var sequenceNumber = File.Exists(dataFileFullPath) ? Int32.Parse(File.ReadAllText(dataFileFullPath)) : 0; 26 | for(;;) 27 | { 28 | sequenceNumber++; 29 | File.WriteAllText(dataFileFullPath, sequenceNumber.ToString()); 30 | Thread.Sleep(PauseBetweenUpdatesMillisec); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Volume/src/VolumeTestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | win10-x64;ubuntu.16.04-x64 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Volume/src/VolumeTestApp.dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:2.0-runtime 2 | ADD bin/ /VolumeTest/Code 3 | ENTRYPOINT ["/VolumeTest/Code/VolumeTestApp"] 4 | -------------------------------------------------------------------------------- /Volume/src/build.Linux.sh: -------------------------------------------------------------------------------- 1 | rm -r ./pkg/Linux 2 | dotnet restore 3 | dotnet publish -c Release -r ubuntu.16.04-x64 -o ./pkg/Linux/bin 4 | cp VolumeTestApp.dockerfile ./pkg/Linux 5 | -------------------------------------------------------------------------------- /Volume/src/build.Windows.cmd: -------------------------------------------------------------------------------- 1 | del /S /Q .\pkg\Windows 2 | dotnet restore 3 | dotnet publish -c Release -r win10-x64 -o .\pkg\Windows\bin 4 | copy VolumeTestApp.dockerfile .\pkg\Windows -------------------------------------------------------------------------------- /Windows/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: service-fabric 3 | platforms: dotnet 4 | author: msfussell 5 | --- 6 | # Windows Server 2016 Container Sample 7 | The solution contains two projects. One deploys the services as guest executables. The other uses dockerfiles to build containerized versions of the services. 8 | In this way you can compare and contrast the difference between deploying a services as an EXEs or as containers. 9 | 10 | ## Prerequisites for development machine 11 | 1. Get a physical machine or Azure VM with "Windows Server 2016 with containers" for your development machine. 12 | 2. Install [Nodejs tools for Visual Studio](https://www.visualstudio.com/vs/node-js/) 13 | 3. Install [Nodejs 6.9.1 x64 runtime](https://nodejs.org/en/) (Note: You can choose other nodejs runtime versions, but you will need to change the dockerfile accordingly in the BackendService project) 14 | 4. Install the Service Fabric SDK (version 5.4.x and above) 15 | 5. Clone or download this container solution into a directory from here onwards called **[mydirectory]** 16 | 17 | ## How to Build and Deploy the GuestExe.Application 18 | 1. Build the VS solution 19 | 2. Go to the directory C:\\[mydirectory]\src\NodejsBackEndService\sources directory and copy the node.exe file into this. 20 | 3. Select the GuestExe.Application project, right click and select **Publish** to publish the GuestExe.Application via Visual Studio. Wait for services to deploy and start. 21 | 4. Open a browser and browse to **http://localhost**. You should see a green web page displayed with the name of the node the BackendService is running on. 22 | 23 | ## How to Build and Deploy the Container.Application 24 | 1. Build the VS solution 25 | 26 | 2. Open a console prompt at C:\\[mydirectory]\src\FrontEndService and run the following docker 27 | command replacing [myrepo] with the name of your dockerhub repo and add a version tag to the image e.g. v1, v2 28 | 29 | docker build --tag=”[myrepo]/servicefabricfrontendservice:v1” --file=”FrontEndService.dockerfile” . 30 | 31 | - NOTE: In the 5.4 release of Service Fabric runtime, when a container is deployed to Service Fabric, to communicate with docker you need to use a local host port by adding -H localhost:2375 to all your docker commmands. 32 | If you see *"error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.25/containers/json: open //./pipe/docker_engine: The system cannot find the file specified."* then instead do the following command; 33 | 34 | docker -H localhost:2375 build --tag=”[myrepo]/servicefabricfrontendservice:v1” --file=”FrontEndService.dockerfile” . 35 | 36 | 3. Download NodeJs node-v6.9.1-x64.msi [from nodejs](https://nodejs.org/en/) (or pick a version of your choice) and copy this into the C:\\[mydirectory]\src\NodejsBackEndService\sources directory. 37 | 38 | 4. Go up one directory level to C:\\[mydirectory]\src\NodejsBackEndService and run the following docker command. 39 | 40 | docker build --tag=”[myrepo]/servicefabricbackendservice:v1” --file=”BackEndService.dockerfile” . 41 | 42 | 5. Check that the images for both containers have been created in the local repository by running the following docker command. 43 | 44 | docker images 45 | 46 | 6. Next, login to your docker hub repo providing your credentials and push the images with the following docker commands. 47 | 48 | docker login 49 | 50 | docker push [myrepo]/servicefabricfrontendservice:v1 51 | 52 | docker push [myrepo]/servicefabricbackendservice:v1 53 | 54 | 7. Select the **Container.Application** project, right click and select **Publish** to publish the Container.Application from Visual Studio. Wait for services to be deployed and started. 55 | 56 | - Note: If you want to *validate* whether the services are running on your local machine, you unfortunately can't just open up **http://localhost** in your browser at this time due to 57 | [an issue in WinNAT](https://blogs.technet.microsoft.com/virtualization/2016/05/25/windows-nat-winnat-capabilities-and-limitations/). However you can use the IP Address of the Windows Container. 58 | To find that, type; 59 | 60 | docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" c8e5  61 | 62 | - Note that 'c8e5' is the start of a running Containers' Container ID, which will be different in your situation. 63 | It shows the IP Address of your running container for the FrontendService container, for example 172.20.116.222. In your environment it will be different. 64 | Open up Internet Explorer and navigate to that IP Address, and you should see a green web page. 65 | 66 | 8. Alternatively create a cluster on Azure with a "Windows 2016 with Containers" image and deploy the 67 | project to this cluster. Since all the calls here go via the Azure load balancer, you can call onto the FrontendService container. 68 | Open a browser and browse to **http://[my.azurecluster.name]:80** and you should see a green web page displayed with the name of the node the BackendService container is running on. 69 | 70 | # Debugging notes 71 | 1. If you see "Access denied" from a service this usually means that you have not ACLed the endpoint with http.sys. 72 | Ensure that protocol="http" is in the Endpoint defintion in the ServiceManiest.xml 73 | 74 | 2. To debug docker logs get the CONTAINER ID with 75 | 76 | docker ps 77 | 78 | Then get logs for the container instance 79 | 80 | docker logs [CONTAINER ID] 81 | 82 | ## More information 83 | The [Service Fabric container documentation][service-fabric-containers-overview] provides details on the container features and scenarios. 84 | 85 | Loek has these excellent blog posts on Service Fabric and Windows Containers 86 | - [Running Windows Containers on Azure Service Fabric](https://loekd.blogspot.com/2017/01/running-windows-containers-on-azure.html) 87 | - [Running Windows Containers on Azure Service Fabric Part II](https://loekd.blogspot.com/2017/01/running-windows-containers-on-azure_10.html) 88 | 89 | The [Service Fabric documentation][service-fabric-docs] includes a rich set of tutorials and conceptual articles, which serve as a good complement to the samples. -------------------------------------------------------------------------------- /Windows/src/Container.Application.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{A07B5EB6-E848-4116-A8D0-A826331D98C6}") = "Container.Application", "Container.Application\Container.Application.sfproj", "{D16F3F4A-B109-41A8-8E78-133F6D1373CF}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_FrontEndService", "FrontEndService\_FrontEndService.csproj", "{179F9B11-1EC3-4414-9384-3719E25848B7}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Deploy", "Deploy", "{FE9FD62D-A953-4AF4-ADF4-AE3991484214}" 11 | ProjectSection(SolutionItems) = preProject 12 | Deploy\DeployContainerApplication.ps1 = Deploy\DeployContainerApplication.ps1 13 | Deploy\RemoveContainerApplication.ps1 = Deploy\RemoveContainerApplication.ps1 14 | Deploy\ScaleoutBackendService.ps1 = Deploy\ScaleoutBackendService.ps1 15 | Deploy\ScaleoutFrontendService.ps1 = Deploy\ScaleoutFrontendService.ps1 16 | EndProjectSection 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{269B725D-DED0-40CB-86DC-43A9B1E1A986}" 19 | ProjectSection(SolutionItems) = preProject 20 | Deploy\Build\dockerbuild.bat = Deploy\Build\dockerbuild.bat 21 | EndProjectSection 22 | EndProject 23 | Project("{A07B5EB6-E848-4116-A8D0-A826331D98C6}") = "GuestExe.Application", "GuestExe.Application\GuestExe.Application.sfproj", "{0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}" 24 | EndProject 25 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "_NodejsBackEndService", "NodejsBackEndService\_NodejsBackEndService.njsproj", "{B560A02E-7AF5-490B-9465-A3F258E57704}" 26 | EndProject 27 | Global 28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 29 | Debug|Any CPU = Debug|Any CPU 30 | Debug|ARM = Debug|ARM 31 | Debug|x64 = Debug|x64 32 | Debug|x86 = Debug|x86 33 | Release|Any CPU = Release|Any CPU 34 | Release|ARM = Release|ARM 35 | Release|x64 = Release|x64 36 | Release|x86 = Release|x86 37 | EndGlobalSection 38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 39 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|Any CPU.ActiveCfg = Debug|x64 40 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|ARM.ActiveCfg = Debug|x64 41 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|x64.ActiveCfg = Debug|x64 42 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|x64.Build.0 = Debug|x64 43 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|x64.Deploy.0 = Debug|x64 44 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Debug|x86.ActiveCfg = Debug|x64 45 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|Any CPU.ActiveCfg = Release|x64 46 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|ARM.ActiveCfg = Release|x64 47 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|x64.ActiveCfg = Release|x64 48 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|x64.Build.0 = Release|x64 49 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|x64.Deploy.0 = Release|x64 50 | {D16F3F4A-B109-41A8-8E78-133F6D1373CF}.Release|x86.ActiveCfg = Release|x64 51 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|ARM.ActiveCfg = Debug|Any CPU 54 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|ARM.Build.0 = Debug|Any CPU 55 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|x64.ActiveCfg = Debug|Any CPU 56 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|x64.Build.0 = Debug|Any CPU 57 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|x86.ActiveCfg = Debug|Any CPU 58 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Debug|x86.Build.0 = Debug|Any CPU 59 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|Any CPU.ActiveCfg = Release|Any CPU 60 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|Any CPU.Build.0 = Release|Any CPU 61 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|ARM.ActiveCfg = Release|Any CPU 62 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|ARM.Build.0 = Release|Any CPU 63 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|x64.ActiveCfg = Release|Any CPU 64 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|x64.Build.0 = Release|Any CPU 65 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|x86.ActiveCfg = Release|Any CPU 66 | {179F9B11-1EC3-4414-9384-3719E25848B7}.Release|x86.Build.0 = Release|Any CPU 67 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|Any CPU.ActiveCfg = Debug|x64 68 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|ARM.ActiveCfg = Debug|x64 69 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|x64.ActiveCfg = Debug|x64 70 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|x64.Build.0 = Debug|x64 71 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|x64.Deploy.0 = Debug|x64 72 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Debug|x86.ActiveCfg = Debug|x64 73 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|Any CPU.ActiveCfg = Release|x64 74 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|ARM.ActiveCfg = Release|x64 75 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|x64.ActiveCfg = Release|x64 76 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|x64.Build.0 = Release|x64 77 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|x64.Deploy.0 = Release|x64 78 | {0C978D4A-E8D9-4674-9F7D-AD2CDEAD4086}.Release|x86.ActiveCfg = Release|x64 79 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 80 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|Any CPU.Build.0 = Debug|Any CPU 81 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|ARM.ActiveCfg = Debug|Any CPU 82 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|ARM.Build.0 = Debug|Any CPU 83 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|x64.ActiveCfg = Debug|Any CPU 84 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|x64.Build.0 = Debug|Any CPU 85 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|x86.ActiveCfg = Debug|Any CPU 86 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Debug|x86.Build.0 = Debug|Any CPU 87 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|Any CPU.ActiveCfg = Release|Any CPU 88 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|Any CPU.Build.0 = Release|Any CPU 89 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|ARM.ActiveCfg = Release|Any CPU 90 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|ARM.Build.0 = Release|Any CPU 91 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|x64.ActiveCfg = Release|Any CPU 92 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|x64.Build.0 = Release|Any CPU 93 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|x86.ActiveCfg = Release|Any CPU 94 | {B560A02E-7AF5-490B-9465-A3F258E57704}.Release|x86.Build.0 = Release|Any CPU 95 | EndGlobalSection 96 | GlobalSection(SolutionProperties) = preSolution 97 | HideSolutionNode = FALSE 98 | EndGlobalSection 99 | GlobalSection(NestedProjects) = preSolution 100 | {269B725D-DED0-40CB-86DC-43A9B1E1A986} = {FE9FD62D-A953-4AF4-ADF4-AE3991484214} 101 | EndGlobalSection 102 | EndGlobal 103 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationPackageRoot/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationPackageRoot/BackEndServicePkg/Config/Settings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationPackageRoot/BackEndServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | [myrepo]/servicefabricbackendservice:v1 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationPackageRoot/FrontEndServicePkg/Config/Settings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationPackageRoot/FrontEndServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | [myrepo]/servicefabricfrontendservice:v1 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationParameters/Cloud.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationParameters/Local.1Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/ApplicationParameters/Local.5Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/Container.Application.sfproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | d16f3f4a-b109-41a8-8e78-133f6d1373cf 6 | 1.4 7 | 8 | 9 | 10 | Debug 11 | x64 12 | 13 | 14 | Release 15 | x64 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/PublishProfiles/Cloud.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/PublishProfiles/Local.1Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/PublishProfiles/Local.5Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Windows/src/Container.Application/Scripts/Deploy-FabricApplication.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Deploys a Service Fabric application type to a cluster. 4 | 5 | .DESCRIPTION 6 | This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. 7 | 8 | .NOTES 9 | WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. 10 | 11 | .PARAMETER PublishProfileFile 12 | Path to the file containing the publish profile. 13 | 14 | .PARAMETER ApplicationPackagePath 15 | Path to the folder of the packaged Service Fabric application. 16 | 17 | .PARAMETER DeloyOnly 18 | Indicates that the Service Fabric application should not be created or upgraded after registering the application type. 19 | 20 | .PARAMETER ApplicationParameter 21 | Hashtable of the Service Fabric application parameters to be used for the application. 22 | 23 | .PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade 24 | Indicates whether to unregister any unused application versions that exist after an upgrade is finished. 25 | 26 | .PARAMETER OverrideUpgradeBehavior 27 | Indicates the behavior used to override the upgrade settings specified by the publish profile. 28 | 'None' indicates that the upgrade settings will not be overridden. 29 | 'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. 30 | 'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. 31 | 32 | .PARAMETER UseExistingClusterConnection 33 | Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. 34 | 35 | .PARAMETER OverwriteBehavior 36 | Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. 37 | 'Never' will not remove the existing application. This is the default behavior. 38 | 'Always' will remove the existing application even if its Application type and Version is different from the application being created. 39 | 'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. 40 | 41 | .PARAMETER SkipPackageValidation 42 | Switch signaling whether the package should be validated or not before deployment. 43 | 44 | .PARAMETER SecurityToken 45 | A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. 46 | 47 | .PARAMETER CopyPackageTimeoutSec 48 | Timeout in seconds for copying application package to image store. 49 | 50 | .EXAMPLE 51 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' 52 | 53 | Deploy the application using the default package location for a Debug build. 54 | 55 | .EXAMPLE 56 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication 57 | 58 | Deploy the application but do not create the application instance. 59 | 60 | .EXAMPLE 61 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} 62 | 63 | Deploy the application by providing values for parameters that are defined in the application manifest. 64 | #> 65 | 66 | Param 67 | ( 68 | [String] 69 | $PublishProfileFile, 70 | 71 | [String] 72 | $ApplicationPackagePath, 73 | 74 | [Switch] 75 | $DeployOnly, 76 | 77 | [Hashtable] 78 | $ApplicationParameter, 79 | 80 | [Boolean] 81 | $UnregisterUnusedApplicationVersionsAfterUpgrade, 82 | 83 | [String] 84 | [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] 85 | $OverrideUpgradeBehavior = 'None', 86 | 87 | [Switch] 88 | $UseExistingClusterConnection, 89 | 90 | [String] 91 | [ValidateSet('Never','Always','SameAppTypeAndVersion')] 92 | $OverwriteBehavior = 'Never', 93 | 94 | [Switch] 95 | $SkipPackageValidation, 96 | 97 | [String] 98 | $SecurityToken, 99 | 100 | [int] 101 | $CopyPackageTimeoutSec 102 | ) 103 | 104 | function Read-XmlElementAsHashtable 105 | { 106 | Param ( 107 | [System.Xml.XmlElement] 108 | $Element 109 | ) 110 | 111 | $hashtable = @{} 112 | if ($Element.Attributes) 113 | { 114 | $Element.Attributes | 115 | ForEach-Object { 116 | $boolVal = $null 117 | if ([bool]::TryParse($_.Value, [ref]$boolVal)) { 118 | $hashtable[$_.Name] = $boolVal 119 | } 120 | else { 121 | $hashtable[$_.Name] = $_.Value 122 | } 123 | } 124 | } 125 | 126 | return $hashtable 127 | } 128 | 129 | function Read-PublishProfile 130 | { 131 | Param ( 132 | [ValidateScript({Test-Path $_ -PathType Leaf})] 133 | [String] 134 | $PublishProfileFile 135 | ) 136 | 137 | $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) 138 | $publishProfile = @{} 139 | 140 | $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") 141 | $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") 142 | 143 | if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) 144 | { 145 | $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") 146 | if ($publishProfile.UpgradeDeployment["Mode"]) 147 | { 148 | $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true 149 | } 150 | } 151 | 152 | $publishProfileFolder = (Split-Path $PublishProfileFile) 153 | $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) 154 | 155 | return $publishProfile 156 | } 157 | 158 | $LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) 159 | 160 | if (!$PublishProfileFile) 161 | { 162 | $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" 163 | } 164 | 165 | if (!$ApplicationPackagePath) 166 | { 167 | $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" 168 | } 169 | 170 | $ApplicationPackagePath = Resolve-Path $ApplicationPackagePath 171 | 172 | $publishProfile = Read-PublishProfile $PublishProfileFile 173 | 174 | if (-not $UseExistingClusterConnection) 175 | { 176 | $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters 177 | if ($SecurityToken) 178 | { 179 | $ClusterConnectionParameters["SecurityToken"] = $SecurityToken 180 | } 181 | 182 | try 183 | { 184 | [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) 185 | } 186 | catch [System.Fabric.FabricObjectClosedException] 187 | { 188 | Write-Warning "Service Fabric cluster may not be connected." 189 | throw 190 | } 191 | } 192 | 193 | $RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" 194 | $ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath 195 | Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" 196 | 197 | $IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' 198 | 199 | if ($IsUpgrade) 200 | { 201 | $Action = "RegisterAndUpgrade" 202 | if ($DeployOnly) 203 | { 204 | $Action = "Register" 205 | } 206 | 207 | $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters 208 | 209 | if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') 210 | { 211 | # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. 212 | $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } 213 | } 214 | 215 | if ($CopyPackageTimeoutSec) 216 | { 217 | Publish-UpgradedServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -UpgradeParameters $UpgradeParameters -ApplicationParameter $ApplicationParameter -UnregisterUnusedVersions:$UnregisterUnusedApplicationVersionsAfterUpgrade -CopyPackageTimeoutSec $CopyPackageTimeoutSec -ErrorAction Stop 218 | } 219 | else 220 | { 221 | Publish-UpgradedServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -UpgradeParameters $UpgradeParameters -ApplicationParameter $ApplicationParameter -UnregisterUnusedVersions:$UnregisterUnusedApplicationVersionsAfterUpgrade -ErrorAction Stop 222 | } 223 | } 224 | else 225 | { 226 | $Action = "RegisterAndCreate" 227 | if ($DeployOnly) 228 | { 229 | $Action = "Register" 230 | } 231 | 232 | if ($CopyPackageTimeoutSec) 233 | { 234 | Publish-NewServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -ApplicationParameter $ApplicationParameter -OverwriteBehavior $OverwriteBehavior -SkipPackageValidation:$SkipPackageValidation -CopyPackageTimeoutSec $CopyPackageTimeoutSec -ErrorAction Stop 235 | } 236 | else 237 | { 238 | Publish-NewServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -ApplicationParameter $ApplicationParameter -OverwriteBehavior $OverwriteBehavior -SkipPackageValidation:$SkipPackageValidation -ErrorAction Stop 239 | } 240 | } -------------------------------------------------------------------------------- /Windows/src/Container.Application/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Windows/src/Deploy/Build/dockerbuild.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/service-fabric-containers/e6fa53a0d1589ee7a77b76304d3201bcfac6a568/Windows/src/Deploy/Build/dockerbuild.bat -------------------------------------------------------------------------------- /Windows/src/Deploy/DeployContainerApplication.ps1: -------------------------------------------------------------------------------- 1 | #Connect-ServiceFabricCluster :19000 2 | 3 | New-ServiceFabricApplication ` 4 | -ApplicationTypeName "Container.ApplicationType" ` 5 | -ApplicationTypeVersion "1.0.0" ` 6 | -ApplicationName "fabric:/Container.Application" 7 | 8 | New-ServiceFabricService ` 9 | -Stateless ` 10 | -PartitionSchemeSingleton ` 11 | -ApplicationName "fabric:/Container.Application" ` 12 | -ServiceTypeName "FrontEndServiceType" ` 13 | -ServiceName "fabric:/Container.Application/FrontEndService" ` 14 | -InstanceCount 1 15 | 16 | New-ServiceFabricService ` 17 | -Stateless ` 18 | -PartitionSchemeSingleton ` 19 | -ApplicationName "fabric:/Container.Application" ` 20 | -ServiceTypeName "BackEndServiceType" ` 21 | -ServiceName "fabric:/Container.Application/BackEndService" ` 22 | -InstanceCount 1 23 | 24 | -------------------------------------------------------------------------------- /Windows/src/Deploy/RemoveContainerApplication.ps1: -------------------------------------------------------------------------------- 1 | #Connect-ServiceFabricCluster :19000 2 | 3 | Get-ServiceFabricApplication | Remove-ServiceFabricApplication -Force 4 | Get-ServiceFabricApplicationType | Unregister-ServiceFabricApplicationType -Force -------------------------------------------------------------------------------- /Windows/src/Deploy/ScaleoutBackendService.ps1: -------------------------------------------------------------------------------- 1 | #Connect-ServiceFabricCluster :19000 2 | 3 | Update-ServiceFabricService -Stateless -ServiceName fabric:/Container.Application/BackEndService -InstanceCount -1 -Force -------------------------------------------------------------------------------- /Windows/src/Deploy/ScaleoutFrontendService.ps1: -------------------------------------------------------------------------------- 1 | #Connect-ServiceFabricCluster :19000 2 | 3 | Update-ServiceFabricService -Stateless -ServiceName fabric:/Container.Application/FrontEndService -InstanceCount -1 -Force -------------------------------------------------------------------------------- /Windows/src/FrontEndService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Windows/src/FrontEndService/FrontEndService.dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------ 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | # ------------------------------------------------------------ 5 | 6 | FROM mcr.microsoft.com/windows/servercore:10.0.14393.321 7 | LABEL Description="Guest executable on Service Fabric in a Docker container" Vendor="self" Version="1.0" 8 | ADD bin/debug/FrontEndService.exe /codelocation/ 9 | EXPOSE 80 10 | ENTRYPOINT ["/codelocation/FrontEndService.exe"] -------------------------------------------------------------------------------- /Windows/src/FrontEndService/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace FrontEndService 7 | { 8 | using System; 9 | using System.Collections.Generic; 10 | using System.IO; 11 | using System.Linq; 12 | using System.Net; 13 | using System.Net.NetworkInformation; 14 | using System.Runtime.Serialization; 15 | using System.Runtime.Serialization.Json; 16 | using System.Text; 17 | 18 | #region serializationTypes 19 | 20 | [DataContract] 21 | class AddressResult 22 | { 23 | [DataMember(Name = "Endpoints")] public Dictionary Endpoints; 24 | } 25 | 26 | [DataContract] 27 | class EndpointsResult 28 | { 29 | [DataMember(Name = "Kind")] public int Kind; 30 | 31 | [DataMember(Name = "Address")] public string Address; 32 | } 33 | 34 | [DataContract] 35 | class ResolveEndpointResult 36 | { 37 | [DataMember(Name = "Name")] public string Name; 38 | 39 | [DataMember(Name = "Endpoints")] public List Endpoints; 40 | 41 | [DataMember(Name = "Version")] public string Version; 42 | } 43 | 44 | #endregion 45 | 46 | public class FrontEndService 47 | { 48 | private string gatewayPort; 49 | private string gatewayAddress; 50 | private string previousRsp; 51 | HttpListener listener; 52 | string serviceName; 53 | bool isContainer; 54 | 55 | public FrontEndService(string gatewayPort, string serviceName, bool isContainer) 56 | { 57 | this.gatewayPort = gatewayPort; 58 | this.previousRsp = null; 59 | this.isContainer = isContainer; 60 | // Create the REST URL to talk to the Naming Service. The URL is different depending on whether the code is in a container 61 | // due to a bus in the Window Server 2016 container networking 62 | if (!isContainer) 63 | { 64 | //Get the environment variable for IP address/FQDN of the node 65 | string nodeIPAddress = Environment.GetEnvironmentVariable("Fabric_NodeIPOrFQDN"); 66 | this.gatewayAddress = String.Format("http://{0}:{1}/Services/{2}/$/ResolvePartition?api-version=1.0", nodeIPAddress, gatewayPort, serviceName); 67 | } 68 | else 69 | { 70 | this.gatewayAddress = String.Format( 71 | "http://{0}:{1}/Services/{2}/$/ResolvePartition?api-version=1.0", 72 | this.GetInternalGatewayAddress(), 73 | gatewayPort, 74 | serviceName); 75 | } 76 | this.serviceName = serviceName; 77 | } 78 | 79 | //Start an HttpListener for the FrontEndService listening on port 80. 80 | public void StartupListener() 81 | { 82 | string listenAddress; 83 | try 84 | { 85 | this.listener = new HttpListener(); 86 | // Port 80 fixed and exposed in the FrontEndService dockerfile 87 | // Need to have different listen addresses depending on whether in a container of not. 88 | // This is temporary due to Windows Server 2016 networking fix coming in a later build. 89 | if (this.isContainer) 90 | { 91 | listenAddress = String.Format("http://{0}:80/", this.GetIpAddress()); 92 | } 93 | else 94 | { 95 | listenAddress = "http://+:80/"; 96 | } 97 | this.listener.Prefixes.Add("http://+:80/"); 98 | Console.WriteLine("Listen address is {0}", listenAddress); 99 | this.listener.Start(); 100 | Console.WriteLine("HttpListener started"); 101 | string nodeName = Environment.GetEnvironmentVariable("Fabric_NodeName"); 102 | Console.WriteLine("Node Name is {0}", nodeName); 103 | string message = String.Format("\nFront End Node Name: {0}\n", nodeName); 104 | byte[] messageBuf = System.Text.Encoding.UTF8.GetBytes(message); 105 | 106 | while (true) 107 | { 108 | try 109 | { 110 | HttpListenerContext context = this.listener.GetContext(); 111 | HttpListenerRequest request = context.Request; 112 | List endpoints = this.GetEndpointAddresses(); 113 | Console.WriteLine("1st Endpoint Address {0}", endpoints[0]); 114 | int index = 0; 115 | while (index < endpoints.Count) 116 | { 117 | try 118 | { 119 | // Call the BackEndService 120 | string response = this.GetResponseFromBackend(endpoints[index]); 121 | Console.WriteLine("Writing response from backend service to client browser {0}", response); 122 | byte[] buffer = System.Text.Encoding.UTF8.GetBytes(response); 123 | context.Response.ContentLength64 = buffer.Length; 124 | System.IO.Stream output = context.Response.OutputStream; 125 | output.Write(buffer, 0, buffer.Length); 126 | 127 | //Write out the Front End Node Name into the response 128 | output.Write(messageBuf, 0, messageBuf.Length); 129 | output.Close(); 130 | } 131 | catch (Exception e) 132 | { 133 | Console.WriteLine( 134 | "Unable to connect to endpoint address {0} index {1} total addresses {2}, Exception {3}", 135 | endpoints[index], 136 | index, 137 | endpoints.Count, 138 | e.Message); 139 | index++; 140 | } 141 | } 142 | } 143 | catch (Exception e) 144 | { 145 | Console.WriteLine("Exception in GetContext {0}", e.Message); 146 | } 147 | } 148 | } 149 | catch (Exception e) 150 | { 151 | Console.WriteLine("Exception occured in startup listener {0}", e.Message); 152 | } 153 | } 154 | 155 | // Temporary workaround for Windows Server 2016 networking. See https://blogs.technet.microsoft.com/virtualization/2016/05/25/windows-nat-winnat-capabilities-and-limitations/ 156 | // Due to a bug you cannot call the host public IP Address from within a container. The workaround is to find the address 157 | // of the gateway in the container and use this to communicate to the host. This will be fixed in a future Windows Server 2016 release 158 | private string GetInternalGatewayAddress() 159 | { 160 | foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces()) 161 | { 162 | if (networkInterface.GetIPProperties().GatewayAddresses != null && 163 | networkInterface.GetIPProperties().GatewayAddresses.Count > 0) 164 | { 165 | foreach (GatewayIPAddressInformation gatewayAddr in networkInterface.GetIPProperties().GatewayAddresses) 166 | { 167 | if (gatewayAddr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 168 | { 169 | return gatewayAddr.Address.ToString(); 170 | } 171 | } 172 | } 173 | } 174 | throw new ArgumentNullException("internalgatewayaddress"); 175 | } 176 | 177 | //Get the listening IP address of the host for the Frontend service 178 | private string GetIpAddress() 179 | { 180 | IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName()); 181 | IPAddress ipAddress = hostEntry.AddressList.FirstOrDefault( 182 | ip => 183 | (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)); 184 | if (ipAddress != null) 185 | { 186 | return ipAddress.ToString(); 187 | } 188 | throw new InvalidOperationException("HostIpAddress"); 189 | } 190 | 191 | //Calls the Service Fabric Naming Service using the this.gatewayAddress set in the FrontEndService() contructor 192 | //to get a list of Endpoint addresses for the BackEndService instance registered with the Naming Service. 193 | //This demonstrates calling the ResolvePartition over REST for the the Naming Service. 194 | private List GetEndpointAddresses() 195 | { 196 | List addresses = new List(); 197 | ResolveEndpointResult result = new ResolveEndpointResult(); 198 | try 199 | { 200 | StringBuilder endpointAddress = new StringBuilder(this.gatewayAddress); 201 | if (!String.IsNullOrEmpty(this.previousRsp)) 202 | { 203 | endpointAddress.AppendFormat("&PreviousRspVersion={0}", this.previousRsp); 204 | } 205 | Console.WriteLine("Gateway address {0}", endpointAddress.ToString()); 206 | HttpWebRequest resolveRequest = (HttpWebRequest) WebRequest.Create(endpointAddress.ToString()); 207 | resolveRequest.KeepAlive = false; 208 | resolveRequest.Method = "GET"; 209 | HttpWebResponse response = (HttpWebResponse) resolveRequest.GetResponse(); 210 | Console.WriteLine("GetResponse completed"); 211 | if (response.StatusCode == HttpStatusCode.Accepted || 212 | response.StatusCode == HttpStatusCode.OK) 213 | { 214 | Stream recvStream = response.GetResponseStream(); 215 | DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ResolveEndpointResult)); 216 | Console.WriteLine("Deserializing"); 217 | result = (ResolveEndpointResult) ser.ReadObject(recvStream); 218 | this.previousRsp = result.Version; 219 | Console.WriteLine("Deserialized address {0}", result.Endpoints[0].Address); 220 | AddressResult serviceEndpoints = null; 221 | DataContractJsonSerializer deserializer = new DataContractJsonSerializer( 222 | typeof(AddressResult), 223 | new DataContractJsonSerializerSettings() {UseSimpleDictionaryFormat = true}); 224 | 225 | MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(result.Endpoints[0].Address)); 226 | serviceEndpoints = (AddressResult) deserializer.ReadObject(stream); 227 | addresses.AddRange(serviceEndpoints.Endpoints.Values); 228 | } 229 | else 230 | { 231 | Console.WriteLine("Recieved status code {0}", response.StatusCode); 232 | } 233 | } 234 | catch (Exception e) 235 | { 236 | Console.WriteLine("Exception occured {0}", e.Message); 237 | } 238 | return addresses; 239 | } 240 | 241 | // Call the BackEndService.js Nodejs application with the address returned for each endpoint. 242 | // Demonstrates calling a Nodejs application from a C# application 243 | private string GetResponseFromBackend(string endpointAddress) 244 | { 245 | try 246 | { 247 | Console.WriteLine("Getting response from {0}", endpointAddress); 248 | string resp = null; 249 | HttpWebRequest resolveRequest = (HttpWebRequest) WebRequest.Create(endpointAddress); 250 | resolveRequest.KeepAlive = false; 251 | resolveRequest.Method = "GET"; 252 | HttpWebResponse response = (HttpWebResponse) resolveRequest.GetResponse(); 253 | Console.WriteLine("GetResponse completed"); 254 | if (response.StatusCode == HttpStatusCode.Accepted || 255 | response.StatusCode == HttpStatusCode.OK) 256 | { 257 | Stream recvStream = response.GetResponseStream(); 258 | StreamReader reader = new StreamReader(recvStream); 259 | resp = reader.ReadToEnd(); 260 | } 261 | return resp; 262 | } 263 | catch (Exception e) 264 | { 265 | Console.WriteLine("Exception occured in GetResponseFrombackend Request {0}", e.Message); 266 | throw; 267 | } 268 | } 269 | } 270 | 271 | class Program 272 | { 273 | static void Main(string[] args) 274 | { 275 | //Uncomment the line below to enable debugging of the FrontEndService 276 | //System.Diagnostics.Debugger.Launch(); 277 | //Get environment variables passed into the service from the Service.xml manifest to enable the FrontEndService to communicate to the BackEndService 278 | //and indicate whether the code is running in Windows Container 279 | string serviceName = Environment.GetEnvironmentVariable("BackendServiceName"); 280 | string httpGatewayPort = Environment.GetEnvironmentVariable("HttpGatewayPort"); 281 | bool isContainer = Convert.ToBoolean(Environment.GetEnvironmentVariable("IsContainer")); 282 | Console.WriteLine("ServiceName {0}, GatewayPort {1}", serviceName, httpGatewayPort); 283 | FrontEndService frontEnd = new FrontEndService(httpGatewayPort, serviceName, isContainer); 284 | frontEnd.StartupListener(); 285 | Console.ReadKey(); 286 | } 287 | } 288 | } -------------------------------------------------------------------------------- /Windows/src/FrontEndService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Reflection; 7 | using System.Runtime.InteropServices; 8 | 9 | // General Information about an assembly is controlled through the following 10 | // set of attributes. Change these attribute values to modify the information 11 | // associated with an assembly. 12 | 13 | [assembly: AssemblyTitle("FrontEndService")] 14 | [assembly: AssemblyDescription("")] 15 | [assembly: AssemblyConfiguration("")] 16 | [assembly: AssemblyCompany("")] 17 | [assembly: AssemblyProduct("FrontEndService")] 18 | [assembly: AssemblyCopyright("Copyright © 2016")] 19 | [assembly: AssemblyTrademark("")] 20 | [assembly: AssemblyCulture("")] 21 | 22 | // Setting ComVisible to false makes the types in this assembly not visible 23 | // to COM components. If you need to access a type in this assembly from 24 | // COM, set the ComVisible attribute to true on that type. 25 | 26 | [assembly: ComVisible(false)] 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | 30 | [assembly: Guid("179f9b11-1ec3-4414-9384-3719e25848b7")] 31 | 32 | // Version information for an assembly consists of the following four values: 33 | // 34 | // Major Version 35 | // Minor Version 36 | // Build Number 37 | // Revision 38 | // 39 | // You can specify all the values or you can default the Build and Revision Numbers 40 | // by using the '*' as shown below: 41 | // [assembly: AssemblyVersion("1.0.*")] 42 | 43 | [assembly: AssemblyVersion("1.0.0.0")] 44 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Windows/src/FrontEndService/_FrontEndService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {179F9B11-1EC3-4414-9384-3719E25848B7} 8 | Exe 9 | Properties 10 | FrontEndService 11 | FrontEndService 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | TRACE;DEBUG 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 63 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationPackageRoot/ApplicationManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationPackageRoot/BackEndServicePkg/Config/Settings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationPackageRoot/BackEndServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 24 | 25 | 26 | node.exe 27 | BackEndService.js 28 | CodePackage 29 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationPackageRoot/FrontEndServicePkg/Config/Settings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationPackageRoot/FrontEndServicePkg/ServiceManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 24 | 25 | 26 | FrontEndService.exe 27 | 28 | Work 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationParameters/Cloud.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationParameters/Local.1Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/ApplicationParameters/Local.5Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/GuestExe.Application.sfproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 0c978d4a-e8d9-4674-9f7d-ad2cdead4086 6 | 1.4 7 | 8 | 9 | 10 | Debug 11 | x64 12 | 13 | 14 | Release 15 | x64 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ApplicationPackageRoot\FrontEndServicePkg\Code\FrontEndService.exe 31 | 32 | 33 | ApplicationPackageRoot\BackEndServicePkg\Code\BackEndService.js 34 | 35 | 36 | ApplicationPackageRoot\BackEndServicePkg\Code\jslocation\index.html 37 | 38 | 39 | ApplicationPackageRoot\BackEndServicePkg\Code\node.exe 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/PublishProfiles/Cloud.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/PublishProfiles/Local.1Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/PublishProfiles/Local.5Node.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/Scripts/Deploy-FabricApplication.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Deploys a Service Fabric application type to a cluster. 4 | 5 | .DESCRIPTION 6 | This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. 7 | 8 | .NOTES 9 | WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. 10 | 11 | .PARAMETER PublishProfileFile 12 | Path to the file containing the publish profile. 13 | 14 | .PARAMETER ApplicationPackagePath 15 | Path to the folder of the packaged Service Fabric application. 16 | 17 | .PARAMETER DeloyOnly 18 | Indicates that the Service Fabric application should not be created or upgraded after registering the application type. 19 | 20 | .PARAMETER ApplicationParameter 21 | Hashtable of the Service Fabric application parameters to be used for the application. 22 | 23 | .PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade 24 | Indicates whether to unregister any unused application versions that exist after an upgrade is finished. 25 | 26 | .PARAMETER OverrideUpgradeBehavior 27 | Indicates the behavior used to override the upgrade settings specified by the publish profile. 28 | 'None' indicates that the upgrade settings will not be overridden. 29 | 'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. 30 | 'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. 31 | 32 | .PARAMETER UseExistingClusterConnection 33 | Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. 34 | 35 | .PARAMETER OverwriteBehavior 36 | Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. 37 | 'Never' will not remove the existing application. This is the default behavior. 38 | 'Always' will remove the existing application even if its Application type and Version is different from the application being created. 39 | 'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. 40 | 41 | .PARAMETER SkipPackageValidation 42 | Switch signaling whether the package should be validated or not before deployment. 43 | 44 | .PARAMETER SecurityToken 45 | A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. 46 | 47 | .PARAMETER CopyPackageTimeoutSec 48 | Timeout in seconds for copying application package to image store. 49 | 50 | .EXAMPLE 51 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' 52 | 53 | Deploy the application using the default package location for a Debug build. 54 | 55 | .EXAMPLE 56 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication 57 | 58 | Deploy the application but do not create the application instance. 59 | 60 | .EXAMPLE 61 | . Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} 62 | 63 | Deploy the application by providing values for parameters that are defined in the application manifest. 64 | #> 65 | 66 | Param 67 | ( 68 | [String] 69 | $PublishProfileFile, 70 | 71 | [String] 72 | $ApplicationPackagePath, 73 | 74 | [Switch] 75 | $DeployOnly, 76 | 77 | [Hashtable] 78 | $ApplicationParameter, 79 | 80 | [Boolean] 81 | $UnregisterUnusedApplicationVersionsAfterUpgrade, 82 | 83 | [String] 84 | [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] 85 | $OverrideUpgradeBehavior = 'None', 86 | 87 | [Switch] 88 | $UseExistingClusterConnection, 89 | 90 | [String] 91 | [ValidateSet('Never','Always','SameAppTypeAndVersion')] 92 | $OverwriteBehavior = 'Never', 93 | 94 | [Switch] 95 | $SkipPackageValidation, 96 | 97 | [String] 98 | $SecurityToken, 99 | 100 | [int] 101 | $CopyPackageTimeoutSec 102 | ) 103 | 104 | function Read-XmlElementAsHashtable 105 | { 106 | Param ( 107 | [System.Xml.XmlElement] 108 | $Element 109 | ) 110 | 111 | $hashtable = @{} 112 | if ($Element.Attributes) 113 | { 114 | $Element.Attributes | 115 | ForEach-Object { 116 | $boolVal = $null 117 | if ([bool]::TryParse($_.Value, [ref]$boolVal)) { 118 | $hashtable[$_.Name] = $boolVal 119 | } 120 | else { 121 | $hashtable[$_.Name] = $_.Value 122 | } 123 | } 124 | } 125 | 126 | return $hashtable 127 | } 128 | 129 | function Read-PublishProfile 130 | { 131 | Param ( 132 | [ValidateScript({Test-Path $_ -PathType Leaf})] 133 | [String] 134 | $PublishProfileFile 135 | ) 136 | 137 | $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) 138 | $publishProfile = @{} 139 | 140 | $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") 141 | $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") 142 | 143 | if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) 144 | { 145 | $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") 146 | if ($publishProfile.UpgradeDeployment["Mode"]) 147 | { 148 | $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true 149 | } 150 | } 151 | 152 | $publishProfileFolder = (Split-Path $PublishProfileFile) 153 | $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) 154 | 155 | return $publishProfile 156 | } 157 | 158 | $LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) 159 | 160 | if (!$PublishProfileFile) 161 | { 162 | $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" 163 | } 164 | 165 | if (!$ApplicationPackagePath) 166 | { 167 | $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" 168 | } 169 | 170 | $ApplicationPackagePath = Resolve-Path $ApplicationPackagePath 171 | 172 | $publishProfile = Read-PublishProfile $PublishProfileFile 173 | 174 | if (-not $UseExistingClusterConnection) 175 | { 176 | $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters 177 | if ($SecurityToken) 178 | { 179 | $ClusterConnectionParameters["SecurityToken"] = $SecurityToken 180 | } 181 | 182 | try 183 | { 184 | [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) 185 | } 186 | catch [System.Fabric.FabricObjectClosedException] 187 | { 188 | Write-Warning "Service Fabric cluster may not be connected." 189 | throw 190 | } 191 | } 192 | 193 | $RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" 194 | $ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath 195 | Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" 196 | 197 | $IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' 198 | 199 | if ($IsUpgrade) 200 | { 201 | $Action = "RegisterAndUpgrade" 202 | if ($DeployOnly) 203 | { 204 | $Action = "Register" 205 | } 206 | 207 | $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters 208 | 209 | if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') 210 | { 211 | # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. 212 | $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } 213 | } 214 | 215 | if ($CopyPackageTimeoutSec) 216 | { 217 | Publish-UpgradedServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -UpgradeParameters $UpgradeParameters -ApplicationParameter $ApplicationParameter -UnregisterUnusedVersions:$UnregisterUnusedApplicationVersionsAfterUpgrade -CopyPackageTimeoutSec $CopyPackageTimeoutSec -ErrorAction Stop 218 | } 219 | else 220 | { 221 | Publish-UpgradedServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -UpgradeParameters $UpgradeParameters -ApplicationParameter $ApplicationParameter -UnregisterUnusedVersions:$UnregisterUnusedApplicationVersionsAfterUpgrade -ErrorAction Stop 222 | } 223 | } 224 | else 225 | { 226 | $Action = "RegisterAndCreate" 227 | if ($DeployOnly) 228 | { 229 | $Action = "Register" 230 | } 231 | 232 | if ($CopyPackageTimeoutSec) 233 | { 234 | Publish-NewServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -ApplicationParameter $ApplicationParameter -OverwriteBehavior $OverwriteBehavior -SkipPackageValidation:$SkipPackageValidation -CopyPackageTimeoutSec $CopyPackageTimeoutSec -ErrorAction Stop 235 | } 236 | else 237 | { 238 | Publish-NewServiceFabricApplication -ApplicationPackagePath $ApplicationPackagePath -ApplicationParameterFilePath $publishProfile.ApplicationParameterFile -Action $Action -ApplicationParameter $ApplicationParameter -OverwriteBehavior $OverwriteBehavior -SkipPackageValidation:$SkipPackageValidation -ErrorAction Stop 239 | } 240 | } -------------------------------------------------------------------------------- /Windows/src/GuestExe.Application/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/BackEndService.dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------ 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | # ------------------------------------------------------------ 5 | 6 | FROM mcr.microsoft.com/windows/servercore:latest 7 | LABEL Description="Guest executable on Service Fabric in a Docker container" Vendor="self" Version="1.0" 8 | ADD sources /build 9 | ADD BackEndService.js /jslocation/ 10 | ADD index.html /jslocation/ 11 | RUN msiexec /i C:\build\node-v6.9.1-x64.msi /qn /l*v C:\build\node-v6.9.1-x64.msi.log & del C:\build\node-v6.9.1-x64.msi 12 | EXPOSE 8905 13 | ENTRYPOINT ["node.exe", "/jslocation/BackEndService.js"] -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/BackEndService.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | // Get a list of the local IP addresses and display them. 7 | // This code is needed for a container to work around the Windows Server NAT issue. 8 | 'use strict'; 9 | var os = require('os'); 10 | var ifaces = os.networkInterfaces(); 11 | var result; 12 | Object.keys(ifaces).forEach(function (ifname) { 13 | var alias = 0; 14 | ifaces[ifname].forEach(function (iface) { 15 | if ('IPv4' !== iface.family || iface.internal !== false) { 16 | return; 17 | } 18 | console.log(ifname, iface.address); 19 | result = iface.address; 20 | ++alias; 21 | }); 22 | }); 23 | 24 | // Start server and load index.html getting the environment Service Fabric environment variable for the node name 25 | console.log("Service Fabric Nodejs container service"); 26 | console.log("Fabric Node: %s", process.env.Fabric_NodeName); 27 | var http = require('http'); 28 | var fs = require('fs'); 29 | fs.readFile('./jslocation/index.html', function (err, html) { 30 | if (err) { 31 | throw err; 32 | } 33 | console.log("Starting web server. Listening on port 8905"); 34 | if (process.env.IsContainer != "true") 35 | { 36 | result = process.env.Fabric_NodeIPOrFQDN; 37 | } 38 | console.log("Listening on address " + result); 39 | http.createServer(function (req, res) { 40 | res.writeHead(200, { 'Content-Type': 'text/html' }); 41 | res.write(""); 42 | res.write(""); 43 | res.write(""); 44 | res.write("

"); 45 | res.write("Node Name: " + process.env.Fabric_NodeName); 46 | res.write("

"); 47 | res.write(""); 48 | res.write(""); 49 | res.write(html); 50 | res.end(); 51 | }).listen(8905, result); 52 | }); -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/README.md: -------------------------------------------------------------------------------- 1 | # NodejsBackEndService 2 | 3 | 4 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/_NodejsBackEndService.njsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | _NodejsBackEndService 7 | NodejsBackEndService 8 | 9 | 10 | 11 | Debug 12 | 2.0 13 | b560a02e-7af5-490b-9465-a3f258e57704 14 | 15 | 16 | BackEndService.js 17 | 18 | 19 | . 20 | . 21 | v4.0 22 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 23 | ShowAllFiles 24 | 1337 25 | true 26 | 27 | 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | False 60 | True 61 | 0 62 | / 63 | http://localhost:48022/ 64 | False 65 | True 66 | http://localhost:1337 67 | False 68 | 69 | 70 | 71 | 72 | 73 | 74 | CurrentPage 75 | True 76 | False 77 | False 78 | False 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | False 88 | False 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

nodejs service running on Service Fabric

5 | 6 |

7 | 8 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/jslocation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

nodejs service running on Service Fabric

5 | 6 |

7 | 8 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-back-end-service", 3 | "version": "0.0.0", 4 | "description": "NodejsBackEndService", 5 | "main": "BackEndService.js", 6 | "author": { 7 | "name": "microsoft" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/typings/globals/node/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution": "main", 3 | "tree": { 4 | "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/8928fc6a3d6e0b7808b12bb4097c232015c7f865/node/index.d.ts", 5 | "raw": "registry:dt/node#7.0.0+20170110233017", 6 | "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/8928fc6a3d6e0b7808b12bb4097c232015c7f865/node/index.d.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Windows/src/NodejsBackEndService/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | --------------------------------------------------------------------------------