I've got a Python webapp running in docker container and a DB container/service, and I'm wondering if the apache/mod_wsgi functionality should be contained within the container that runs the python app itself, or separate. I'm currently running them together, but I've seen graphics like the one in this article which depict (for example) nginix as a separate containerized service. But why is this useful?
There are a number of reasons:
- The instances can be scaled differently. For example, databases usually require a minimum of 3 physically-separated nodes for durability, where a web server usually resides in memory and can be restarted quickly, so you might keep it only on one node during low-traffic times and scale it up to more nodes during peak traffic.
- You can use a more standard configuration. If you just use a nginx container, you can pull it straight off docker hub and use the same image millions of other people have tested, with just your own application-specific customizations. No building and testing your own Dockerfiles, with all of the concomitant hassle and risks.
- You reduce the attack surface of any given vulnerability. If your database has an exploit, your attacker won't have access to anything private in your nginx container, and vice versa.
- Your orchestration can more easily help you health check and restart the individual components. For example, Kubernetes can be configured to periodically check for a 200 OK and restart nginx if it doesn't receive it.
- You have a more "physical" separation between components, which makes it somewhat easier to enforce interfaces between them, have them developed by different teams, be upgraded on different schedules, be checked into separated repositories, and so forth.
Of course, there is a trade off in that you have more moving parts and you now need some sort of orchestration to coordinate between them. That effort should not be underestimated. However, beyond a certain complexity, the benefits of modularity outweigh the extra complexity introduced.
Here are some advantages of running Nginx or Apache outside of your application:
- You want to host several applications running on the same port at different domains (reverse proxy).
- You want HTTP error responses to occur even if the application container fails. The Apache or Nginx container will return 502 if your application container has failed or is not running. This may be useful during redeployments (if you haven't sorted out how to redeploy without downtime). 502 Is much better response than no connection.
- Separation of concerns. IMO it's better architecture to separate pieces into parts that have a single responsibility.
- Smaller docker images & faster builds. If you don't have to package your HTTP server into each docker image you build, it should save time.
- Agnostic to HTTP server. If you don't package the HTTP server with your application, it's much easier to switch that layer.
- Ability to add layers between Apache and your application. If you decide you want to add more software (logging, rate-limiting, firewall, etc.) between the HTTP layer and your application, you may do so if your containers are separate.