For the docker bit, I believe the COPY and RUN commands being interchanged as Donut mentioned in the comments could help. Reference for this and backing of the claim: Semaphore Article explaining the layer caching. But Since you are using a docker in docker type build this is unlikely to be much.
For the Ethereum dev tools themselves, I believe this is as ...
basically when you call approve from inside your contract then inside the approve method the msg.sender is your contract.
so replace uint allowed = IERC20(token1).allowance(msg.sender, address(sushiRouter)); with uint allowed = IERC20(token1)....
In my case, I forgot to specify which contract blockchain-service/migrations folder. Read further the details here: https://www.trufflesuite.com/tutorials/robust-smart-contracts-with-openzeppelin#compiling-and-deploying-the-smart-contract