137

I used to list the tests directory in .dockerignore so that it wouldn't get included in the image, which I used to run a web service.

Now I'm trying to use Docker to run my unit tests, and in this case I want the tests directory included.

I've checked docker build -h and found no option related.

How can I do this?

satoru
  • 31,822
  • 31
  • 91
  • 141

6 Answers6

210

Docker 19.03 shipped a solution for this.

The Docker client tries to load <dockerfile-name>.dockerignore first and then falls back to .dockerignore if it can't be found. So docker build -f Dockerfile.foo . first tries to load Dockerfile.foo.dockerignore.

Setting the DOCKER_BUILDKIT=1 environment variable is currently required to use this feature. This flag can be used with docker compose since 1.25.0-rc3 by also specifying COMPOSE_DOCKER_CLI_BUILD=1.

See also comment0, comment1, comment2


from Mugen comment, please note

the custom dockerignore should be in the same directory as the Dockerfile and not in root context directory like the original .dockerignore

i.e.

when calling

DOCKER_BUILDKIT=1
docker build -f /path/to/custom.Dockerfile ...

your .dockerignore file should be at

/path/to/custom.Dockerfile.dockerignore

Nam G VU
  • 33,193
  • 69
  • 233
  • 372
thisismydesign
  • 21,553
  • 9
  • 123
  • 126
  • 39
    Note the custom `dockerignore` should be in the same directory as the `Dockerfile` and not in root context directory like the original `.dockerignore` – Mugen Nov 27 '19 at 09:39
  • 5
    @Mugen -- if the Dockerfile is in a subdirectory of the context, are the paths in the docker ignore relative to the location of the Dockerfile? (so you can ignore e.g. `../foo`?) – shaunc Dec 31 '19 at 00:57
  • 11
    @shaunc surprisingly no, they are relative to the location of the context – Mugen Dec 31 '19 at 07:44
  • 3
    I've tried this and it isn't working with docker-compose – SumNeuron Jan 14 '20 at 14:40
  • This does not work if you are using experimental syntax in Dockerfile: `# syntax = docker/dockerfile:1.0-experimental` – Aalex Gabi Jan 29 '20 at 11:01
  • So disappointed that it requires buildkit to which I tried to migrate about seven times and failed each time... – Szczepan Hołyszewski May 13 '20 at 16:20
  • @sumneuron I was not able to get this to work with docker-compose either – vizon Jul 14 '21 at 20:19
  • 8
    What if you are doing scripted builds with `-f -`? A flag just seems simplest; would be great if we could use `-i dockerignore-fifo` – Darren Bishop Jul 16 '21 at 11:57
  • 1
    @DarrenBishop Probably will not happen because docker devs do not work well with community. Check this one [issue](https://github.com/moby/moby/issues/12886). It has been more than 7 years... – piotrekkr Jul 04 '23 at 06:37
21

At the moment, there is no way to do this. There is a lengthy discussion about adding an --ignore flag to Docker to provide the ignore file to use - please see here.

The options you have at the moment are mostly ugly:

  • Split your project into subdirectories that each have their own Dockerfile and .dockerignore, which might not work in your case.
  • Create a script that copies the relevant files into a temporary directory and run the Docker build there.
nwinkler
  • 52,665
  • 21
  • 154
  • 168
  • Seems like there are lots of other options. Perhaps too many. One is to temporarily move files you don't want in the build to an ignored directory (I think this even reduces the context). Another is to create a tarball to add to the image (This doesn't help with the size of the context). Another is to have alternate ignore files and move them into the `.docker_ignore` name as necessary. – nroose May 03 '19 at 22:02
3

Adding the cleaned tests as a volume mount to the container could be an option here. After you build the image, if running it for testing, mount the source code containing the tests on top of the cleaned up code.

services:
   tests:
      image: my-clean-image
      volumes:
         - '../app:/opt/app' # Add removed tests
Kazlauskis
  • 141
  • 1
  • 8
3

I've tried activating the DOCKER_BUILDKIT as suggested by @thisismydesign, but I ran into other problems (outside the scope of this question).

As an alternative, I'm creating an intermediary tar by using the -T flag which takes a txt file containing the files to be included in my tar, so it's not so different than a whitelist .dockerignore.

I export this tar and pipe it to the docker build command, and specify my docker file, which can live anywhere in my file hierarchy. In the end it looks like this:

tar -czh -T files-to-include.txt | docker build -f path/to/Dockerfile -

HHK
  • 1,352
  • 1
  • 15
  • 25
1

Another option is to have a further build process that includes the tests. The way I do it is this:

If the tests are unit tests then I create a new Docker image that is derived from the main project image; I just stick a FROM at the top, and then ADD the tests, plus any required tools (in my case, mocha, chai and so on). This new 'testing' image now contains both the tests and the original source to be tested. It can then simply be run as is or it can be run in 'watch mode' with volumes mapped to your source and test directories on the host.

If the tests are integration tests--for example the primary image might be a GraphQL server--then the image I create is self-contained, i.e., is not derived from the primary image (it still contains the tests and tools, of course). My tests use environment variables to tell them where to find the endpoint that needs testing, and it's easy enough to get Docker Compose to bring up both a container using the primary image, and another container using the integration testing image, and set the environment variables so that the test suite knows what to test.

Mark Birbeck
  • 2,813
  • 2
  • 25
  • 12
0

Sadly it isn't currently possible to point to a specific file to use for .dockerignore, so we generate it in our build script based on the target/platform/image. As a docker enthusiast it's a sad and embarrassing workaround.

Peter Kionga-Kamau
  • 6,504
  • 2
  • 17
  • 13