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:
To begin, we will create two applications that will be used in the examples. They will be called
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:
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:
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
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.ymlfile, the role is defined below
servers:. If no role is defined, MRSK will default it to
# Deploy to these servers. servers: web: # <- Role - 10.10.10.10
In the above case, the role of the service will be
In the case below, since we haven't defined a role, it will default to
# 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
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
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
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:
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 :)