diff --git a/.gitignore b/.gitignore index 9cac0be528e3f..97a7c198824ba 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,4 @@ log/ # Spelling add-on file for VS Code. spell.json samples/framework/docker/MVCRandomAnswerGenerator/containerImage +.DS_Store \ No newline at end of file diff --git a/docs/core/docker/building-net-docker-images.md b/docs/core/docker/building-net-docker-images.md index 5369fe66ac586..701cce54e4ecb 100644 --- a/docs/core/docker/building-net-docker-images.md +++ b/docs/core/docker/building-net-docker-images.md @@ -93,6 +93,9 @@ npm install -g yo generator-aspnet generator-docker For a reference point, before we containerize the application, first run the application locally. +The finished application is located in the +[dotnet/core-docs repository on GitHub](https://github.com/dotnet/docs/tree/master/samples/core/docker/building-net-docker-images). + Create a directory for your application. Open a command or terminal session in that directory and use the ASP.NET Yeoman generator by typing the following: diff --git a/samples/core/docker/building-net-docker-images/.gitignore b/samples/core/docker/building-net-docker-images/.gitignore new file mode 100644 index 0000000000000..0ca27f04e171b --- /dev/null +++ b/samples/core/docker/building-net-docker-images/.gitignore @@ -0,0 +1,234 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/samples/core/docker/building-net-docker-images/.vscode/launch.json b/samples/core/docker/building-net-docker-images/.vscode/launch.json new file mode 100644 index 0000000000000..158f1fb691a2c --- /dev/null +++ b/samples/core/docker/building-net-docker-images/.vscode/launch.json @@ -0,0 +1,39 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name":".NET Core Docker Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "composeForDebug", + "cwd": "/app", + "program": "/app/api.dll", + "sourceFileMap": { + "/app": "${workspaceRoot}" + }, + + "launchBrowser": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + } + }, + + "pipeTransport": { + "pipeProgram": "/bin/bash", + "pipeCwd": "${workspaceRoot}", + "pipeArgs": [ "-c", "./dockerTask.sh startDebugging" ], + "windows": { + "pipeProgram": "${env.windir}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "pipeCwd": "${workspaceRoot}", + "pipeArgs": [ ".\\dockerTask.ps1", "-StartDebugging" ] + } + } + } + ] +} \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/.vscode/settings.json b/samples/core/docker/building-net-docker-images/.vscode/settings.json new file mode 100644 index 0000000000000..741a1d1691968 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "dockerfile.*": "dockerfile" + } +} \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/.vscode/tasks.json b/samples/core/docker/building-net-docker-images/.vscode/tasks.json new file mode 100644 index 0000000000000..2c4b213507a59 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/.vscode/tasks.json @@ -0,0 +1,66 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "0.1.0", + "windows": { + "command": "powershell", + "options": { + "cwd": "${workspaceRoot}" + }, + "tasks": [ + { + "taskName": "build", + "suppressTaskName": true, + "args": ["-ExecutionPolicy", "RemoteSigned", ".\\dockerTask.ps1", "-Build", "-Environment", "debug" ], + "isBuildCommand": true, + "showOutput": "always", + "echoCommand": true + }, + { + "taskName": "compose", + "suppressTaskName": true, + "args": ["-ExecutionPolicy", "RemoteSigned", ".\\dockerTask.ps1", "-Compose", "-Environment", "debug" ], + "isBuildCommand": false, + "showOutput": "always", + "echoCommand": true + }, + { + "taskName": "composeForDebug", + "suppressTaskName": true, + "args": ["-ExecutionPolicy", "RemoteSigned", ".\\dockerTask.ps1", "-ComposeForDebug", "-Environment", "debug" ], + "isBuildCommand": false, + "showOutput": "always", + "echoCommand": true + } + ] + }, + "osx": { + "command": "/bin/bash", + "options": { + "cwd": "${workspaceRoot}" + }, + "tasks": [ + { + "taskName": "build", + "suppressTaskName": true, + "args": [ "-c", "./dockerTask.sh build debug" ], + "isBuildCommand": true, + "showOutput": "always" + }, + { + "taskName": "compose", + "suppressTaskName": true, + "args": [ "-c", "./dockerTask.sh compose debug" ], + "isBuildCommand": false, + "showOutput": "always" + }, + { + "taskName": "composeForDebug", + "suppressTaskName": true, + "args": [ "-c", "./dockerTask.sh composeForDebug debug" ], + "isBuildCommand": false, + "showOutput": "always" + } + ] + } +} \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/Controllers/ValuesController.cs b/samples/core/docker/building-net-docker-images/Controllers/ValuesController.cs new file mode 100644 index 0000000000000..36b5c10a0176c --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Controllers/ValuesController.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace api.Controllers +{ + [Route("api/[controller]")] + public class ValuesController : Controller + { + // GET api/values + [HttpGet] + public IEnumerable Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public string Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody]string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody]string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/samples/core/docker/building-net-docker-images/Dockerfile b/samples/core/docker/building-net-docker-images/Dockerfile new file mode 100644 index 0000000000000..ad35eabb48f2a --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Dockerfile @@ -0,0 +1,6 @@ +FROM microsoft/dotnet:1.0.0-core +WORKDIR /app +ENV ASPNETCORE_URLS http://*:5000 +EXPOSE 5000 +ENTRYPOINT ["dotnet", "api.dll"] +COPY . /app diff --git a/samples/core/docker/building-net-docker-images/Dockerfile.debug b/samples/core/docker/building-net-docker-images/Dockerfile.debug new file mode 100644 index 0000000000000..ca3cc8904b0cf --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Dockerfile.debug @@ -0,0 +1,13 @@ +FROM microsoft/dotnet:1.0.0-preview2-sdk +ENV NUGET_XMLDOC_MODE skip +ARG CLRDBG_VERSION=VS2015U2 +WORKDIR /clrdbg +RUN curl -SL https://raw.githubusercontent.com/Microsoft/MIEngine/getclrdbg-release/scripts/GetClrDbg.sh --output GetClrDbg.sh \ + && chmod 700 GetClrDbg.sh \ + && ./GetClrDbg.sh $CLRDBG_VERSION \ + && rm GetClrDbg.sh +WORKDIR /app +ENV ASPNETCORE_URLS http://*:5000 +EXPOSE 5000 +ENTRYPOINT ["/bin/bash", "-c", "if [ -z \"$REMOTE_DEBUGGING\" ]; then dotnet api.dll; else sleep infinity; fi"] +COPY . /app diff --git a/samples/core/docker/building-net-docker-images/Program.cs b/samples/core/docker/building-net-docker-images/Program.cs new file mode 100644 index 0000000000000..288f2566bf53c --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Program.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; + +namespace api +{ + public class Program + { + public static void Main(string[] args) + { + var config = new ConfigurationBuilder() + .AddCommandLine(args) + .AddEnvironmentVariables(prefix: "ASPNETCORE_") + .Build(); + + var host = new WebHostBuilder() + .UseConfiguration(config) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup() + .Build(); + + host.Run(); + } + } +} diff --git a/samples/core/docker/building-net-docker-images/Properties/launchSettings.json b/samples/core/docker/building-net-docker-images/Properties/launchSettings.json new file mode 100644 index 0000000000000..94751e8786427 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Properties/launchSettings.json @@ -0,0 +1,28 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:1479/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "api": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "http://localhost:5000/api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/core/docker/building-net-docker-images/README.md b/samples/core/docker/building-net-docker-images/README.md new file mode 100644 index 0000000000000..a066c38f1bc2d --- /dev/null +++ b/samples/core/docker/building-net-docker-images/README.md @@ -0,0 +1,39 @@ +# Welcome to ASP.NET Core + +We've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new. + +You've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016) + +## This application consists of: + +* Sample pages using ASP.NET Core MVC +* [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries +* Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939) + +## How to + +* [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600) +* [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562) +* [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315) +* [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316) +* [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317) +* [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318) +* [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319) + +## Overview + +* [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008) +* [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320) +* [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602) +* [Security](https://go.microsoft.com/fwlink/?LinkId=398603) +* [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321) +* [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322) +* [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323) + +## Run & Deploy + +* [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851) +* [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853) +* [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609) + +We would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015) diff --git a/samples/core/docker/building-net-docker-images/Startup.cs b/samples/core/docker/building-net-docker-images/Startup.cs new file mode 100644 index 0000000000000..ac41e89dd26d6 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/Startup.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace api +{ + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddEnvironmentVariables(); + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services.AddMvc(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + loggerFactory.AddDebug(); + + app.UseMvc(); + } + } +} diff --git a/samples/core/docker/building-net-docker-images/appsettings.json b/samples/core/docker/building-net-docker-images/appsettings.json new file mode 100755 index 0000000000000..723c096a87e9a --- /dev/null +++ b/samples/core/docker/building-net-docker-images/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/samples/core/docker/building-net-docker-images/docker-compose.debug.yml b/samples/core/docker/building-net-docker-images/docker-compose.debug.yml new file mode 100644 index 0000000000000..a69a97f9cfcbf --- /dev/null +++ b/samples/core/docker/building-net-docker-images/docker-compose.debug.yml @@ -0,0 +1,12 @@ +version: '2' + +services: + api: + image: api:debug + build: + context: . + dockerfile: Dockerfile.debug + ports: + - "5000:5000" + environment: + - REMOTE_DEBUGGING diff --git a/samples/core/docker/building-net-docker-images/docker-compose.yml b/samples/core/docker/building-net-docker-images/docker-compose.yml new file mode 100644 index 0000000000000..4ddc2b1160f77 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/docker-compose.yml @@ -0,0 +1,10 @@ +version: '2' + +services: + api: + image: api + build: + context: . + dockerfile: Dockerfile + ports: + - "5000:5000" diff --git a/samples/core/docker/building-net-docker-images/dockerTask.ps1 b/samples/core/docker/building-net-docker-images/dockerTask.ps1 new file mode 100644 index 0000000000000..0bc2fe4ef23b1 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/dockerTask.ps1 @@ -0,0 +1,160 @@ +<# +.SYNOPSIS +Builds and runs a Docker image. +.PARAMETER Compose +Runs docker-compose. +.PARAMETER Build +Builds a Docker image. +.PARAMETER Clean +Removes the image api and kills all containers based on that image. +.PARAMETER ComposeForDebug +Builds the image and runs docker-compose. +.PARAMETER StartDebugging +Finds the running container and starts the debugger inside of it. +.PARAMETER Environment +The enviorment to build for (Debug or Release), defaults to Debug +.EXAMPLE +C:\PS> .\dockerTask.ps1 -Build +Build a Docker image named api +#> + +Param( + [Parameter(Mandatory=$True,ParameterSetName="Compose")] + [switch]$Compose, + [Parameter(Mandatory=$True,ParameterSetName="ComposeForDebug")] + [switch]$ComposeForDebug, + [Parameter(Mandatory=$True,ParameterSetName="StartDebugging")] + [switch]$StartDebugging, + [Parameter(Mandatory=$True,ParameterSetName="Build")] + [switch]$Build, + [Parameter(Mandatory=$True,ParameterSetName="Clean")] + [switch]$Clean, + [parameter(ParameterSetName="Compose")] + [Parameter(ParameterSetName="ComposeForDebug")] + [parameter(ParameterSetName="Build")] + [parameter(ParameterSetName="Clean")] + [ValidateNotNullOrEmpty()] + [String]$Environment = "Debug" +) + +$imageName="api" +$projectName="api" +$serviceName="api" +$containerName="${projectName}_${serviceName}_1" +$publicPort=5000 +$url="http://localhost:$publicPort" +$runtimeID = "debian.8-x64" +$framework = "netcoreapp1.0" + +# Kills all running containers of an image and then removes them. +function CleanAll () { + $composeFileName = "docker-compose.yml" + if ($Environment -ne "Release") { + $composeFileName = "docker-compose.$Environment.yml" + } + + if (Test-Path $composeFileName) { + docker-compose -f "$composeFileName" -p $projectName down --rmi all + + $danglingImages = $(docker images -q --filter 'dangling=true') + if (-not [String]::IsNullOrWhiteSpace($danglingImages)) { + docker rmi -f $danglingImages + } + } + else { + Write-Error -Message "$Environment is not a valid parameter. File '$composeFileName' does not exist." -Category InvalidArgument + } +} + +# Builds the Docker image. +function BuildImage () { + $composeFileName = "docker-compose.yml" + if ($Environment -ne "Release") { + $composeFileName = "docker-compose.$Environment.yml" + } + + if (Test-Path $composeFileName) { + Write-Host "Building the project ($ENVIRONMENT)." + $pubFolder = "bin\$Environment\$framework\publish" + dotnet publish -f $framework -r $runtimeID -c $Environment -o $pubFolder + + Write-Host "Building the image $imageName ($Environment)." + docker-compose -f "$pubFolder\$composeFileName" -p $projectName build + } + else { + Write-Error -Message "$Environment is not a valid parameter. File '$composeFileName' does not exist." -Category InvalidArgument + } +} + +# Runs docker-compose. +function Compose () { + $composeFileName = "docker-compose.yml" + if ($Environment -ne "Release") { + $composeFileName = "docker-compose.$Environment.yml" + } + + if (Test-Path $composeFileName) { + Write-Host "Running compose file $composeFileName" + docker-compose -f $composeFileName -p $projectName kill + docker-compose -f $composeFileName -p $projectName up -d + } + else { + Write-Error -Message "$Environment is not a valid parameter. File '$dockerFileName' does not exist." -Category InvalidArgument + } +} + +function StartDebugging () { + Write-Host "Running on $url" + + $containerId = (docker ps -f "name=$containerName" -q -n=1) + if ([System.String]::IsNullOrWhiteSpace($containerId)) { + Write-Error "Could not find a container named $containerName" + } + + docker exec -i $containerId /clrdbg/clrdbg --interpreter=mi +} + +# Opens the remote site +function OpenSite () { + Write-Host "Opening site" -NoNewline + $status = 0 + + #Check if the site is available + while($status -ne 200) { + try { + $response = Invoke-WebRequest -Uri $url -Headers @{"Cache-Control"="no-cache";"Pragma"="no-cache"} -UseBasicParsing + $status = [int]$response.StatusCode + } + catch [System.Net.WebException] { } + if($status -ne 200) { + Write-Host "." -NoNewline + Start-Sleep 1 + } + } + + Write-Host + # Open the site. + Start-Process $url +} + +$Environment = $Environment.ToLowerInvariant() + +# Call the correct function for the parameter that was used +if($Compose) { + Compose + OpenSite +} +elseif($ComposeForDebug) { + $env:REMOTE_DEBUGGING = 1 + BuildImage + Compose +} +elseif($StartDebugging) { + StartDebugging +} +elseif($Build) { + BuildImage +} +elseif ($Clean) { + CleanAll +} \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/dockerTask.sh b/samples/core/docker/building-net-docker-images/dockerTask.sh new file mode 100755 index 0000000000000..b270871d6bd36 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/dockerTask.sh @@ -0,0 +1,153 @@ +imageName="api" +projectName="api" +serviceName="api" +containerName="${projectName}_${serviceName}_1" +publicPort=5000 +url="http://localhost:$publicPort" +runtimeID="debian.8-x64" +framework="netcoreapp1.0" + +# Kills all running containers of an image and then removes them. +cleanAll () { + if [[ -z $ENVIRONMENT ]]; then + ENVIRONMENT="debug" + fi + + composeFileName="docker-compose.yml" + if [[ $ENVIRONMENT != "release" ]]; then + composeFileName="docker-compose.$ENVIRONMENT.yml" + fi + + if [[ ! -f $composeFileName ]]; then + echo "$ENVIRONMENT is not a valid parameter. File '$composeFileName' does not exist." + else + docker-compose -f $composeFileName -p $projectName down --rmi all + + # Remove any dangling images (from previous builds) + danglingImages=$(docker images -q --filter 'dangling=true') + if [[ ! -z $danglingImages ]]; then + docker rmi -f $danglingImages + fi + fi +} + +# Builds the Docker image. +buildImage () { + if [[ -z $ENVIRONMENT ]]; then + ENVIRONMENT="debug" + fi + + composeFileName="docker-compose.yml" + if [[ $ENVIRONMENT != "release" ]]; then + composeFileName="docker-compose.$ENVIRONMENT.yml" + fi + + if [[ ! -f $composeFileName ]]; then + echo "$ENVIRONMENT is not a valid parameter. File '$composeFileName' does not exist." + else + echo "Building the project ($ENVIRONMENT)." + pubFolder="bin/$ENVIRONMENT/$framework/publish" + dotnet publish -f $framework -r $runtimeID -c $ENVIRONMENT -o $pubFolder + + echo "Building the image $imageName ($ENVIRONMENT)." + docker-compose -f "$pubFolder/$composeFileName" -p $projectName build + fi +} + +# Runs docker-compose. +compose () { + if [[ -z $ENVIRONMENT ]]; then + ENVIRONMENT="debug" + fi + + composeFileName="docker-compose.yml" + if [[ $ENVIRONMENT != "release" ]]; then + composeFileName="docker-compose.$ENVIRONMENT.yml" + fi + + if [[ ! -f $composeFileName ]]; then + echo "$ENVIRONMENT is not a valid parameter. File '$composeFileName' does not exist." + else + echo "Running compose file $composeFileName" + docker-compose -f $composeFileName -p $projectName kill + docker-compose -f $composeFileName -p $projectName up -d + fi +} + +startDebugging () { + echo "Running on $url" + + containerId=$(docker ps -f "name=$containerName" -q -n=1) + if [[ -z $containerId ]]; then + echo "Could not find a container named $containerName" + else + docker exec -i $containerId /clrdbg/clrdbg --interpreter=mi + fi + +} + +openSite () { + printf 'Opening site' + until $(curl --output /dev/null --silent --head --fail $url); do + printf '.' + sleep 1 + done + + # Open the site. + open $url +} + +# Shows the usage for the script. +showUsage () { + echo "Usage: dockerTask.sh [COMMAND] (ENVIRONMENT)" + echo " Runs build or compose using specific environment (if not provided, debug environment is used)" + echo "" + echo "Commands:" + echo " build: Builds a Docker image ('$imageName')." + echo " compose: Runs docker-compose." + echo " clean: Removes the image '$imageName' and kills all containers based on that image." + echo " composeForDebug: Builds the image and runs docker-compose." + echo " startDebugging: Finds the running container and starts the debugger inside of it." + echo "" + echo "Environments:" + echo " debug: Uses debug environment." + echo " release: Uses release environment." + echo "" + echo "Example:" + echo " ./dockerTask.sh build debug" + echo "" + echo " This will:" + echo " Build a Docker image named $imageName using debug environment." +} + +if [ $# -eq 0 ]; then + showUsage +else + case "$1" in + "compose") + ENVIRONMENT=$(echo $2 | tr "[:upper:]" "[:lower:]") + compose + openSite + ;; + "composeForDebug") + ENVIRONMENT=$(echo $2 | tr "[:upper:]" "[:lower:]") + export REMOTE_DEBUGGING=1 + buildImage + compose + ;; + "startDebugging") + startDebugging + ;; + "build") + ENVIRONMENT=$(echo $2 | tr "[:upper:]" "[:lower:]") + buildImage + ;; + "clean") + ENVIRONMENT=$(echo $2 | tr "[:upper:]" "[:lower:]") + cleanAll + ;; + *) + showUsage + ;; + esac +fi \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/project.json b/samples/core/docker/building-net-docker-images/project.json new file mode 100644 index 0000000000000..563f1fa6b2057 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/project.json @@ -0,0 +1,61 @@ +{ + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.1", + "type": "platform" + }, + "Microsoft.AspNetCore.Mvc": "1.0.1", + "Microsoft.AspNetCore.Routing": "1.0.1", + "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0" + }, + "tools": { + "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final" + }, + "frameworks": { + "netcoreapp1.0": { + "imports": [ + "dotnet5.6", + "portable-net45+win8" + ] + } + }, + "buildOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true, + "debugType": "portable" + }, + "runtimeOptions": { + "configProperties": { + "System.GC.Server": true + } + }, + "publishOptions": { + "include": [ + "wwwroot", + "**/*.cshtml", + "appsettings.json", + "web.config", + "Dockerfile.debug", + "Dockerfile", + "docker-compose.debug.yml", + "docker-compose.yml" + ] + }, + "scripts": { + "postpublish": [ + "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" + ] + }, + "tooling": { + "defaultNamespace": "api" + } +} \ No newline at end of file diff --git a/samples/core/docker/building-net-docker-images/web.config b/samples/core/docker/building-net-docker-images/web.config new file mode 100644 index 0000000000000..a8d6672758d64 --- /dev/null +++ b/samples/core/docker/building-net-docker-images/web.config @@ -0,0 +1,14 @@ + + + + + + + + + + + +