Simon's Blog

Dev vs Ops - Hide and Seek

March 11, 2021

Introduction

I received a merge request for review. The changes involved renaming a folder, with no other discernable changes. This MR had the following paraphrased description:

The code works on my laptop, but this is the only way I could get it to build on Jenkins, otherwise the build fails.

🤔

Blurred Line

Similar to my last blog post in the Dev vs Ops series, my mind wandered onto the difference between this dev’s machine (a Macbook similar to mine) and Jenkins. I knew it had something to do with docker.

One of the selling points of containerisation is that the same container that builds on a dev’s machine gets built on your CI and gets shipped out to production, reducing the impact of different environments.

To rule out the environments being the issue, I attempted to build the docker image locally and in fact the same error occurred. Something was failing between our machines and the docker daemon.

Solution

Most dockerfiles will have the following directive or something similar within them:

COPY . .

This line basically says copy everything from the host in this directory into the docker container’s root folder. One might want to only copy a src folder and nest in inside another directory in the container, which would look something like this:

COPY src/ /app/src/

When you run docker build, the docker daemon will actually show you the progress of copying the host’s context into the docker daemon and the amount of data it moves across this boundary.

We do not want to move everything from the host into a container, typically we would only want to move the minimum required to be able to build and run our code.

Rather than specifying exactly what we want to copy into the container (using COPY) in a whitelist fashion, instead we can do this in a blacklist fashion by creating a file called .dockerignore.

Similar to .gitignore, this file instructs the docker daemon to ignore specific files, folders or combination thereof.

It turns out that one of the files was importing a file held inside a specific folder… this same folder was included in the .dockerignore file as it was not required at runtime in production. This meant that the file existed at build time on the dev’s machine, but not within the docker daemon when the container was being built.

Takeaway

Works on my machine needs to be taken with a pinch of salt, or you’ll end up playing hide and seek with missing files.


Written by Simon who lives in Malta. You can find out more about me on the about page, or get in contact.