Developing and testing applications inside of Docker containers and finally running them in the same manner in production is a great approach to reduce the used to work on my machine but is magically failing in production
risk.
This is also reflected in factor no. 10 of the well-known 12 factor manifesto which I try to follow wherever it makes sense for the given use case: Keep development, staging, and production as similar as possible.
On our production server, we have a reverse-proxy in place which is taking incoming requests on port 80 and forwards them to the correct container depending on the Host
header used when accessing the host via virtual domains - e.g. requests to app1.domain.name
go to the app1
container while requests to app2.domain.name
go to the app2
container etc. We use traefik for that but it could also be jwilder/nginx-proxy or any other reverse-proxy or load balancer. No other container ports are publicly exposed for the application containers.
My question now is, what would be the most efficient way to simulate this setup during development? I could think of the following ones:
- Ignore the reverse-proxy during development and expose a public port for each service under which one can reach it during development. In production, however, do not publicly expose any ports. While this is easy to do, it does not give exact parity between the development and production setup.
- Run a similar reverse-proxy locally during development. While this gives much better parity between development and production environment, this requirement needs to be documented somewhere and places some burden on new developers to get the prerequisites right before actually diving into the application itself - something that the Docker approach actually tries to avoid.
- Automate setting up a development environment which mimics the production one (including the reverse-proxy) by putting everything into a virtual machine (e.g. with Vagrant). While this would be convenient from a developer's point of view, it takes some further time to setup initially and consumes more resources.
Did I miss here some other approach which is superior to the ones described?