What is the Dockerfile "right approach" for production?

9/2/2019

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"]
-- user3053247
.net-core
docker
docker-compose
dockerfile
kubernetes

2 Answers

9/2/2019

The general practice I follow is:

First stage:

  1. once feature branch merged to master, run tests in CICD(eg. Jenkins)
  2. Once tests succeed, build the versioned artifact eg. (.JAR for java, .DLL for dotnet)
  3. publish the versioned artifact to artifactory(eg Jfrog or nexus) if needed
  4. create a git tag

Second stage:

  1. use versioned artifact created above and create versioned container image copying only the artifact. If you don't have artifactory yet, you can simply copy the local artifact.

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"]
  1. tag the versioned container image and push to container registry (eg. elastic container registry(ecr) from Amazon)

Third stage:

  1. update kubernetes deployment manifest with new version of container image.
  2. apply kubernetes deployment manifest

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

-- prayagupd
Source: StackOverflow

9/2/2019

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.

-- Christian Sauer
Source: StackOverflow