<p>I don't know if this is a good practice or not, but I usually create 2 docker files.
One just runs the application and the other runs a multi-stage build (including test), the latter is only used by the developer, the former is the one used on CI.</p>
<p>The CI steps depend mostly on what language is the code, what types of tests you want to run, and what process (or development flow)  the company use.</p>
<p>For a compiled language (like java or golang):</p>
<p>tests that does not need to build the code (unit tests, SAST..) --&gt; build (the code and the container image if needed) --&gt; tests that need a runnable version of the code (end-to-end) --&gt; artifact repository</p>
<p>For a non compiled language (like php or python):
tests --&gt; tag</p>

CC BY-SA 4.0
2021-08-01T05:23:18.730Z
When we run the build in a docker process (during docker build) how do we get test reports etc.? Also it's possible to run different tasks in parallel in Jenkins e.g. you can run unit tests, component tests and integration test all together and the final build status can be concluded based on outcome of all 3. How would you achieve something of that sort with this?
dev2d
CC BY-SA 4.0
2021-07-30T22:59:29.670Z
2021-08-05T15:05:53.653Z
2021-08-05T15:05:53.653Z
Joao  Vitorino
<p>It would be consistent with most other languages' setups to run <code>gradle build</code> in a Dockerfile.  You may want to set up a <a href="https://docs.docker.com/develop/develop-images/multistage-build/" rel="nofollow noreferrer">multi-stage build</a> so that the first stage has a complete JDK, <code>COPY</code>s in the <code>build.gradle</code> and source code, and builds it; and then the second stage only contains the JRE and the jar file <code>COPY --from=</code> the first stage.  (Java is unusual in that it's <em>possible</em> to build a portable jar file outside Docker and <code>COPY</code> it directly into an image; most other languages either interpret the source directly, or build a native artifact that's not as portable.)</p>
<p>The advantages of doing this are IMHO somewhat minimal.  If you have a multi-language environment, being able to <code>git clone; docker build</code> every service the same way is useful.  You will use the JVM specified by the Dockerfile's <code>FROM</code> line, instead of what's installed on the host, but you will probably need a JVM anyways for day-to-day development and IME the precise patch level of the JRE isn't that important in practice.</p>
<hr />
<p>I would not run tests in a Dockerfile.</p>
<p>At a philosophical level, they don't really belong there.  The Dockerfile has one task: it takes source files or a jar file in, and produces a Docker image out.  The Dockerfile system is designed for it to be hard for there to be side effects, so it's very difficult to start a support process or access a database even if you otherwise would want to.  Running tests are in some way a &quot;side effect&quot; like this.</p>
<p>Mechanically, it makes sense to run tests both before and after the image build, but not necessarily during.  You can break your tests into <em>unit tests</em> and <em>integration tests</em>.  The unit tests should only depend on your application code, with mocks for any external dependencies; since they don't depend on anything but the code and the JRE, you should get consistent results whether you run them on the host or in a container, and you can first run unit tests and then only build the image if they pass.  The integration tests depend on the entire system, including things you can't connect to from the Dockerfile, and so a good practice here is to run integration tests against the built image as you're about to ship it.</p>
<pre class="lang-none prettyprint-override"><code>   Source code      (checked in to a repository)
        |
        v
   Unit tests       (on the host, no external dependencies)
        |
        v
Docker image build  (push to a repository now if needed)
        |           (only this step is the Dockerfile)
        v
Integration tests   (on the built container, with dependencies
        |            running in other containers, either launched
        v            from the host or a dedicated test-runner container)
     Deploy
</code></pre>
<p>I would avoid complex Dockerfiles that have multiple optional stages that sometimes include test frameworks and sometimes don't.  Build one image and run it in all environments, and keep the Dockerfile simple and readable.</p>

CC BY-SA 4.0
2021-08-04T11:10:07.187Z
2021-08-04T11:10:07.187Z
David Maze
<p>I have mostly seen people using following type of pipeline steps(it varies, but in general this is the flow of steps I have observed)</p>
<blockquote>
<p>Process: clone repo -&gt; build -&gt; test -&gt; create docker image -&gt; push
binary to artifactory -&gt; push image to docker registry</p>
</blockquote>
<p>Recently I came across a docker file (multi-stage docker file) which was executing gradle build and test while building image.</p>
<p>I wanted to reach out to this community and check what are the advantages/dis-advantages of having a docker file which does gradle/maven build and test as a part of <code>docker build</code>?</p>
<p>Please Guide</p>

