Simple unit tests for ensuring basic functionality of these utility
functions. Exported from the "config" package now for testing.
Change-Id: I5f7133d16c14f99ff0b3b6392e4f210357678a88
Adds a test to ensure that the new use-system-flag declaration is
handled correctly in a YAML config definition.
Change-Id: I551531e20f6b13b60314f4d1d86ac60c7aca9761
We attempt to install dependencies from pip to a custom location using
the --target flag. This flag is broken in Debian/Ubuntu due to a
distro-specific --user install default in versions prior to 18.1.1
(including the Stretch version).
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=830892
This behavior can be switched off by specifying the --system flag in the
install command. This patch adds support for a use-system-flag directive
that allows doing so.
Bug: T227919
Change-Id: Ifacc3d96be3a89135187e46450d524a7d083f885
We've changed the config to be more consistent about "copies" and
"artifacts". This means that "copies" no longer accepts a string, but a
slice of strings. We should bump the config version and blubber version
to make it clear that we're not longer backwards compatible.
Change-Id: Ib68f623cbdcdf0aed74f4fdaec062835748e8eb9
Refactored `copies` configuration to allow for greater control over when
and which both local build context files and variant artifacts are
copied into the target image.
The new configuration introduces a "local" keyword to signify when a
`copies` entry should apply to the files from the local build context as
opposed to files from another variant's image during a multi-stage
build.
variants:
build:
copies:
- from: local
source: ./src
destination: .
Note that with this change, the user must now explicitly define whether
_any_ files should be copied in from the local build context. None will
be copied in by default.
To help keep configurations succinct, especially considering this new
requirement, and to approximate the old `copies: variant`, a shorthand
format and sane defaults for `source` and `destination` (depending whether
`from` is "local" or a variant name) were implemented.
variants:
build:
copies: [local]
development:
copies:
- from: build
- from: local
source: ./config.dev.yaml
destination: ./config.yaml
The shorthand:
copies: [ref, ...]
# is equivalent to
copies: [{ from: ref }, ...]
And the following defaults are used when no `source` and `destination`
are specified.
copies:
- from: local
# defaults to
- from: local
source: .
destination: .
copies:
- from: variant
# defaults to two entries
- from: variant
source: /srv/app # the lives.in dir
destination: /srv/app
- from: variant
source: /opt/local # the shared lib dir
destination: /opt/local
Bug: T211625
Change-Id: I4c4217905afc0762b6bd66ed594d43cc0486e3e2
Uses the github.com/ghodss/yaml library to convert YAML to JSON before
unmarshaling for the purposes of supporting YAML and JSON input while
converting to only support JSON internally.
Bug: T207694
Change-Id: I00668014907e9ea54917f5d5067cac08d0668053
Support for mounting a shared volume instead of copying application
files was meant to provide an option for development use cases. This
functionality has never been thoroughly tested or utilized for any use
case. It should be removed for now.
Relates tangentially to task T204591 that simplifies node support.
Change-Id: Ib70cb7bceb504841897a38d732880ba376fe67c8
The original design decision to install `node_modules` to a central
location outside the application directory was for a purported
development use case not yet realized. It has led to confusion and
unintended failures, and is just generally weird.
Let's right this wrong before it fossilizes into debt, like a hysterical
raisin in the sun.
Bug: T204591
Change-Id: I2e4797833471596b10b6b4a2705055050ca98ac6
The builder configuration has proven useful for supporting generic
pre-entrypoint commands such as dependency managers not otherwise
supported by specific Blubber configuration. Adding additional
`builder.requirements` config expands support for such commands by
allowing the user to specify files that should be copied into the image
before the builder command runs.
To support this extra configuration, `builder` had to be changed from a
simple string to a mapping. The builder command must now by given as
`builder.command`.
The pattern of creating parent directories, copying files, and executing
one or more commands prior to the entrypoint has become a common
one. Some of the implementation of this pattern was moved from
`PythonConfig` into shared build macros `build.SortFilesByDir` and
`build.SyncFiles`. All config types that must have requirements files
copied over independently of the entire source tree (`PythonConfig`,
`BuilderConfig`, `NodeConfig`) now delegate to these functions.
Change-Id: I67f33034f22cee2851ec866cfb07ab20c23eba8c
The `lint` rule was previous surfacing purely whitespace output of
`gofmt` as a failure and running `go tool vet` instead of `go vet` (the
former accepts source files as arguments, the latter takes package
names).
A real lint error in `config/node.go` was also fixed.
Change-Id: I7f13dcbb45a448f1ecac87e97527a7f4ed4d2c48
All import paths and other references to the previously Blubber repo in
Phabricator have been changed to point to the new Gerrit project URL.
Note that building or testing against this change will require you to
move your working directory to `$GOPATH/src/gerrit.wikimedia.org/r/blubber`.
Contribution documentation was updated to reflect the changes, and the
`.arcvendor` submodule has been removed.
Bug: T200452
Change-Id: I3ab23e420b2825e86e2bd7c9b3da9d4de23edaa1
Summary:
Change `node.dependencies` flag to `node.requirements`, the list of
files (typically `package.json` and either `npm-shrinkwrap.json` or
`package-lock.json`) that declare dependencies to be installed with NPM.
Test Plan: Run `go test ./...`. Try it out with something like Mathoid.
Reviewers: thcipriani, hashar, mobrovac, Joe, akosiaris, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1058
Summary:
We want to also install the wheels, not just generate them. To do that
we add a pip install -t <target> command. For this to work however, we
need to install into /opt/lib/python and amend the environment
accordingly to set PYTHONPATH and PATH in order for the libraries and
binaries to be accessible.
Reviewers: dduvall, thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1057
Summary:
Ensure that `DEBIAN_FRONTEND=noninteractive` is set before injecting
`apt-get install` instructions.
Test Plan: Run unit tests.
Reviewers: thcipriani, mmodell, hashar, demon, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1032
Summary:
Since `config.Validate` was changed to take any interface as an
argument, many of the validation tests can be refactored in a way that
avoids having to parse the full config context in YAML and instead
validates each specific config struct directly. The new test pattern is
simpler and less prone to future breakage should unrelated parts of the
overall config change.
Tests that rely on root config context were left unchanged.
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, demon, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1023
Summary:
Introduced a `version` config field that must be specified and match
`config.CurrentVersion`.
Changed `config.ReadConfig` to use `yaml.UnmarshalStrict` to ensure that
errors are surfaced when unknown/bad fields are present in the given
YAML config. A smaller `config.VersionConfig` is now unmarshaled first
to prevalidate the new `version` field before the entire config is
parsed.
Fixes T191460
Test Plan:
Run `go test ./...`. Run `blubber` against some configuration containing
invalid fields and ensure that it surfaces a YAML error.
Reviewers: thcipriani, demon, hashar, mmodell, mobrovac, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T191460
Differential Revision: https://phabricator.wikimedia.org/D1021
Summary:
It occurred to me while looking at code in another patch that there is
no need to have this function be public.
Test Plan: `go test ./...`
Reviewers: dduvall, #release-engineering-team
Reviewed By: dduvall, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1012
Summary:
Use cases involving running of test suites and doc generation require
more liberal ownership and read/write permission to application files.
When `runs.insecurely` is set to `true`, the effective runtime user will
be `lives.as`, the same user that owns the application files and
installed dependencies.
D999 is a complement to this change to allow restrictions on this and
other potentially sensitive configuration.
Depends on D999, D1002
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, mmodell, hashar, #release-engineering-team, demon
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1003
Summary:
The implementation of D984 did not include enforcing ownership for
`build.CopyFrom` instruction and so artifacts copied from one image to
another via `copies:` were problematically owned as root.
In order to fix this behavior:
1. `config.ArtifactConfig` `build.CopyFrom` instructions are now
injected duration `build.PhaseInstall`
2. `config.VariantConfig` calls `build.ApplyUser` for these artifact
instructions as well using the `runs.as` user
3. `build.CopyAs` was refactored to wrap any `build.Instruction` which
should only really be used with `build.Copy` or `build.CopyFrom`.
Test Plan:
Run `go test ./...`. Run `blubber` against configuration with a variant that
uses `copies` and verify that the `COPY --from` instructions also include a
`--chown` flag.
Reviewers: thcipriani, mmodell, hashar, #release-engineering-team, demon
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D1002
Summary:
Implements a rough interface for validating configuration against
arbitrary policy rules. Policies are provided as YAML and passed via the
command line as file paths or remote URIs.
The format of policies is:
enforcements:
- path: <path>
rule: <rule>
Where `<path>` is a YAML-ish path to a config field and `<rule>` is any
expression our config validator understands (expressions built in by the
validator library and custom tags defined in `config.validation.go`).
Example policy:
enforcements:
- path: variants.production.base
rule: oneof=debian:jessie debian:stretch
- path: variants.production.runs.as
rule: ne=foo
- path: variants.production.node.dependencies
rule: isfalse
Command flag parsing was implemented in `main.go` to support the new
`--policy=uri` flag and improve existing handling of `--version` and the
usage statement.
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, demon, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D999
Summary:
A new root and variant `python` config field is provided with two new
fields below, `version` and `requirements`.
The former, `version`, should specify the Python executable to use when
executing related package installation commands and ostensibly the same
executable that will be used to run the application.
The latter, `requirements`, should specify all pip requirements files
such that a compiler that supports layered filesystems (e.g. Docker) can
output separate instructions that will invalidate cache layers for
changes to those files independently of changes to the rest of the
codebase.
Python related instructions will be generated only if either `version`
or `requirements` are given.
Fixes T186545
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, hashar, demon, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T186545
Differential Revision: https://phabricator.wikimedia.org/D976
Summary:
Introduce new `build.EntryPoint` and `build.WorkingDirectory`
instructions to allow configuration to inject them instead of hard
coding their generation in the Docker compiler.
Simplified the Docker compiler to simply iterate over build phases as
returned by a new function `build.Phases()`.
Depends on D990
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, demon, hashar, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D991
Summary:
Introduces new `lives` configuration that provides the name/UID/GID of
the user that will own application files and installed dependencies.
This new configuration is distinct from `runs` in that the former
determines application file location ownership and the latter now only
determines runtime process ownership. Default configuration has also
been introduced for both config sections.
In addition to the new configuration, a new `build.CopyAs` instruction
has been introduced that ensures correct UID/GID ownership of files
copied into the container image, and all unqualified `build.Copy`
instructions are wrapped by the new `build.CopyAs` instruction using the
UID/GID appropriate for the current build phase. A new `build.User`
instruction is also introduced and injected into the build at the start
of certain phases to enforce ownership of `build.Run` processes.
This effective process/file ownership model is:
PhasePrivileged - "root"
PhasePrivilegedDropped - lives.as
PhasePreInstall - lives.as
PhaseInstall - lives.as
PhasePostInstall - runs.as
Fixes T187372
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, hashar, demon, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Subscribers: mmodell
Tags: #release-engineering-team
Maniphest Tasks: T187372
Differential Revision: https://phabricator.wikimedia.org/D984
Summary:
Refactored variant include resolution to correctly order the hierarchy
of includes while still protecting against infinite recursion. The
function was renamed, refactored for clarity, and exported so as to be
better tested and documented with examples.
Test Plan:
Run `go test ./...`.
Check the rendered `config.ResolveIncludes` `godoc` for sanity.
Reviewers: thcipriani, mmodell, hashar, Jrbranaa, zeljkofilipin, demon, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D959
Summary:
Implemented a validation system using the
`github.com/go-playground/validator` package, extending it with custom
validation tags, and implemented translation of validation errors into
somewhat human-friendly messages.
Fixes T175186
Depends on D845
Test Plan: Run the unit tests and try running blubber against some bad config.
Reviewers: thcipriani, hashar, Jrbranaa, Joe, #release-engineering-team, mobrovac
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T175186
Differential Revision: https://phabricator.wikimedia.org/D868
Summary:
Fixed all linter warnings and advice except for vet's rule about unkeyed
composite literals which was disabled via a `-composites=false` flag in
`.arclint`. Most unkeyed literals (e.g. `build.Run{"command"}`) in this
project just seem too usefully succinct compared to their more verbose
keyed counterparts.
Depends on D841
Test Plan: Run `arc lint --everything` and verify there are no warnings or advice.
Reviewers: thcipriani, hashar, #release-engineering-team
Reviewed By: thcipriani, hashar, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D845
Summary:
Wrote inline documentation for all the things.
Fixes T168000
Test Plan: Execute `godoc -http=:6060` and proofread all the things.
Reviewers: thcipriani, hashar, #release-engineering-team, demon
Reviewed By: thcipriani, #release-engineering-team, demon
Tags: #release-engineering-team
Maniphest Tasks: T168000
Differential Revision: https://phabricator.wikimedia.org/D841
Summary:
Debian only provides a package for the GitHub version so it's either
this or we'd have to maintain a patch to change the import paths at
packaging, a moving target for sure.
Since it's only a development dependency, we're not too worried about
versioning it and this is a much more simple solution.
Refs T175609
Test Plan: Run `go get ./... && go test ./...`.
Reviewers: thcipriani, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T175609
Differential Revision: https://phabricator.wikimedia.org/D782
Summary:
Now that our Phabricator instance handles `go get` requests, we can use
a path without the `.git` suffix as the canonical import path.
Test Plan: Run `go test ./...` and `go build`.
Reviewers: thcipriani, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D780
Summary:
Problem running blubber cfg.yml test with this config:
```
base: nodejs-slim
variants:
build:
base: nodejs-devel
development:
includes: [build]
entrypoint: [npm, start]
test:
includes: [development]
entrypoint: [npm, test]
```
yields a Dockerfile with `FROM nodejs-slim`; however, I expected that
the base would be `nodejs-devel` since `test` inherits from
`development` which inherits from `build`.
In order for this to work as expected we have to recursively expand
variants as in this patch.
Reviewers: dduvall, #release-engineering-team
Reviewed By: dduvall, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D773
Summary:
For `npm run` to find executables provided by external dependencies, the
`$NODE_PATH/.bin` directory must be present in `PATH`.
Depends on D769
Test Plan:
Run `go test ./...`.
Build and run Mathoid's test variant at:
https://gerrit.wikimedia.org/r/#/c/376319/2
Reviewers: thcipriani, mobrovac, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, mobrovac, mmodell, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D770
Summary:
Defined new abstract `build.Volume` and corresponding
`docker.DockerVolume` instructions.
Refactored compilation of main `COPY` or `VOLUME` instruction for
application files to use the new instructions and moved injection of
these instructions out of the compiler and into `VariantConfig`. The
latter can be smarter about the following cases:
1. When `copies` is set, simply depend on artifacts for the application
files and do not copy anything from the build host.
2. When `sharedvolume` is `true`, inject a `build.Volume` instruction
for the application working directory.
3. When neither of the above are set, copy application files from the
host.
Fixes T174623
Depends on D768
Test Plan:
Run `go test ./...`. Run `blubber blubber.example.yaml production` and ensure:
1. The `prep` stage has a `COPY . .` instruction.
2. The final stage has no `COPY . .` instruction, only `COPY --from=prep`
instructions.
Reviewers: thcipriani, mobrovac, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, mobrovac, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T174623
Differential Revision: https://phabricator.wikimedia.org/D769
Summary:
Support a `copies` variant config entry that will result in a
multi-stage build, copying both shared library files and application
directory from a previously defined variant. This is essentially a
shorthand for two `artifacts` entries that are likely to be idiomatic to
multi-stage build/prod configurations.
Defined a new abstract `build.CopyFrom` instruction and corresponding
`docker.DockerCopyFrom` instruction and refactored the writing of these
Dockerfile lines to be accomplished using an `InstructionsForPhase`
method on `config.ArtifactsConfig`.
Implemented new support for `copies` configuration in
`config.VariantConfig` and an `InstructionsForPhase` method that returns
`build.CopyFrom` instructions for both the shared library and
application directories.
Fixes T174622
Depends on D759
Test Plan:
Run `go test ./...`. Run `blubber blubber.example.yaml production` and ensure
the right `COPY --from` lines are included for the final stage.
Reviewers: thcipriani, mobrovac, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T174622
Differential Revision: https://phabricator.wikimedia.org/D768
Summary:
Define `NODE_ENV` based on the configuration and define `NODE_PATH` when
either `npm.install` or `npm.env` are true. The latter behavior is
necessary for final stages of multi-stage builds where npm modules are
not installed but the application requires node-related environment
variables to run.
Depends on D757
Ref T174626
Rename npm module/config to node
Renamed `npm` yaml entry to `node` and `NpmConfig` to `NodeConfig`.
Since we're dealing with general node builds and configuration, this
seems to make more sense.
Test Plan:
Run `go test ./...` or `arc unit`. Run blubber against at least the
`blubber.example.yaml`.
Reviewers: thcipriani, mobrovac, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T174626
Differential Revision: https://phabricator.wikimedia.org/D759
Summary:
Install node application dependencies into the common unprivileged
directory defined and managed by `RunsConfig`, and define `NODE_PATH`
such that node applications will search the directory for modules.
This fixes the optimization of image layers by using the original
location for installed modules instead of performing a subsequent move
of the modules back into the project directory. The latter may or may
not result in an additional fs layer depending on the backing storage,
making the previous install/move method unreliable.
Fixes T171632
Depends on D741, D756
Test Plan: Run `go test ./...` or `arc unit`. Build a node application image.
Reviewers: thcipriani, mobrovac, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T171632
Differential Revision: https://phabricator.wikimedia.org/D757
Summary:
Establish `/opt/lib` as the location for installing application
dependencies that are installed via unprivileged execution and from
untrusted sources. The directory is created during the privileged build
phase and owned by the unprivileged runtime user.
Depends on D741
Test Plan: Run `go test ./...` or `arc unit`.
Reviewers: thcipriani, mobrovac, mmodell, #release-engineering-team
Reviewed By: thcipriani, mobrovac, mmodell, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D756
Summary:
Refactored build instructions to use concrete types and
`build.Instruction` as an interface instead of relying on a simple enum
and arbitrary string arguments. The formal types result in:
1. Clearer internal data structures
2. Partial compilation and proper argument quoting for all instructions
moved into the common `build` package
3. Higher order instructions like `build.RunAll` that easily reduce to
compiler specific output
Test Plan: Run `arc unit` or `go test ./...`
Reviewers: thcipriani, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D741
Summary:
Refactored build instructions in `RunsConfig` to properly quote command
arguments injected from user data.
Established unit tests for `RunsConfig` instruction phases.
Refs T170285. Depends on D711
Omit ENV instruction when `runs.environment` is empty
Fixes T170285
Test Plan:
Run `arc unit`. Create a config without `runs.environment` defined and verify
that no bare `ENV` line ends up in the `Dockerfile` output.
Reviewers: thcipriani, hashar, mmodell, #release-engineering-team
Reviewed By: thcipriani, #release-engineering-team
Tags: #release-engineering-team
Maniphest Tasks: T170285
Differential Revision: https://phabricator.wikimedia.org/D715
Summary:
One of Golang's "advantages" is not quibbling over style. To this end
the `go fmt` command exists. This is the result of me running:
find . -name '*.go' -exec go fmt {} \;
Test Plan: built package, ran tests
Reviewers: dduvall, mmodell, #release-engineering-team
Reviewed By: dduvall, mmodell, #release-engineering-team
Subscribers: hashar
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D694
Summary:
Added support for definition of environment variables under
`runs.environment`. Corresponding `ENV` instructions will be added to
Dockerfile output for the unprivileged build phase.
Fixes T168425
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, mobrovac, hashar, Jrbranaa, mmodell, #release-engineering-team
Reviewed By: mobrovac
Tags: #release-engineering-team
Maniphest Tasks: T168425
Differential Revision: https://phabricator.wikimedia.org/D691
Summary:
Fixes build issues around home permissions by setting `HOME` to the
unprivileged user's home directory once the "privileges dropped" build
phase has been reached.
Test Plan: Run `go test ./...`.
Reviewers: thcipriani, mobrovac, hashar, Jrbranaa, mmodell, #release-engineering-team
Reviewed By: mobrovac
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D686
Summary:
Refactored bool config fields to use a new `config.Flag` type that keeps
track of whether it was set by unmarshalled data or merged from another
instance, fixing the behavior of these fields when overwritten by
variants.
Fixes T166353
Test Plan: Run config unit tests (`cd config; go test`)
Reviewers: thcipriani, Joe, hashar, mobrovac, mmodell, #release-engineering-team
Reviewed By: mobrovac
Tags: #release-engineering-team
Maniphest Tasks: T166353
Differential Revision: https://phabricator.wikimedia.org/D680
Summary:
Now that the project is hosted on Phabricator the import URIs must be
changed.
Reviewers: thcipriani, hashar, Jrbranaa, mmodell, #release-engineering-team, demon
Reviewed By: #release-engineering-team, demon
Tags: #release-engineering-team
Differential Revision: https://phabricator.wikimedia.org/D657
Establish phases within Docker compiler to allow providers (apt, npm,
etc.) to inject their own run/copy instructions into to the Dockerfile
compilation process while leaving the compiler agnostic to the providers
themselves.
The instructions and phases are also generalized to leave room for
alternative compilers should they be needed in the future (e.g. aci
support via acbuild) but also as a general design constraint to leave
compiler implementation concerns out of providers.