The "on-the-knee" setup i have been using for my (Django) side project is:
- base image that installs OS Updates + OS package requirements + production dependencies
- dev image inherits from base image, installs dev dependencies + source code volume mounted on '/app/src'
- test image inherits from base image, installs test dependencies + source code volume mounted on '/app/src' (image used both for local tests and CI)
- prod image inherits from base image, adds source code to '/app/src' (this image will eventually be tagged and pushed to a production registry after builds)
Only adding source code to the image in prod image for not breaking cache during development.