Docker containers are good deployment unit. At this point producing them and publishing them to a container registry is pretty straight forward. That's not something that requires devops people. Any reasonably senior backend developer ought to know how to do this or can learn how to do it in a few hours.

The rest is just deploying and running containers. There are lots of ways to do that. I loved using Google Cloud Run a few years ago. Stupidly easy to get started with and flexible enough for many things. With some service discovery on top, it's perfect for a lot of stuff. Add some managed middleware & databases to the mix and you essentially have a close to zero ops CI/CD capable environment. No devops needed for this either. When I did this for the first time, I was up and running with our dockerized app in about 15 minutes. Most of that was just waiting for builds to finish.

I'm CTO of a company currently and I've gotten sidetracked with enough lengthy and super expensive devops type stuff in past projects that I'm on purpose avoiding to go near certain things not because I can't do it but because I don't think these things are worth spending any time on for us right now. So, no terraform, no kubernetes, no microservices. I just don't have the time or patience for that stuff. We run a monolith. So, there's not a lot I actually need from my infrastructure. I need it to be fast, secure, and resilient and be able to run my monolith. But I don't need to have things like service discovery, complicated network setup (bog standard vpc is fine), and all the other stuff that devops people obsess about.

We use a load-balancer, I clicked one together in the Google UI. It's fine. Ten minute job. Doesn't need terraform scripting. We have two of them. And we have a couple buckets and our monolith behind that. I could grab the gcloud command that recreates this thing and put it somewhere. But I have more urgent things to do.

For deployment we use simple gcloud commands from github actions to update vms with new instance templates to tell them to run the latest container that our build produced. We started with cloud run but our monolith has a few worker threads that we don't want killed so we moved it to proper vms. Very easy to do in Google Cloud.

Our deploy command does a rolling restart. We have health checks, logging, monitoring, alerting, etc. Could be better but it works. Initial provisioning of the environment was manual and we scripted together all the commands that are part of our deploy process for automation. We added a managed redis, database, and elasticsearch to this. None of that was particularly hard or worth automating to me. Yes, it's bit of a snowflake. But not that complicated and I documented it. So, we can do it again in a few hours if we ever need to.

The dirty little secret of a lot of devops that it's a lot over over-engineered YAGNY stuff that is super labor intensive to setup and maintain and you end up using it a lot less often than people think.

This is why freelance devops engineers are so in demand: this stuff just requires a lot of manual work! Companies need these people full time and usually more than just one. The devops alone can add up to hundreds of thousands of dollars/euros per year.

It's a lot of manual work that probably should be automated. However, hiring a lot of people at great expense to automate things that are cheap and not that complicated is not always the best use of resources. I've seen companies that spend an order of magnitude more on devops salaries than on the actual hosting bills. If you think about it, that's kind of weird to be spending so much for so little gains. And most of these companies are not particularly big or experience enormous scaling issues.