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:
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:
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 belowservers:
. If no role is defined, MRSK will default it toweb
.
Example:
# 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.
# 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.
# 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:
# 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:
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.
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 :)
Top comments (1)
Thanks, it helped me a lot.