Before docker: I used to build the Release bits and run a set of test on them. Those bits were tested from Unit Tests to Comp, Functional, E2E, etc..
With docker: 1) I have a CI pipeline to test the bits, but ... 2) With Docker file I build and push the bit on the image in the same time. So considering the non-deterministic build system this is risk.. Is any way that I can write the Dockerfile to address this concern, or what is your approach?
Dockerfile for .net core that I am using as sample:
COPY . .
COPY /service /src/service
RUN dotnet build "src/service/ConsoleApp1/ConsoleApp1.csproj" -c release -o /app
FROM build AS publish
RUN dotnet publish "src/service/ConsoleApp1/ConsoleApp1.csproj" -c release -o /app
WORKDIR /app
FROM runtime AS final
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ConsoleApp1.dll"]
The general practice I follow is:
First stage:
.JAR
for java, .DLL
for dotnet)git tag
Second stage:
eg. (WARNING: is not tested)
FROM microsoft/dotnet:latest
RUN mkdir -p /usr/local/app
COPY your-service/artifact-location/artifact-name.dll /usr/local/app
ENTRYPOINT ["dotnet", "/usr/local/app/ConsoleApp1.dll"]
Third stage:
Here is example for java here if that helps - https://github.com/prayagupd/eccount-rest/blob/master/Dockerfile and CICD pipeline for Jenkins - https://github.com/prayagupd/eccount-rest/blob/master/Jenkinsfile
First of all, our build system should be deterministic - if it is not, you have a problem. As for your Dockerfile: The file shown is really threeimages - the first one builds the code, the second one publishes it and the last one merely executes it.
A good pipeline usually looks like this:
Build AND Unittest - if the unittests fail, abort the build. If unittests are green, publish the generated image to a docker registry of your choosing.
Use that image in a dev environment, e.g. a Kubernetes cluster, azure container instances etc. pp. Now run any E2E, IT tests etc you need. Only and only if all of your tests are coming back green promote the image to a production environment, e.g. move them from dev to prod. Your dev environment can look totally different depending on the solution - if you have a single service you want to deploy, run the e2e tests directly, but maybe you have a complex cluster you need to set up, so run the tests on such a test cluster.
Since the image cannot change due to the nature of docker you can safely promote the image from dev to production. But you need to make sure that you never overwrite an image in your registry, e.g. avoid the latest tag and use explicit tags or even sha256 tags.