So I believe I came up with a somewhat re-usable solution for this problem using devpi. It allows you to use the same Dockerfile for the testing and production image.
Devpi allows me to create my own index which can shadow my production index with versions of software that haven't been officially released.
Steps to make this work:
1. Base image from ARG
Your use case is very simple, so relying on GIT_STRATEGY=fetch is probably sufficient and as you said the default behavior.
You should be cautious using artifacts unnecessarily as they are uploaded to the gitlab server.
The answer to your question generally depends on a few things, like the size of your repository, network connection, runner executor type, ...
We shouldn't need to create image on each stage and should promote the same image tag in across environments ( i.e whatever we have in UAT will get QA/TESTED and released to PROD as artifact ), how are you managing this image promotion across environment ? what are other release process look like ?
Yes, rebuilding images is considered an anti-pattern in ...
Although difficult to give a canonical answer, I think I understand your frustration. My opinion is that you are focussing on promoting the wrong thing - the image.
I would start with the concept of "Dev-Prod parity" (or in your case, UAT/Prod parity). This concept says:
Keep development, staging, and production as similar as possible
A bit too long for a comment, so converting to an answer:
That's super broad and highly depends on your final needs IMHO, if you're full AWS and ok with being vendor locked down, then code commit/code build/code pipeline is great as it's nicely integrated now.
If you have needs outside pure AWS services, that may get harder, for exemple if you plan on ...