My workflow is based around Google Container Registry and build triggers.
With those you get unlimited private repos to make all your custom Docker images, and they rebuild everytime you push to GitHub linked to a specific branch, so you can have production/dev/fork etc. to pull from.
I usually build on top of a specific Rocker image, adding all the dependencies as needed, and/or relying on the aforementioned containerit to build the Dockerfile. Then push it to GitHub to have the Docker image available, that are launched in their own VM.
The VMs run on their own version and pull data jobs etc., but if the code/environment updates I can run another VM with the new Docker to test it first before moving it over to the production main branch.
I think Docker is really useful for R in particular, being able to pin down the installed libraries etc.