Docker Swarm - Installing a 5-tier Web App
Tags: beginners, docker, showdev, tutorial
Published: 2022-12-24 18:29:24

## 🐋 *Docker Swarm? Why Not K8s?*

Docker Swarm is *simple*. It comes with Docker and has exactly what we need for this project... 

We want to create a simple 5-service web application. 

In order to understand why we’re using Docker instead of K8s here, we really need to ask ourselves what we really want out of a container orchestrator.

In other words, what do we _need_?

![Similar to Maslow’s Hierarchy of Needs in an interesting way](https://www.familyresourcehomecare.com/wp-content/uploads/2020/11/Hierarchy-of-Needs.png)

Similar to Maslow’s Hierarchy of Needs in an interesting way

### Our _Needs_

- Orchestrator to relaunch a container if the container goes down
- Light load balancer between two nodes for our voting app
- Persistent storage
- Frontend/backend network

---

## _Goal, Success Criteria, & Prereqs_

![Argentina won the FIFA World Cup on 12/18](https://e3.365dm.com/22/12/640x380/skynews-argentina-world-cup_6000343.jpg?20221218153041)

Argentina won the FIFA World Cup on 12/18

### 💻Prerequisites

- Linux, MacOS, WSL
- Terminal Access
- Internet Access
- Docker Engine + CLI installed
- [Ability to create Swarm cluster](https://dev.to/joeyb908/creating-a-cluster-with-docker-swarm-1728)

### 🥅Goal

The goal for this project is to create a 5-service web app that’s distributed amongst 5 nodes.

### ✅Success Criteria

Success is determined when the following is achieved.

- Visitors can visit the IP address of the website successfully and can:
    - View webpage
    - Interact with web app, cast, and change vote
- Administrator can view results in real-time

---

## 🗺️Directions

![https://media.giphy.com/media/3o6wrtF81uczxbHtn2/giphy.gif](https://media.giphy.com/media/3o6wrtF81uczxbHtn2/giphy.gif)

- All images are on Docker Hub, so you should use editor to craft your commands locally,
then paste them into swarm shell (at least that's how I'd do it)
- a `backend` and `frontend` overlay network are needed.
Nothing different about them other than that backend will help protect database from the voting web app.
(similar to how a VLAN setup might be in traditional architecture)
- The database server should use a named volume for preserving data.
Use the new `-mount` format to do this: `-mount type=volume,source=db-data,target=/var/lib/postgresql/data`

### Services (names below should be service names)

- vote
    - bretfisher/examplevotingapp_vote
    - web frontend for users to vote dog/cat
    - ideally published on TCP 80. Container listens on 80
    - on frontend network
    - 2+ replicas of this container
- redis
    - redis:3.2
    - key-value storage for incoming votes
    - no public ports
    - on frontend network
    - 1 replica NOTE VIDEO SAYS TWO BUT ONLY ONE NEEDED
- worker
    - bretfisher/examplevotingapp_worker
    - backend processor of redis and storing results in postgres
    - no public ports
    - on frontend and backend networks
    - 1 replica
- db
    - postgres:9.4
    - one named volume needed, pointing to /var/lib/postgresql/data
    - on backend network
    - 1 replica
    - remember set env for password-less connections -e POSTGRES_HOST_AUTH_METHOD=trust
- result
    - bretfisher/examplevotingapp_result
    - web app that shows results
    - runs on high port since just for admins (lets imagine)
    - so run on a high port of your choosing (I choose 5001), container listens on 80
    - on backend network
    - 1 replica
    
    ---
    

##1️⃣ Create a 3 Node Swarm Cluster

Because this is not a tutorial on how to create a Swarm cluster, I will not be covering how to create one here. To do so, please follow the link located within the prerequisites or by clicking the link [here](https://dev.to/joeyb908/creating-a-cluster-with-docker-swarm-1728). You will have to complete steps 1 - 5. 


![Successful creation of a 3-node cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uls5k4epsyidd07zslob.png)

A successful 3-node cluster looks like this after typing `docker node ls` .

##2️⃣ Crafting the Docker Commands

There will be two parts to this step. The first will involve creating the frontend and backend overlay networks. These allow the nodes to connect and communicate with each other, and most importantly, load balance once traffic hits the node.

There will be a total of five Docker commands when it comes to our services. I will write each one, then explain what each part means.

Be warned, this step is _dense_!

![Balance is important](https://cdn.statically.io/img/www.memesportal.com/wp-content/uploads/2021/04/303krn.jpg?f=auto)

### ⚡Part 1 - The Networks

#### Create Two Overlay Networks

```docker
docker network create \
	--driver overlay \
frontend

&& docker network create \
	--driver overlay \
backend
```

######Commands Broken Down

`docker network create` - Create a new network

`--driver overlay` - Specifically create an overlay network

`frontend` or `backend` - The name of our network(s)

![All networks after creating the front and backend overlay networks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v89azvkkf30l6nswnezp.png)

### 🧑‍🔧Part 2 - The Services

### Create the Vote Webapp Frontend

```docker
docker service create \
	--name vote-app \
	-p 80:80 \
	--network frontend \
	--replicas 2 \
bretfisher/examplevotingapp_vote
```
######Commands Broken Down

`docker service create` - Create a new service for Swarm

`--name vote-app` - Name the service ********vote-app********

`-p 80:80` - Publish & expose port 80 for outgoing/incoming traffic

`--network frontend` - Attach the service to the frontend network

`--replicas 2` - Create 2 replicas within the Swarm

`bretfisher/examplevotingapp_vote` - The web app container image

### Create the Database

Create a password using a secret. This is the most secure way of passing a password to the database. The only thing you need to do is clear your terminal log with `history -c`  after creating your password!

`printf "enter-pass-here" | docker secret create db_pass -`

`printf "enter-pass-here"` - Create the password string that will be used

`docker secret create` - Create a secret in docker

`my_secret_data` - The name of the secret

`-`  - Copies `enter-pass-here` into `my_secret_data`

```docker
docker service create \
	--name db \
	--network backend \
	--secret my_secret_data \
	-e POSTGRES_PASSWORD_FILE=/run/secrets/my_secret_data \
	-e POSTGRES_HOST_AUTH_METHOD=trust \
	--mount type=volume,source=db-data,target=/var/lib/postgresql/data \
postgres:9.4
```
######Commands Broken Down

`--secret my_secret_data` - Use the secret `my_secret_data`

`-e POSTGRES_PASSWORD_FILE=/run/secrets/db_pass` - Tell postgres to use the secret, `my_secret_data`

`-e POSTGRES_HOST_AUTH_METHOD=trust` - Allows all users to connect

`--mount type=volume,source=db-data,target=/var/lib/postgresql/data` - Stores the data persistently in case the DB container gets restarted

### Create the redis Service

`docker service create --name redis --network frontend --replicas 1 redis:3.2`

### Create the Worker

`docker service create --name worker --network frontend --network backend --replicas 1 bretfisher/examplevotingapp_worker`

### Create Results

`docker service create --name result --network backend --replicas 1 -p 5001:80 bretfisher/examplevotingapp_result`


![5 services running successfully with Swarm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fdrvhrejlnu5ixxub78.png)

##3️⃣ Test It Out!

Head over to the IPv4 address from your instance and you should see something similar to this. 

After casting the vote, head to the IP address for your server and specifically head to port 5001. You’ll be brought to a webpage where you can see the percentage between cats and dogs to see which is truly man’s best friend!


![Admin-level view of the results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6nitm1ztkgc19ux64m8.png)

## 🏁Result

You’ve now got a fully operational, 5-service webapp running on three different nodes! This was a joy to complete as it was the most complicated of the projects I’ve done so far. 

The original lesson had me use a static plaintext password for postgress but I had recently learned how to use secrets and wanted to give it a shot! It took me a few extra tries to figure out how to get it to work, but I’m glad I took the extra time to figure it out.

This was my last Docker Swarm project for the near-future. I will be moving on to learn Kubernetes now and I’m very excited for that!