blob: 71f1dbe12a01424bb61a1f1661a45df0efc6bad0 [file] [log] [blame] [view]
# DockerBuild
`infra.tools.dockerbuild` is a management and execution environment for Chrome
Infrastructure's Docker toolchain build environment. Fundamentally, it handles:
- Generation and internment of Chrome Infrastructure Docker build images.
- Specific build instructions for Python wheels.
- Entry point for build operations using Docker toolchains.
DockerBuild is complex. It justifies this complexity by solving some annoying
problems:
- Cross-compiling is really useful. It is difficult to have continuous builders
for each supported platform, especially the more esoteric ones. Adding support
for a new platform is decoupled from actually having that platform running.
- Cross-compiling Python wheels is nuanced and full of errors. Python build
scripts, in general, do not really accommodate cross-compiling without hacks.
These hacks, and the overall logic, should be enshrined somewhere.
- Building the Python `cryptography` wheel for Linux really sucks. This logic
and all of its prerequisites should be enshrined in a script somewhere.
- In general, it is really good to zip up build toolchains and environments
and use them hermetically instead of relying on the configuration of a
builder somewhere.
## DockerBuild Images
DockerBuild images are based on
[dockcross](https://github.com/dockcross/dockcross) project images. Each
`dockcross` image bundles a platform's toolchain with an entry point script
which can be used to execute commands within that toolchain. The script, when
run, mounts a directory to `/work` within the Docker image and invokes the
provided command on that directory. This allows a user to almost-seamlessly
use the `dockcross` image's toolchain to operate on local files. This, in turn
makes it really easy to cross-compile.
DockerBuild extends `dockcross` images to add:
- A host and cross-compiled Python environment.
- A host Perl installation.
- Several packages in support of generation of complex Python wheels.
See [dockcross.py](dockcross.py) for more details.
DockerBuild images, like `dockcross` images, can be run using a generated entry
point script. This can be created by running the image:
```bash
docker run <image-name> > ./entrypoint.sh
chmod +x ./entrypoint.sh
./entrypoint.sh
```
Alternatively, the script can be run through `dockerbuild` using the `run`
subcommand.
## Note on Windows and Mac
It is important to note that Docker image environments only exist for Linux
systems at the moment. Chrome Infrastructure's build strategy for Windows and
Mac is to actually perform the builds on real Windows and Mac systems. Support
for Windows and Mac Python wheels is built into DockerBuild, but serves mostly
as a wrapper around using `pip` to download pre-generated packages and upload
them to CIPD.
Windows and Mac support are gated on the ability to have a fully-functioning
Windows and Mac build toolchain running in a Linux (i.e., Docker) environment.
This may be possible with a combination of `wine` and/or a Mac cross-compiler,
but this is not currently explored or implemented.
## Lifecycle
Walking backwards through the lifecycle of this script:
- Building Python wheels requires
- Python wheel source files, which requires
- Downloading and storing Python sources in CIPD.
- It also requires a DockerBuild image, which requires
- A `dockcross` base image and a set of sources.
- The sources need to be interned in CIPD for consistency.
- The `dockcross` base image needs to be built independently.
Minimal operation will use cached pre-built DockerBuild images and cached
CIPD sources, allowing a user to avoid building everything from scratch.
However, the logic to build everything from scratch is included in DockerBuild
for updates and reproducibility.
### Subcommand: sources
The various sources used to build Python wheels and DockerBuild images must be
downloaded from the Internet and interned in CIPD packages. This ensures that
any given image will be reproducible and resilient to external packaging and
infrastructure changes.
The `sources` subcommand scans through all sources used by DockerBuild,
acquires them, and creates CIPD packages for them. Run `sources` with the
`--help` flag for more information.
If new sources are added, or sources without CIPD packages are identified,
a warning message will be printed at the end of DockerBuild operation
encouraging the user to upload source CIPD packages for future reproducible
builds.
### Subcommand: docker-mirror
The `dockcross` project's images are used as base images for DockerBuild's
specialized images. Rather than rely on upstream Docker hosts, DockerBuild
offers the `docker-mirror` subcommand to load upstream `dockcross` images and
store them in our Google Cloud Docker image registry.
`docker-mirror` can be run to synchronize and/or update the local images. All
DockerBuild images are generated from the local images, not the upstream images,
so an explicit synchronization step is required to update their `dockcross`
bases.
### Subcommand: docker-generate
DockerBuild's specialized Docker images can be built locally using the
`docker-generate` subcommand. This will pull the base `dockcross` images
and required sources and construct local DockerBuild images.
Optionally, the local images can be pushed to the Google Cloud Docker image
registry using the `--upload` flag. This ensures that other users of the script
can retrieve and use the images without requiring them to build them locally.
### Subcommand: wheel-build
DockerBuild has specific support for building Python wheels and uploading them
to CIPD. This synergizes with
[vpython](/go/src/infra/tools/vpython)'s CIPD wheel packaging expectations.
Wheels can be built and uploaded by using the `wheel-build` subcommand, and
uploaded using the `--upload` flag.
Support for additional Python wheels and/or wheel versions can be added by
editing [wheels.py](wheels.py) and adding entries for the new wheels.
Adding support for universal wheels is easy. Adding support for **most**
platform-specific binary wheels can range from easy to hacky-difficult depending
on the wheel's binary requirements and suitability for cross-compiling. This has
to be evaluated on a case-by-base basis, sadly.
### Subcommand: run
DockerBuild offers an entry point into a DockerBuild image's toolchain
environment through its `run` subcommand. `run` will mount the specified
directory inside of the DockerBuild environment and execute the specified
command against that directory.
`run` can be used to cross-compile software (e.g., `git`) for other Infra
platforms.
## Problems with Known Fixes
### Got permission denied while trying to connect to the Docker daemon socket...
Fix: Add your local user to the docker POSIX group:
```
sudo usermod -a -G docker $USER
```
You need to restart your shell for this to take effect.
### Got permission denied while trying to upload CIPD package...
Upload rights are restricted to troopers and members of
[`vpython-wheels-uploaders`](
https://chrome-infra-auth.appspot.com/auth/groups/vpython-wheels-uploaders)
First, make sure you are logged into cipd with your @google.com account.
```bash
cipd auth-info
cipd auth-login
```
Second, [file a bug with the Infra\>LUCI\>Admin component](https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ELUCI%3EAdmin) to add you to this group.
### Got permission denied while downloading docker image
When running commands that require docker images, such as the
`docker-generate` subcommand, you need to be authenticated.
It is recommended to use gcloud to handle this; try running
`gcloud auth configure-docker`. Authenticating with a google.com
account using `gcloud auth login` may be necessary.
### Error response from daemon: squash is only supported with experimental mode
Fix: Run docker in experimental mode (yes, this is a hack):
```
vim /etc/default/docker
# Edit file such that DOCKER_OPTS includes "--experimental=true"
sudo service docker restart
```
## Examples
### Upload all sources to CIPD
To upload all sources to CIPD, run:
```bash
vpython3 -m infra.tools.dockerbuild --upload-sources sources
```
### Update dockcross base image mirrors
To update the Google Cloud repository's mirrored `dockcross` images, run:
```bash
vpython3 -m infra.tools.dockerbuild docker-mirror --upload
```
### Build and upload DockerBuild images
To build new DockerBuild images and upload them to the Google Cloud repository,
run:
```bash
vpython3 -m infra.tools.dockerbuild docker-generate --upload
```
### Regenerate all configured wheels
To ensure that all configured Python wheels are uploaded to CIPD for all known
platforms, run the following command:
```bash
vpython3 -m infra.tools.dockerbuild --upload-sources wheel-build --upload
```
- `--upload-sources` instructs DockerBuild to upload CIPD packages for any
new wheel sources that are not already locally mirrored.
- `--upload` instructs the `wheel-build` subcommand to upload any wheels that
are not currently present in CIPD.
This can be run after adding a new wheel configuration, or after adding a new
platform to support.