# 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

Click here for Swarm-Counter.zip

# project structure

+-- backend
|    +-- ...
+-- frontend
|    +-- ...
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
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




 
 
 
 



+-- 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

./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

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
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

./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
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

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
docker-compose -f compose-build.yml build
docker-compose -f compose-build.yml push
1
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

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

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

# 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

./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

./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

# 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

./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
docker-compose -f ./compose-build.yml build
docker-compose -f ./compose-build.yml push
1
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

# 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
    14
    docker stack deploy -c ./stack/stack-app.yml swarm-lab
    
    1
    • or use command
    docker service scale swarm-lab_frontend=5
    
    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 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 ago   
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12