How I use MRSK and multiple Rails app on the same server
Tags: kamal, deploy, ruby, rails
Published: 2023-06-25 05:28:04

Recently, we made the decision to use MRSK to deploy applications at the company I work for. We have a physical server at our disposal, and we found the approach developed by DHH and his team quite interesting.

One of the requirements for using this tool was the ability to deploy multiple applications on the same server. We have several applications here, and it was important for us to be able to access each of them through a subdomain. That's what I'll be discussing in this post.

If you'd like to learn more about MRSK in its entirety, from installation to configuration and deployment, I recommend other excellent articles to guide you:

- 
https://greg.molnar.io/blog/deploying-a-rails-app-with-mrsk/

- 
https://www.driftingruby.com/episodes/deploying-with-mrsk

- 
And others


#Creating two applications#

To begin, we will create two applications that will be used in the examples. They will be called `app1` and `app2`.

To facilitate the identification of each application, we will create a route and configure it as the root path. In each application, we will have a view that displays "APP1" and "APP2" respectively.

So far, we have two separate applications. When running each of them on our local machine, we get the following results:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okfngvcazixzwmte9ehx.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqw8xk7ppxnccz81oyo0.png)

#Initializing MRSK#

At this point, we will prepare our applications for deployment by initializing MRSK in each of them using the command `mrsk init`. This will generate three files: `.env`, `.mrsk/hooks`, and `config/deploy.yml`. We will focus on the `config/deploy.yml` file, as it allows us to deploy two applications on the same server.

To perform the deployment, we also need to configure the `Dockerfile` so that our image can be built. However, as mentioned at the beginning of the article, the complete step-by-step process for deploying using MRSK is not the focus here. Therefore, we will assume that you already know the necessary steps for configuring the `Dockerfile`.

#Configuring the deploy.yml file#
Let's configure the `deploy.yml` file for both applications.

>To achieve our goal, it is important to know the exact role of each of our services. In the `deploy.yml` file, the role is defined below `servers:`. If no role is defined, MRSK will default it to `web`.

Example:

```yml
# Deploy to these servers.
servers:
  web: # <- Role
    - 10.10.10.10
```
In the above case, the role of the service will be `web`.

In the case below, since we haven't defined a role, it will default to `web` too.

```yml
# Deploy to these servers.
servers:
  - 10.10.10.10
```

That is very important because when we define the rules for each application to communicate with `Traefik`, we need to specify the role of the service (which will be our container).

Let's see how the `Traefik` rules will be defined in this file.

```yml
# APP1
# Name of your application. Used to uniquely configure containers.
service: app1

# Name of the container image.
image: user/app1

# Deploy to these servers.
servers:
  - 10.10.10.10

# Credentials for your image host.
registry:
  username:
    - MRSK_REGISTRY_USERNAME

  password:
    - MRSK_REGISTRY_PASSWORD

labels:
  traefik.http.routers.app1-web.rule: Host(`app1.demo.com`)
```
What will make the applications accessible in distinct ways is the `labels:` tag, which identifies the `service:` tags and the previously mentioned Role. Note that in `labels:` tag we have defined this rule for the service with a container identified as `app1-web` , and in this rule, we specify that we will access this application through the subdomain `app1` at the address `app1.demo.com`.

Now, let's take a look at the `deploy.yml` file for our second application:

```yml
# APP2
# Name of your application. Used to uniquely configure containers.
service: app2

# Name of the container image.
image: user/app2

# Deploy to these servers.
servers:
  - 10.10.10.10

# Credentials for your image host.
registry:
  username:
    - MRSK_REGISTRY_USERNAME

  password:
    - MRSK_REGISTRY_PASSWORD

labels:
  traefik.http.routers.app2-web.rule: Host(`app2.demo.com`)
```
In the second case, we have the `Traefik` rule for the `app2` service and the `web` role.

#After the deployment#

First of all, after we deployed our applications, let's check the status of our Docker containers on the server by running the command `docker container ls`. Here is the result:

```
ubuntu@ip-172-31-14-245:~$ docker container ls
CONTAINER ID   IMAGE                                                     COMMAND                  CREATED              STATUS                        PORTS                                       NAMES
4a919eb90e92   user/app1:dc7bfa712ce9c564230c50ab48c2e61542599a43   "./bin/rails server"     About a minute ago   Up About a minute (healthy)   3000/tcp                                    app1-web-dc7bfa712ce9c564230c50ab48c2e61542599a43
9b17c1cb5db0   user/app2:1a517f061829788aeab563a732978c36d6f233d4   "./bin/rails server"     6 minutes ago        Up 6 minutes (healthy)        3000/tcp                                    app2-web-1a517f061829788aeab563a732978c36d6f233d4
157155628e36   traefik:v2.9                                              "/entrypoint.sh --pr…"   34 minutes ago       Up 34 minutes                 0.0.0.0:80->80/tcp, :::80->80/tcp           traefik
```
Please note that we have two containers for our applications `app1` and `app2`. Additionally, we have a container for `Traefik`, which is used as a reverse proxy.

Now let's see if it's possible to access both applications at the same time by simply switching the subdomain for each one. Here is the result:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4iqxhqs4sa6rkx2e7zd.png)

Great!

By following these steps, we have successfully deployed multiple applications using the same target host and separated them effectively.

In this example, if we access the `demo.com` address, none of the applications will be found, ensuring complete separation between them. This is how we use multiple applications with MRSK in the company I work for, where we have several applications, and all of them are segregated in a similar manner.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aphrl5ghaay5fo995jlk.png)

This approach allows for better organization, management, and isolation of the applications, ensuring that they can coexist on the same server without conflicts. It also provides a clear and structured way to access each application through distinct subdomains.


I hope I have contributed in some way :)