Skip to main content

docker scaffold

The moon docker scaffold <...projects> command creates multiple repository skeletons for use within Dockerfiles to effectively take advantage of Docker's layer caching. It utilizes the project graph to copy all critical files, like manifest, lockfiles, and configuration.

# Scaffold a skeleton to .moon/docker
$ moon docker scaffold <project>

View the official Docker usage guide for a more in-depth example of how to utilize this command.


  • <...names> - List of project names or aliases to scaffold sources for, as defined in projects.


  • --include - Additional files to include in the sources skeleton. Accepts a list of file globs relative from the workspace root.

How it works

This command may seem like magic, but it's relative simple thanks to moon's infrastructure and its project graph. When the command is ran, we generate 2 skeleton structures in .moon/docker (be sure to gitignore this). One for the workspace, and the other for sources.


Because scaffolding uses the project graph, it requires all projects with a package.json to be configured in moon. Otherwise, moon will fail to copy all required files and builds may fail.


The workspace skeleton mirrors the project folder structure of the repository 1:1, and only copies files required for dependencies to install. This is typically manifests (package.json), lockfiles (yarn.lock, etc), other critical configs, and .moon itself. This is necessary for package managers to install dependencies (otherwise they will fail), and for dependencies to be layer cached in Docker.

An example of this skeleton using Yarn may look like the following:

├── .moon/
├── .yarn/
├── apps/
│ ├── client/
│ │ └── package.json
│ └── server/
│ └── package.json
├── packages/
│ ├── foo/
│ │ └── package.json
│ ├── bar/
│ │ └── package.json
│ └── baz/
│ └── package.json
├── .yarnrc.yml
├── package.json
└── yarn.lock


The sources skeleton is not a 1:1 mirror of the repository, and instead is the source files of a project (passed as an argument to the command), and all of its dependencies. This allows moon run and other commands to work within the Dockerfile, and avoid having to COPY . . the entire repository.

Using our example workspace above, our sources skeleton would look like the following, assuming our client project is passed as an argument, and this project depends on the foo and baz projects.

├── apps/
│ └── client/
| ├── src/
| ├── tests/
| ├── public/
| ├── package.json
| ├── tsconfig.json
│ └── (anything else)
└── packages/
├── foo/
│ ├── lib/
│ ├── src/
│ ├── package.json
│ ├── tsconfig.json
│ └── (anything else)
└── baz/
├── lib/
├── src/
├── package.json
├── tsconfig.json
└── (anything else)