Set Up Staging and Production with Dokploy
Read full transcript 13 segments
-
Once your application has real users, you need somewhere to test changes before they reach production. In this video, I'm going to show you how you can set up a separate staging and production environment on your own self-hosted servers, and how you can manage both through a single dashboard using Dockploy. Then we're going to go over testing a change in staging and releasing it to production. So, here's my simple application that's already deployed on my VPS using Dockploy. It's got a domain name, a valid HTTPS certificate managed by Let's Encrypt. This is something that's taken care for you automatically when you're using Dockploy, and my application is running on a KVM 2 instance on Hostinger, and this is a solid VPS with two CPU cores and 8 GB of RAM. My VPS takes care of all of the infrastructure, and this is where I run the application. However, my control plane is on Dockploy, and Dockploy is a free and open-source platform as a service that allows you to get a very cloud-like feeling while still self-hosting your applications.
-
This is what the Dockploy dashboard looks like, and it's deployed on my VPS. I can use it to manage my projects, and this is where my to-do application is configured, and I'm running it using Docker Compose. I connected to my Git repo, set up the environment variables, and then it runs everything for me. You can preview the compose file, and we have a couple of services, our web UI, which is a React client, our web API, which is our .NET backend, and I also have a Postgres database and a Grafana stack for observability. If we take a high-level view of the entire system, this is what it looks like. We start with a Hostinger VPS, which is where I'm running my Dockploy platform as a service. Dockploy takes care of a couple of things. It installs Docker on our VPS, and it allows us to manage our application using Docker Compose in this case, but you can also run standalone applications. And inside of my Docker Compose boundary, I've got a couple of containers, the React application, the .NET backend, I've also got a Postgres database, and Grafana for observability.
-
Now, none of these are actually reachable from outside the VPS. Instead, there is a traffic proxy that runs in front, and this is what our users reach from the browser when they enter the domain name to try to access the application. So, traffic proxies the request to the React application, which uses a packaged up Nginx proxy to send the request to the .NET backend for client-server communication. Now, this is implemented just to simplify the deployment stack, and so that I can have everything packaged up inside of a single Docker Compose. But, a more common setup is to just host your client applications in some static hosting provider, for example, Cloudflare Pages. And the traffic proxy also plays another role, and that is it takes care of setting up HTTPS for our system, and it manages the Let's Encrypt certificate. Now, all of this is just one environment, and we want to move to a more robust solution with a staging and a production environment. So, what that's going to look like is we're going to essentially duplicate our stack.
-
However, we don't have to duplicate everything. I'll remove the client temporarily, and what we're going to do is get another VPS on Hostinger, and what's interesting here is we're going to leverage Dock Deploy's remote server feature. So, this allows us to still run the control plane on our first VPS, as well as the traffic proxy. And the only thing that's going to run on our second VPS is going to be the application stack with the Docker Compose. So, I'm going to take my existing VPS and use that as a staging environment. I'm already running the control plane on this environment, so using it for staging is going to be acceptable, as I want to have my second VPS completely free of any other applications, and its only responsibility is going to be running the production environment. Now, the communication here is still going to go through the traffic proxy, and we're going to route the requests to the second VPS by setting up the proper domain names. This also allows us to set up some firewall rules where we can lock up this request to only allow incoming requests for production environment from the IP address of our traffic proxy. We can manage this through some firewall rules and completely isolate our production environment from any public access. So this is the high-level architecture that we're going to build in this video and the next thing we need is another VPS. And this is where Hostinger comes in, who is also the sponsor of today's video. They have a Black Friday sale currently running with up to 70% off on VPS hosting. You're
-
going to find some incredible value for money with these VPSs and they run on insanely powerful AMD epic processors with fast SSD storage. Now when it comes to choosing your VPS plan, you have a couple of options to choose from starting from the KVM one plan and ranging to KVM eight. For our production environment, I'm going to choose a KVM two instance, which comes with two CPU cores, 8 GB of RAM and 100 GB of SSD storage. So I'll click choose plan and this is going to take me to the checkout screen where I can choose the time period for renting my VPS and you can choose between 24 months and 12 months, which offer a better price than the one month option. Now on top of the Black Friday deal, you can also enter the coupon code Milan at checkout to get an additional 10% off of your order. Once you've chosen your term and entered your time period, you can go ahead and choose between one of their many data I'm going to be sticking with Germany and you can also choose if you want to pre-install an operating system, an optional control plane or any application that you might need. Once you're happy with your choices, you can click continue and I'm going to complete this part off-screen and then jump into the VPS setup. So this is what my VPS setup looks like and they have this very cool UI where you can check out the latency from your location one of their many data centers.
-
Now the closest one to me is going to be the Germany data center, so that's what I'm going to choose and this is also where my other VPS is hosted. I'm going to click next. For my operating system, I'm going to choose Ubuntu and I'm going to use version 24, which has been used in production for longer, so that's what I'm going to select here. Then, the next thing I can do is generate a root password for my VPS, which you should store somewhere securely so that you don't lose it and you can optionally add an SSH key here. Now, I'm going to be doing this later once I've set this up with Dockploy. I'm going to click next and I don't need the additional features, so I'm going to finish my setup. And now we have to wait a couple of minutes for our VPS to initialize, but thanks to the magic of video editing, this is going to be instant. And now that our VPS is ready, we can either SSH into the server, which I recommend that you do as you should update the installed packages and also set up automatic updates. I'll leave some resources in the description of this video if you want to learn more about this. I'm going to do this off-screen. Let's head into our VPS dashboard. You can see our server is up and running and now we can proceed to set this up as a remote server with Dockploy. What we need to do here is scroll down until we find the SSH key section and I'm going to add an SSH key.
-
And in fact, I'm going to use the generate key option. I'm going to give this key a name of Daymark Production and I'm going to update the public key label to also be Daymark Production. I'm going to copy the public key and click create. So, this is our SSH key that Dockploy is going to use to manage our remote server. Now, we need to add this SSH key to my VPS and I can easily do this from the Hostinger dashboard by going to settings and then SSH keys and I can add my SSH key by pasting the contents. I'm going to save this and our public key is now added to the VPS. Now, if we go back to the overview tab, we're going to grab the public IP address of our VPS and now we can head back to Dockploy where we can go into the remote servers page. From here, I'm going to create my server, which I'm going to call Daymark Production. Going to be a deploy server, and we're going to choose the SSH key that we just created. Our IP address is going to be the public IP address of our VPS, which we just copied. And port 22 is used for SSH access. I'm going to keep the root user, although in general, it's a best practice to use a non-root user.
-
However, DockToy does require pseudo access on whichever user you decide to use. I'm going to leave enable Docker cleanup on as I want to use this feature, and I'm going to create my remote server. Now, this only takes care of setting up the record within DockToy. We still need to set up our server, so this is going to be the next step. So, let's click set up server. And the first step is adding the SSH keys, which we've already done. Now, we can confirm that this works by going and opening up the terminal, and if the connection is established, then the SSH keys were properly added to our VPS. Now, the next step is setting up the server so that it can run with DockToy. And this part is largely automated. You can click set up server, and then confirm, and DockToy is going to establish a connection with our VPS, and it's going to install the required packages that it needs to be able to run our applications there, and allow us to manage everything through the DockToy user interface. I'm going to give this a couple of moments to complete. You can see we get some info logs and success logs as it's making progress, and eventually you can see that it succeeds, and we can close this deployment log tab. Now, if I go back to setting up the server and go into validate, and this is going to run some checks on our VPS just to confirm that the DockToy best practices are met. Now, the one thing that's missing is being in the Docker group, but this shouldn't be an issue for our setup. Now, the security tab is something I recommend
-
you check out, and it lists a couple of best practices for setting up UFW Uncomplicated Firewall, SSH, and Fail2Ban. Now, you don't have to use these if you still have other security best practices in place, like a provider level firewall implemented. And if your servers are hidden from the public inside of a virtual private net. If these two are not true, then I do recommend setting up uncomplicated firewall and fail2ban. So, I'm going to close this down as our remote server is ready. And then let's head over into projects and into the Daymark project. So, what we have here is the option to choose our environment. And by default, there is a production environment. Now, I want to create another one called staging. And what I'm going to do is select my existing application and then click bulk actions, move, and I want to move this to the staging environment. So, now my production environment is empty. And if I move to the staging environment, my application is still there. Now, if we take a look at how our application is set up, it runs the respective Docker Compose file from our GitHub repo. And it also configures a couple of environment variables so that it can manage the database password and the JSON web token secret. Now, for all of these, I've got placeholder values in place because this is just a demo application, of course. Now, we need to set up our production application instance. And you can do so by going to create service, choosing compose. I'm going to call it app and add production in braces just so it's more obvious which environment this is. Now, this is
-
a key part here where you choose which server you want to deploy this to. And I'm going to deploy to our production server. The app name stays the same. The compose type is Docker Compose and let's click create. You should also see our remote server name as a label here. Now, let's go into our compose service to actually set this up. And I'm going to choose my GitHub account, select my repository. I'll use the main branch for this deployment. And then our compose path is docker-compose.dockploy.yaml. I'm going to save these settings and I want to turn off automatic deployments on every push to our repo because I want to manually deploy these changes once I'm sure that everything is okay on the staging environment. We also have to set up our environment variables and I'm going to drop them in. This is now going to become our production host name and what's left to do is to deploy our application to the remote server. So, let's go ahead and watch this deployment and hopefully everything should work out fine without any issues. Currently, it's downloading the missing images. These include our Postgres database, the Grafana stack and it also has to build the image for our Docker application as well as the React app with Engine X.
-
Once all of that is prepared, then it's going to start everything up using Docker Compose and we should see our production environment be up and running and after about a minute, we can see our production environment is now up and running. So, I can go ahead and close this and with my host names properly configured, we should be able to access both applications from their respective host names. I'm managing my domain through Hostinger as well. So, if I go to edit the DNS records, we're going to just shuffle around the ones that we currently have. So, what I want to do is retarget the root A record to the staging subdomain. So, let's hit edit here and I'm going to update the name to be staging and we're going to let this propagate. I'm going to add another root record. This is going to be an A record. We'll use the at sign and we're going to use our new VPS's IP address and a time to live of 60 seconds. So, let's go ahead and add this new DNS record and we're going to let this propagate for a couple of moments before trying to access our staging and production applications. So, if I go to staging.daymarktudoapp.cloud, you can see my application is served and this is from our staging environment and the same server that our Dockploy control plane is running on. I'm going to authenticate with my user account and you can see I'm able to access the dashboard. Also, if I go to my production app, daymarktudoapp.cloud, I can also log in and see my dashboard.
-
So, now let's just quickly walk through the process of getting something deployed to our staging environment, making sure it works, and then releasing that to production. And the simple change I'm going to make is update this label here to say version two. So, from inside of VS Code, I'm going to find that respective component. I will type out V2, save this, which is also going to format my file. And now I can open up my terminal, and I'm going to type in get status. And we can see we got two files changed. I only want to stage my component, so I'm going to say get add and paste in the file to the component. Then we're going to say get commit, and we're going to add a message, let's say V2. This is going to be more than enough. And once I've committed this, I'm going to say get push, and this is going to push my change to my remote branch. And this should trigger my automatic deployment on the staging environment, which we can confirm if we open up our staging app. You can see our deployment is running with our sample commit message that just says version two. And now if I go to the staging app and hit refresh, you can see version two shows up, which means the latest version is now deployed. On the production app, this is not the case because the deployments there are not automatic. So, now we can go ahead and test out the change on our staging server, and once we're happy, head over to production.
-
And inside of our remote server, we're going to click deploy and get the change manually deployed to production. Now, your next step would be automating this process so that you don't have to manually deploy to production. Instead, it can be a process where you test the changes in staging, and once the verification test that you establish pass, then you automatically deploy to production. And now if I refresh the production UI, you can see our version two shows up here, which means the latest changes are also deployed in production. And this should give you an easy way to set up a staging and production environment using Dokku. If you want to learn more about setting up everything from scratch, I recommend taking a look at this video here where I go through the process of setting up my VPS, installing everything that's required, configuring Dokku Deploy, and getting my first application deployed. If you enjoyed this video, consider smashing the like button as I would really appreciate it. Thanks a lot for watching, and until next time, stay awesome.
Summary
This tutorial demonstrates how to set up and manage separate staging and production environments on self-hosted servers using Dockploy, Docker Compose, and Hostinger VPS. Key technologies and services discussed include Dockploy, Docker, Hostinger VPS, React, .NET, PostgreSQL, Grafana, Traefik proxy, and Let's Encrypt for HTTPS. The practical takeaway is that developers can efficiently scale their self-hosted infrastructure by utilizing Dockploy's remote server feature to isolate production workloads on a dedicated VPS while managing everything from a single control plane.