<docker><dockerfile>
Best Practice for writing DockerFile
dev2d
# Best Practice for writing DockerFile

(Asked by: username_0 on 2021-07-29)

I have mostly seen people using following type of pipeline steps(it varies, but in general this is the flow of steps I have observed)

> Process: clone repo -> build -> test -> create docker image -> push
> binary to artifactory -> push image to docker registry

Recently I came across a docker file (multi-stage docker file) which was executing gradle build and test while building image.

I wanted to reach out to this community and check what are the advantages/dis-advantages of having a docker file which does gradle/maven build and test as a part of `docker build`?

Please Guide

**Tags:** docker, dockerfile


---

## 2 answers

### Answer by username_1 on 2021-07-30. Score: 2

I don't know if this is a good practice or not, but I usually create 2 docker files.
One just runs the application and the other runs a multi-stage build (including test), the latter is only used by the developer, the former is the one used on CI.

The CI steps depend mostly on what language is the code, what types of tests you want to run, and what process (or development flow) the company use.

For a compiled language (like java or golang):

tests that does not need to build the code (unit tests, SAST..) --> build (the code and the container image if needed) --> tests that need a runnable version of the code (end-to-end) --> artifact repository

For a non compiled language (like php or python):
tests --> tag

> **Comments:**
> **username_0**: When we run the build in a docker process (during docker build) how do we get test reports etc.? Also it's possible to run different tasks in parallel in Jenkins e.g. you can run unit tests, component tests and integration test all together and the final build status can be concluded based on outcome of all 3. How would you achieve something of that sort with this?  

---

### Answer by username_2 on 2021-08-04. Score: 0

It would be consistent with most other languages' setups to run gradle build in a Dockerfile.  You may want to set up a multi-stage build so that the first stage has a complete JDK, COPYs in the build.gradle and source code, and builds it; and then the second stage only contains the JRE and the jar file COPY --from= the first stage.  (Java is unusual in that it's possible to build a portable jar file outside Docker and COPY it directly into an image; most other languages either interpret the source directly, or build a native artifact that's not as portable.)
The advantages of doing this are IMHO somewhat minimal.  If you have a multi-language environment, being able to git clone; docker build every service the same way is useful.  You will use the JVM specified by the Dockerfile's FROM line, instead of what's installed on the host, but you will probably need a JVM anyways for day-to-day development and IME the precise patch level of the JRE isn't that important in practice.

I would not run tests in a Dockerfile.
At a philosophical level, they don't really belong there.  The Dockerfile has one task: it takes source files or a jar file in, and produces a Docker image out.  The Dockerfile system is designed for it to be hard for there to be side effects, so it's very difficult to start a support process or access a database even if you otherwise would want to.  Running tests are in some way a "side effect" like this.
Mechanically, it makes sense to run tests both before and after the image build, but not necessarily during.  You can break your tests into unit tests and integration tests.  The unit tests should only depend on your application code, with mocks for any external dependencies; since they don't depend on anything but the code and the JRE, you should get consistent results whether you run them on the host or in a container, and you can first run unit tests and then only build the image if they pass.  The integration tests depend on the entire system, including things you can't connect to from the Dockerfile, and so a good practice here is to run integration tests against the built image as you're about to ship it.
   Source code      (checked in to a repository)
        |
        v
   Unit tests       (on the host, no external dependencies)
        |
        v
Docker image build  (push to a repository now if needed)
        |           (only this step is the Dockerfile)
        v
Integration tests   (on the built container, with dependencies
        |            running in other containers, either launched
        v            from the host or a dedicated test-runner container)
     Deploy

I would avoid complex Dockerfiles that have multiple optional stages that sometimes include test frameworks and sometimes don't.  Build one image and run it in all environments, and keep the Dockerfile simple and readable.


---

