# Counter App
# Deploys Counter WebApp
# Create the context in our own machine
docker context create lab-swarm --docker "host=ssh://swarm-1"
1
docker context use lab-swarm
1
# Check the nodes
docker node ls
1
output
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
hfi81meua03hj7q2g8llgwe8m * swarm-1 Ready Active Leader 20.10.12
a84z576oiihy4d1qd5zojxu0a swarm-2 Ready Active 20.10.12
1
2
3
2
3
Click here for Swarm-Counter.zip
# project structure
+-- backend
| +-- ...
+-- frontend
| +-- ...
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
2
3
4
5
6
2
3
4
5
6
docker-compose-prod.yml
version: "3"
services:
traefik:
image: traefik:v2.3
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TRAEFIK_PROVIDERS_DOCKER=true
- TRAEFIK_ENTRYPOINTS_web=true
- TRAEFIK_ENTRYPOINTS_web_ADDRESS=:80
- TRAEFIK_ENTRYPOINTS_websecure=true
- TRAEFIK_ENTRYPOINTS_websecure_ADDRESS=:443
frontend:
build:
context: ./frontend
dockerfile: prod.Dockerfile
labels:
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
- "traefik.http.routers.front.entrypoints=web"
- "traefik.http.services.front.loadbalancer.server.port=80"
backend:
build:
context: ./backend
dockerfile: prod.Dockerfile
labels:
- "traefik.http.routers.api.rule=PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=web"
- "traefik.http.services.api.loadbalancer.server.port=8000"
mongo:
image: mongo:3.6.22-xenial
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
volumes:
- mongo-sad-lab-traefik-proxy:/data/db
volumes:
mongo-sad-lab-traefik-proxy: 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
+-- backend
| +-- ...
+-- frontend
| +-- ...
+-- stack
| +-- stack-app.yml
| +-- stack-proxy-registry.yml
+-- compose-build.yml
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
./stack/stack-proxy-registry.yml
version: "3"
services:
traefik:
image: traefik:v2.3
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
placement:
constraints:
- "node.role==manager"
environment:
- TRAEFIK_PROVIDERS_DOCKER=true
- TRAEFIK_PROVIDERS_DOCKER_SWARMMODE=true
- TRAEFIK_ENTRYPOINTS_web=true
- TRAEFIK_ENTRYPOINTS_web_ADDRESS=:80
- TRAEFIK_ENTRYPOINTS_websecure=true
- TRAEFIK_ENTRYPOINTS_websecure_ADDRESS=:443
registry:
image: registry:2.8.0
ports:
- "5000:5000"
volumes:
- registry-volume:/var/lib/registry
deploy:
placement:
constraints:
- "node.hostname==swarm-1"
volumes:
registry-volume: 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
32
33
34
35
36
37
38
39
40
41
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
32
33
34
35
36
37
38
39
40
41
For Traefix constraints read here (opens new window)
docker stack deploy -c ./stack/stack-proxy-registry.yml swarm-lab
1
docker stack ls
1
output
NAME SERVICES ORCHESTRATOR
swarm-lab 2 Swarm
1
2
2
docker stack ps swarm-lab
1
output
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
9j4gec2pm7mz swarm-lab_registry.1 registry:2.8 swarm-1 Running Running 4 minutes ago
aq84g2l8k0vb swarm-lab_traefik.1 traefik:v2.3 swarm-1 Running Running 4 minutes ago
1
2
3
2
3
./stack/stack-app.yml
version: "3"
services:
frontend:
image: localhost:5000/raknatee/frontend:1.0.0
deploy:
replicas: 3
labels:
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
- "traefik.http.routers.front.entrypoints=web"
- "traefik.http.services.front.loadbalancer.server.port=80"
backend:
image: localhost:5000/raknatee/backend:2.0.0
deploy:
replicas: 3
labels:
- "traefik.http.routers.api.rule=PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=web"
- "traefik.http.services.api.loadbalancer.server.port=8000"
mongo:
image: mongo:3.6.22-xenial
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
deploy:
placement:
constraints:
- "node.hostname==swarm-2"
volumes:
- mongo-lab-swarm:/data/db
volumes:
mongo-lab-swarm: 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
32
33
34
35
36
37
38
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
32
33
34
35
36
37
38
docker stack deploy -c ./stack/stack-app.yml swarm-lab
1
docker stack ps swarm-lab
1
output
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
br61dz9j40kl swarm-lab_backend.1 localhost:5000/raknatee/backend:v1 swarm-1 Running Preparing 20 seconds ago
s60zw79fwytu \_ swarm-lab_backend.1 localhost:5000/raknatee/backend:v1 swarm-1 Shutdown Rejected 21 seconds ago "No such image: localhost:5000…"
h9r12432c6b6 \_ swarm-lab_backend.1 localhost:5000/raknatee/backend:v1 swarm-1 Shutdown Rejected 46 seconds ago "No such image: localhost:5000…"
otfqcn395lpb swarm-lab_frontend.1 localhost:5000/raknatee/frontend:v1 swarm-2 Running Preparing 20 seconds ago
vsk23lbdycwt \_ swarm-lab_frontend.1 localhost:5000/raknatee/frontend:v1 swarm-2 Shutdown Rejected 21 seconds ago "No such image: localhost:5000…"
tkkrfp8vecbi \_ swarm-lab_frontend.1 localhost:5000/raknatee/frontend:v1 swarm-2 Shutdown Rejected 46 seconds ago "No such image: localhost:5000…"
f5c9rulewb0x \_ swarm-lab_frontend.1 localhost:5000/raknatee/frontend:v1 swarm-2 Shutdown Rejected about a minute ago "No such image: localhost:5000…"
s3170w3pegsu swarm-lab_mongo.1 mongo:3.6.22-xenial swarm-2 Running Running about a minute ago
9j4gec2pm7mz swarm-lab_registry.1 registry:2.8 swarm-1 Running Running 7 minutes ago
aq84g2l8k0vb swarm-lab_traefik.1 traefik:v2.3 swarm-1 Running Running 7 minutes ago
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
compose-build.yml
version: "3"
services:
frontend:
image: localhost:5000/raknatee/frontend:1.0.0
build:
context: ./frontend
dockerfile: prod.Dockerfile
backend:
image: localhost:5000/raknatee/backend:2.0.0
build:
context: ./backend
dockerfile: prod.Dockerfile 1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
docker-compose -f compose-build.yml build
docker-compose -f compose-build.yml push
1
2
2
# Get Information about Service and Stack
docker stack ps swarm-lab -f "desired-state=running"
1
output
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
m0xgkn321212 swarm-lab_backend.1 localhost:5000/raknatee/backend:1.0.0 swarm-2 Running Running 5 minutes ago
9sq0whxgju55 swarm-lab_backend.2 localhost:5000/raknatee/backend:1.0.0 swarm-2 Running Running 5 minutes ago
ir33prxah830 swarm-lab_backend.3 localhost:5000/raknatee/backend:1.0.0 swarm-2 Running Running 5 minutes ago
6d69kzj05tjw swarm-lab_frontend.1 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 53 seconds ago
kzqwjugh0wxf swarm-lab_frontend.2 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 44 seconds ago
e1efxbaw988o swarm-lab_frontend.3 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 49 seconds ago
t8afz5b9gnbg swarm-lab_mongo.1 mongo:3.6.22-xenial swarm-2 Running Running 25 minutes ago
s4hkjlsbhw7m swarm-lab_registry.1 registry:2.8.0 swarm-1 Running Running 26 minutes ago
qgc47qsxy64r swarm-lab_traefik.1 traefik:v2.3 swarm-1 Running Running 26 minutes ago
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
docker stack services swarm-lab
1
output
ID NAME MODE REPLICAS IMAGE PORTS
r49y6f1d9xs6 swarm-lab_backend replicated 3/3 localhost:5000/raknatee/backend:1.0.0
uydnut9cr45m swarm-lab_frontend replicated 3/3 localhost:5000/raknatee/frontend:1.0.0
7774gahqhky8 swarm-lab_mongo replicated 1/1 mongo:3.6.22-xenial
1e0fufzxkxo9 swarm-lab_registry replicated 1/1 registry:2.8.0 *:5000->5000/tcp
bi3ue7hnih50 swarm-lab_traefik replicated 1/1 traefik:v2.3 *:80->80/tcp, *:443->443/tcp
1
2
3
4
5
6
2
3
4
5
6
docker service ls
1
output
ID NAME MODE REPLICAS IMAGE PORTS
r49y6f1d9xs6 swarm-lab_backend replicated 3/3 localhost:5000/raknatee/backend:1.0.0
uydnut9cr45m swarm-lab_frontend replicated 3/3 localhost:5000/raknatee/frontend:1.0.0
7774gahqhky8 swarm-lab_mongo replicated 1/1 mongo:3.6.22-xenial
1e0fufzxkxo9 swarm-lab_registry replicated 1/1 registry:2.8.0 *:5000->5000/tcp
bi3ue7hnih50 swarm-lab_traefik replicated 1/1 traefik:v2.3 *:80->80/tcp, *:443->443/tcp
1
2
3
4
5
6
2
3
4
5
6
# What if we want to deploy new version of our application?
# Lets coding
+-- backend
| +-- src
| | +-- main.py
| | +-- ...
| +-- ...
+-- frontend
| +-- ...
+-- stack
| +-- stack-app.yml
| +-- stack-proxy-registry.yml
+-- compose-build.yml
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
./backend/src/main.py
from fastapi import FastAPI
from mongo_connector import Mongo
app = FastAPI()
base_url = "/api"
api_version = "2"
@app.get(base_url+"/")
def read_root():
data = Mongo.get_instance()['my-db']['my-collection'].find_one({"name":"counter"},{'_id':0})
return {**data,**{"api_version":api_version}}
@app.get(base_url+"/count")
def add_count():
data = Mongo.get_instance()['my-db']['my-collection'].update_one({"name":"counter"},{"$inc":{"value":1}})
return {"result":data.modified_count}
def init_obj():
data = [ d for d in Mongo.get_instance()['my-db']['my-collection'].find({"name":"counter"})]
if(not data):
new_data = {
"name":"counter",
"value": 0
}
Mongo.get_instance()['my-db']['my-collection'].insert_one(new_data)
init_obj()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
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
./stack/stack-app.yml
version: "3"
services:
frontend:
image: localhost:5000/raknatee/frontend:1.0.0
deploy:
replicas: 3
labels:
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
- "traefik.http.routers.front.entrypoints=web"
- "traefik.http.services.front.loadbalancer.server.port=80"
backend:
image: localhost:5000/raknatee/backend:2.0.0
deploy:
replicas: 3
labels:
- "traefik.http.routers.api.rule=PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=web"
- "traefik.http.services.api.loadbalancer.server.port=8000"
mongo:
image: mongo:3.6.22-xenial
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
deploy:
placement:
constraints:
- "node.hostname==swarm-2"
volumes:
- mongo-lab-swarm:/data/db
volumes:
mongo-lab-swarm: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
32
33
34
35
36
37
38
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
32
33
34
35
36
37
38
# Build Image and push them
+-- backend
| +-- src
| | +-- main.py
| | +-- ...
| +-- ...
+-- frontend
| +-- ...
+-- stack
| +-- stack-app.yml
| +-- stack-proxy-registry.yml
+-- compose-build.yml
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
./compose-build.yml
version: "3"
services:
frontend:
image: localhost:5000/raknatee/frontend:1.0.0
build:
context: ./frontend
dockerfile: prod.Dockerfile
backend:
image: localhost:5000/raknatee/backend:2.0.0
build:
context: ./backend
dockerfile: prod.Dockerfile1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
docker-compose -f ./compose-build.yml build
docker-compose -f ./compose-build.yml push
1
2
2
# Update Stack
docker stack deploy -c ./stack/stack-app.yml swarm-lab
1
docker stack ps swarm-lab -f "desired-state=running"
1
output
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
htmk9fquunzh swarm-lab_backend.1 localhost:5000/raknatee/backend:2.0.0 swarm-2 Running Running 37 seconds ago
9p3i2gxxzsag swarm-lab_backend.2 localhost:5000/raknatee/backend:2.0.0 swarm-1 Running Running 52 seconds ago
u8895b37z42j swarm-lab_backend.3 localhost:5000/raknatee/backend:2.0.0 swarm-2 Running Running 23 seconds ago
6d69kzj05tjw swarm-lab_frontend.1 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago
kzqwjugh0wxf swarm-lab_frontend.2 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago
e1efxbaw988o swarm-lab_frontend.3 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago
t8afz5b9gnbg swarm-lab_mongo.1 mongo:3.6.22-xenial swarm-2 Running Running 3 days ago
s4hkjlsbhw7m swarm-lab_registry.1 registry:2.8.0 swarm-1 Running Running 3 days ago
qgc47qsxy64r swarm-lab_traefik.1 traefik:v2.3 swarm-1 Running Running 3 days ago
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# What if we want to scale them ?
assume we want frontend service to have 5 containers
There are 2 ways.
- use docker-compose.yml and deploy new stack
./stack/stack-app.yml
version: "3" services: frontend: image: localhost:5000/raknatee/frontend:1.0.0 deploy: replicas: 5 labels: - "traefik.http.routers.front.rule=PathPrefix(`/`)" - "traefik.http.routers.front.entrypoints=web" - "traefik.http.services.front.loadbalancer.server.port=80" ...1
2
3
4
5
6
7
8
9
10
11
12
13
14docker stack deploy -c ./stack/stack-app.yml swarm-lab1- or use command
docker service scale swarm-lab_frontend=51docker stack ps swarm-lab -f "desired-state=running"1output
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS htmk9fquunzh swarm-lab_backend.1 localhost:5000/raknatee/backend:2.0.0 swarm-2 Running Running 8 minutes ago 9p3i2gxxzsag swarm-lab_backend.2 localhost:5000/raknatee/backend:2.0.0 swarm-1 Running Running 9 minutes ago u8895b37z42j swarm-lab_backend.3 localhost:5000/raknatee/backend:2.0.0 swarm-2 Running Running 8 minutes ago 6d69kzj05tjw swarm-lab_frontend.1 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago kzqwjugh0wxf swarm-lab_frontend.2 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago e1efxbaw988o swarm-lab_frontend.3 localhost:5000/raknatee/frontend:1.0.0 swarm-1 Running Running 3 days ago tcf5jlf4svo5 swarm-lab_frontend.4 localhost:5000/raknatee/frontend:1.0.0 swarm-2 Running Running 12 seconds ago licrrgt7f38o swarm-lab_frontend.5 localhost:5000/raknatee/frontend:1.0.0 swarm-2 Running Running 13 seconds ago t8afz5b9gnbg swarm-lab_mongo.1 mongo:3.6.22-xenial swarm-2 Running Running 3 days ago s4hkjlsbhw7m swarm-lab_registry.1 registry:2.8.0 swarm-1 Running Running 3 days ago qgc47qsxy64r swarm-lab_traefik.1 traefik:v2.3 swarm-1 Running Running 3 days ago1
2
3
4
5
6
7
8
9
10
11
12