Skip to content

Commit 75af246

Browse files
author
Mano Marks
authored
Merge pull request dockersamples#122 from sixeyed/master
Add .NET Core variants running in Windows containers
2 parents 5a6cb91 + fec8297 commit 75af246

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+5054
-7
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.pyc
22
project.lock.json
33
bin/
4-
obj/
4+
obj/
5+
.vs/

ExampleVotingApp.sln

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.28010.2036
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vote", "vote\dotnet\Vote\Vote.csproj", "{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker", "worker\dotnet\Worker\Worker.csproj", "{083764E8-4C34-43FB-A468-F80CE0ADE10A}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Result", "result\dotnet\Result\Result.csproj", "{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}"
11+
EndProject
12+
Global
13+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
14+
Debug|Any CPU = Debug|Any CPU
15+
Release|Any CPU = Release|Any CPU
16+
EndGlobalSection
17+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
18+
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19+
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Debug|Any CPU.Build.0 = Debug|Any CPU
20+
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Release|Any CPU.ActiveCfg = Release|Any CPU
21+
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Release|Any CPU.Build.0 = Release|Any CPU
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
GlobalSection(ExtensibilityGlobals) = postSolution
35+
SolutionGuid = {9DEFC158-1225-4393-8A38-22256211D43D}
36+
EndGlobalSection
37+
EndGlobal

README.md

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
Example Voting App
22
=========
33

4+
A simple distributed application running across multiple Docker containers.
5+
46
Getting started
57
---------------
68

7-
Download [Docker](https://www.docker.com/products/overview). If you are on Mac or Windows, [Docker Compose](https://docs.docker.com/compose) will be automatically installed. On Linux, make sure you have the latest version of [Compose](https://docs.docker.com/compose/install/). If you're using [Docker for Windows](https://docs.docker.com/docker-for-windows/) on Windows 10 pro or later, you must also [switch to Linux containers](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers).
9+
Download [Docker Desktop](https://www.docker.com/products/docker-desktop) for Mac or Windows. [Docker Compose](https://docs.docker.com/compose) will be automatically installed. On Linux, make sure you have the latest version of [Compose](https://docs.docker.com/compose/install/).
10+
11+
12+
## Linux Containers
13+
14+
The Linux stack uses Python, Node.js, .NET Core (or optionally Java), with Redis for messaging and Postgres for storage.
15+
16+
> If you're using [Docker Desktop on Windows](https://store.docker.com/editions/community/docker-ce-desktop-windows), you can run the Linux version by [switching to Linux containers](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers), or run the Windows containers version.
817
918
Run in this directory:
1019
```
@@ -21,6 +30,27 @@ Once you have your swarm, in this directory run:
2130
docker stack deploy --compose-file docker-stack.yml vote
2231
```
2332

33+
## Windows Containers
34+
35+
An alternative version of the app uses Windows containers based on Nano Server. This stack runs on .NET Core, using [NATS](https://nats.io) for messaging and [TiDB](https://github.com/pingcap/tidb) for storage.
36+
37+
You can build from source using:
38+
39+
```
40+
docker-compose -f docker-compose-windows.yml build
41+
```
42+
43+
Then run the app using:
44+
45+
```
46+
docker-compose -f docker-compose-windows.yml up -d
47+
```
48+
49+
> Or in a Windows swarm, run `docker stack deploy -c docker-stack-windows.yml vote`
50+
51+
The app will be running at [http://localhost:5000](http://localhost:5000), and the results will be at [http://localhost:5001](http://localhost:5001).
52+
53+
2454
Run the app in Kubernetes
2555
-------------------------
2656

@@ -47,11 +77,11 @@ Architecture
4777

4878
![Architecture diagram](architecture.png)
4979

50-
* A Python webapp which lets you vote between two options
51-
* A Redis queue which collects new votes
52-
* A .NET worker which consumes votes and stores them in…
53-
* A Postgres database backed by a Docker volume
54-
* A Node.js webapp which shows the results of the voting in real time
80+
* A front-end web app in [Python](/vote) or [ASP.NET Core](/vote/dotnet) which lets you vote between two options
81+
* A [Redis](https://hub.docker.com/_/redis/) or [NATS](https://hub.docker.com/_/nats/) queue which collects new votes
82+
* A [.NET Core](/worker/src/Worker), [Java](/worker/src/main) or [.NET Core 2.1](/worker/dotnet) worker which consumes votes and stores them in…
83+
* A [Postgres](https://hub.docker.com/_/postgres/) or [TiDB](https://hub.docker.com/r/dockersamples/tidb/tags/) database backed by a Docker volume
84+
* A [Node.js](/result) or [ASP.NET Core SignalR](/result/dotnet) webapp which shows the results of the voting in real time
5585

5686

5787
Note

docker-compose-windows.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: "3.2"
2+
3+
services:
4+
vote:
5+
image: dockersamples/examplevotingapp_vote:dotnet-nanoserver-sac2016
6+
build:
7+
context: ./vote/dotnet
8+
ports:
9+
- "5000:80"
10+
depends_on:
11+
- message-queue
12+
13+
result:
14+
image: dockersamples/examplevotingapp_result:dotnet-nanoserver-sac2016
15+
build:
16+
context: ./result/dotnet
17+
ports:
18+
- "5001:80"
19+
environment:
20+
- "ConnectionStrings:ResultData=Server=db;Port=4000;Database=votes;User=root;SslMode=None"
21+
depends_on:
22+
- db
23+
24+
worker:
25+
image: dockersamples/examplevotingapp_worker:dotnet-nanoserver-sac2016
26+
build:
27+
context: ./worker/dotnet
28+
environment:
29+
- "ConnectionStrings:VoteData=Server=db;Port=4000;Database=votes;User=root;SslMode=None"
30+
depends_on:
31+
- message-queue
32+
- db
33+
34+
message-queue:
35+
image: nats:nanoserver
36+
37+
db:
38+
image: dockersamples/tidb:nanoserver
39+
ports:
40+
- "3306:4000"
41+
42+
networks:
43+
default:
44+
external:
45+
name: nat

docker-stack-windows.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
version: "3.2"
2+
3+
services:
4+
vote:
5+
image: dockersamples/examplevotingapp_vote:dotnet-nanoserver-sac2016
6+
ports:
7+
- mode: host
8+
target: 80
9+
published: 5000
10+
deploy:
11+
endpoint_mode: dnsrr
12+
networks:
13+
- frontend
14+
- backend
15+
16+
result:
17+
image: dockersamples/examplevotingapp_result:dotnet-nanoserver-sac2016
18+
environment:
19+
- "ConnectionStrings:ResultData=Server=db;Port=4000;Database=votes;User=root;SslMode=None"
20+
ports:
21+
- mode: host
22+
target: 80
23+
published: 5001
24+
deploy:
25+
endpoint_mode: dnsrr
26+
networks:
27+
- frontend
28+
- backend
29+
30+
worker:
31+
image: dockersamples/examplevotingapp_worker:dotnet-nanoserver-sac2016
32+
environment:
33+
- "ConnectionStrings:VoteData=Server=db;Port=4000;Database=votes;User=root;SslMode=None"
34+
deploy:
35+
endpoint_mode: dnsrr
36+
mode: replicated
37+
replicas: 3
38+
networks:
39+
- backend
40+
41+
message-queue:
42+
image: nats:nanoserver
43+
deploy:
44+
endpoint_mode: dnsrr
45+
networks:
46+
- backend
47+
48+
db:
49+
image: dockersamples/tidb:nanoserver
50+
ports:
51+
- mode: host
52+
target: 4000
53+
published: 3306
54+
deploy:
55+
endpoint_mode: dnsrr
56+
networks:
57+
- backend
58+
59+
networks:
60+
frontend:
61+
backend:

result/dotnet/Dockerfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM microsoft/dotnet:2.1-sdk-nanoserver-sac2016 as builder
2+
3+
WORKDIR /Result
4+
COPY Result/Result.csproj .
5+
RUN dotnet restore
6+
7+
COPY /Result .
8+
RUN dotnet publish -c Release -o /out Result.csproj
9+
10+
# app image
11+
FROM microsoft/dotnet:2.1-aspnetcore-runtime-nanoserver-sac2016
12+
13+
WORKDIR /app
14+
ENTRYPOINT ["dotnet", "Result.dll"]
15+
16+
COPY --from=builder /out .
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Result.Models;
2+
3+
namespace Result.Data
4+
{
5+
public interface IResultData
6+
{
7+
ResultsModel GetResults();
8+
}
9+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Linq;
2+
using Dapper;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.Logging;
5+
using MySql.Data.MySqlClient;
6+
using Result.Models;
7+
8+
namespace Result.Data
9+
{
10+
public class MySqlResultData : IResultData
11+
{
12+
private readonly string _connectionString;
13+
private readonly ILogger _logger;
14+
15+
public MySqlResultData(IConfiguration config, ILogger<MySqlResultData> logger)
16+
{
17+
_connectionString = config.GetConnectionString("ResultData");
18+
_logger = logger;
19+
}
20+
21+
public ResultsModel GetResults()
22+
{
23+
var model = new ResultsModel();
24+
using (var connection = new MySqlConnection(_connectionString))
25+
{
26+
var results = connection.Query("SELECT vote, COUNT(id) AS count FROM votes GROUP BY vote ORDER BY vote");
27+
if (results.Any(x => x.vote == "a"))
28+
{
29+
model.OptionA = (int) results.First(x => x.vote == "a").count;
30+
}
31+
if (results.Any(x => x.vote == "b"))
32+
{
33+
model.OptionB = (int) results.First(x => x.vote == "b").count;
34+
}
35+
model.VoteCount = model.OptionA + model.OptionB;
36+
}
37+
return model;
38+
}
39+
}
40+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Microsoft.AspNetCore.SignalR;
2+
3+
namespace Result.Hubs
4+
{
5+
public class ResultsHub : Hub
6+
{
7+
//no public methods, only used for push from PublishRTesultsTimer
8+
}
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Result.Models
2+
{
3+
public class ResultsModel
4+
{
5+
public int OptionA { get; set; }
6+
7+
public int OptionB { get; set; }
8+
9+
public int VoteCount { get; set; }
10+
}
11+
}

0 commit comments

Comments
 (0)