I was scared of Docker and React, but no more.

I thought, why can I not run shell scripts to pull my code from git, update dependencies to requirements.txt or the package.json, and simply use pm2 as the webserver host and reload all the apps? So much easier to deploy, since installing pm2 and some shell scripts with env variables for deployment just takes about 5 minutes, right? No need to securely transfer or keep these images with weird code! Thing is, I was ignoring the pertinent use cases...

You have to understand the best ways to use it for your scenario and how it is typically used.

Use case 1. Prototype demo using funky services like file conversion
- Running "docker run fileconversionapi" is as fast as grabbing an API key, but no worries about usage billing! And it's super easy to network for local or eventually production, either with host network, or docker swarm. Value - Self-reliance.

Use case 2. Actually self hosting apps.. might include a long running database docker image etc, using a local mapped volume to avoid data loss. Super quick, easy defaults. Value - Privacy

Use case 3. Live production app - building from working code
This is where people go wrong. They have a cool python server script with loads of dependencies and even some data / model files and want to put it on production. Rather than run "pip install -r requirements.txt" on each new server or their 1st cloud server, they turn to docker.
Common mistakes - they try and put environment variables in the wrong place (in the code itself, in ENV) or they try and put the code into the docker image with the requirements/keys... e.g. git clone <repo> the pip install -r requirements.txt and distribute the docker file rather than the built full docker image). Doesn't work cause the docker runs can fail with different code changes to the repo etc. Essentially little point to automating build scripts like this compared to the benefit of sharing the latest image. - Value: you can delay productionising code until later and it's still OK. But if you are a newb (like I was) at docker, you'll probably do it wrong, even if you avoid security pitfalls due to wider coding experience. You'll be needlessly rebuilding the docker image... Protip, building the docker image should happen once every 6 month at most for clean builds. Multiple layers should only happen when optimization becomes vitally important.

Use case 4. Live production app - rolling updates / regular code / sharing image for developer nr 2. and 3. to instantly onboard
You can switch easily to AMIs with startup commands than exec docker code. You can rely on older AMIs or use kubernetes. Networking is simple generally. A docker contain does not know about the VPC, so it can't lay expectations that cause network hell in particular. - Value: high level control of the complexity in a range of deployment options, from single instance to multiple instance. Massive Value - you can move docker images between cloud providers as .tar files and instantly set up your infrastructure with valid letsencrypt SSL certs and everything from the last host.

Use case 5. You want to clearly establish a separate microservice, maybe because your new code requires python 3.10 not 3.7 or something. You're not even sure if you'll deploy it, you are just testing, but if it works, you need it in production tomorrow. Well anybody reading "PYTHON310" in the short docker image can tell why you did that a lot more obviously than a random VM once named "python 3.10 code" that now does random machine learning things. Value - throwawayability