Improvement proposal: Embrace native remote build contexts to improve Dockerfile design

Overview

The spec has good intent behind of idea of build anywhere, however advising against the the use of COPY from the local context is an unnecessary condition, since Docker has native support for remote build contexts. This results in loosing version association with the local source control system and produces a cyclic reference that’s tedious to maintain . There is also an improvement for end-users so should be seen as a win-win situation.

Current state

The spec assumes the build will only ever be made using the PATH option such as:

docker build .

which is missing some very nice docker build features for working with other perfectly valid inputs.

Proposal

Adjust the spec wording

It must be possible to build an image in an empty directory using a single docker build command.

This means the current pattern is not excluded, instead it lifts the implied limitation that currently exists

Allow build context to be set natively

Relative source code can be brought into the build context from a remote location, adhering to the spec, and allowing natural COPY instructions that work equally well for automation, development, and end-users.

A nice standard approach that will cover most implementations, with natural versioning

docker build -t some-rosetta:1.2 https://github.com/some-rosetta.git#1.2
docker build -t ${git.commit}  .

This would no longer be deemed bad practice:

FROM golang:1.13

COPY . .
make build

CMD node run

Case study - Cardano Rosetta

We shipped a refactored design in 0.2.1.

  • Dockerfile diff
  • There is no longer a static version reference which the previous value of master was invalid as the file accessed from a point in the history should be locked here.
  • dev.Dockerfile removed, which first required a bash script to build the required layers from the Dockerfile into images, so that it could get access to common code via reference. The host no longer has disconnected state left behind on standard cleanups

With this refactor, automated CI testing was implemented, as the old limitation made it awkward to setup the PR merge preview state and was subsequently deferred.

:wave: @rhysbw Thanks for posting this improvement proposal. I hope to see many more community-driven improvements to Rosetta! :rocket:

TL;DR I think this is a great proposal. I’ve circled up with our blockchain/infra team internally and they are also comfortable with this build strategy. I’ll update the website this week with the new guidance!

In the past, we’ve steered away from native remote build contexts because our infrastructure team felt they introduced an unnecessary attack vector (as anyone could potentially manipulate the build context and copy something into the build). Typically, the Dockerfiles we use in production don’t use any build context (which explains the requirement for no COPY instructions on the website).

We aren’t as concerned with downloading files in the Dockerfile because we always checkout code at commit hashes and perform checksums (which seems tougher to enforce with remote build contexts…I need to read up on this in the docs).

I’ve felt this pain while working on our rosetta-bitcoin implementation as every new commit should technically set the commit in the Dockerfile with the previous commit (and you cannot run the most recent commit until actually committing the code to get the hash). When developing locally, I usually comment out the git clone and just use a COPY . . (which is clearly an indication of a problem haha).

I think your proposed spec word does a great job of capturing the nuance we really care about: It must be possible to build an image in an empty directory using a single docker build command. I think the method you’ve proposed here is totally fine (for those concerned, it is trivial to replace the COPY with the link provided for the remote build context on a forked image). As you’ve mentioned, supporting this pattern should make development less tedious and Rosetta implementations easier to use out-of-the-box (less Dockerfile changes across updates). I don’t see any harm in allowing teams to pin code to commits if they prefer, so I’m not going to propose we deprecate that approach.

Thanks again for posting!

1 Like