Skip to main content

· 3 min read
Alex Kouzemtchenko

Espresso AI started as a primarily Linux shop, but as we've added more developers on OS X we've needed a way to build docker containers on OS X that are compatible with our Linux production environment.

Pants has supported running portions of the build in docker containers for a while, but the exact configuration is a little tricky, particularly if you want to build x86_64 containers on Apple ARM processors.

The recipe itself is very straight forward, adding these two sections to your root BUILD and pants.toml files will build your python binaries and docker containers for Linux/x64 on both Linux & OSX:

BUILD
__defaults__({
pex_binary: dict(environment="linux"),
docker_image: dict(build_platform=["linux/amd64"]),
})

local_environment(
name="local_linux",
compatible_platforms=["linux_x86_64"],
fallback_environment="docker",
docker_env_vars=["AWS_PROFILE=profile"]
)

local_environment(
name="local_osx",
compatible_platforms=["macos_arm64"],
)

docker_environment(
name="docker",
platform="linux_x86_64",
image="python:3.11-bookworm",
docker_env_vars=["AWS_PROFILE=profile"]
)
pants.toml
[environments-preview.names]
local = "//:local_linux"
local_osx = "//:local_osx"
docker = "//:docker"

With these snippets, we have defined 3 environments:

  • A docker environment with associated image for running the linux builds
  • A local linux environment that falls back to docker
  • An OSX environment for running non-linux builds & other goals locally on osx

We've setup a few defaults for our repo to avoid unnecessary configuration in our BUILD files:

  • All of our pex_binary targets are built using either the local or docker linux environments via the fallback mechanism
  • All of our docker_image targets have the build_platform explicitly specified so that we do not inherit the platform defaults to build arm64 images.

The other targets, such as tests, get built/run/etc using one of the maching local_workspace targets.

We've also worked around a non-obvious requirement to duplicate our [docker.env_vars] setting in the docker_env_vars field of the docker_environment target. If your publish of a docker container is failing, this is likely the cause.

Troubleshooting Tips

If you are tempted to apply the build_platform argument on your individual docker_image targets, or attempt to add this to your Dockerfile, note that you need to specify this on the entire chain of docker images you depend on if you have multi-stage builds.

If you have attempted your own version of this build_platform setup before using this recipe, you may run into some caching issues and may benefit from using the --no-local-cache flag once to get builds working.

If you notice you cannot publish images with this setup, run the publish command with the PANTS_LEVEL=debug environment variable to see what environment variables are actually making it to the docker push command.

Understanding common errors

If you are receiving errors like this, it indicates you are attempting to run a linux/x64 binary on a linux/arm64 container image and need to adjust your docker image by updating the build platform as shown in the example above:

Failed to find compatible interpreter on path /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin.

Examined the following interpreters:
1.) /usr/bin/python3.10 CPython==3.10.12
2.) /usr/bin/python3.11 CPython==3.11.9

No interpreter compatible with the requested constraints was found:

A distribution for pendulum could not be resolved for /usr/bin/python3.11.
Found 1 distribution for pendulum that do not apply:
1.) The wheel tags for pendulum 2.1.2 are cp311-cp311-manylinux_2_35_x86_64 which do not match the supported tags of /usr/bin/python3.11:
cp311-cp311-manylinux_2_35_aarch64

· 2 min read
Greg Niemann

Today we are excited to announce that Klaviyo has become the first Platinum sponsor of the Pants project via the corporate sponsorship program! This is one of the first such sponsorships through our new Open Source Sponsorship program, through which we are trying to support the open source projects we depend on. While the core development and maintenance of Pants is volunteer driven, there are costs involved with maintaining and distributing such a large piece of software, costs which far too often are covered by individual volunteers. We benefit enormously from this project and want to help contribute to its ongoing success.

Klaviyo chose Pants as the build system for our backend monorepo 18 months ago (read about how we chose Pants here). Since then, we have been impressed not only by the power, flexibility and ease of use relative to other systems that Pants offers, but also by the amazing community that surrounds it. It is truly the Pants community that sets it apart, from active development efforts to the vibrant and welcoming Slack. This community is a prime reason we chose Pants, and is what we hope to foster with our sponsorship.

Like all software of this size, we recognize there are costs associated with the development of Pants - from compute costs for CI, to hosting for the incredible documentation site. We are happy to help fund these costs so that the project and community can continue to grow. We hope that our initial sponsorship will prompt other commercial businesses using Pants to do the same, at any level of support, helping to support a growing Pants community for years to come.

· One min read
Gregory Borodin

A frequently asked question on Pants Slack is how to set a version - such as for a docker image, helm chart or Python distribution - based on git state.

Pants does have various solutions for this, but they tend to be too complicated, or too limited:

It turns out there is a hack that elegantly solves this problem. To make it work we need one more pants feature hidden in the docs — the .pants.bootstrap file. It makes it possible to automatically set the VERSION env var right before pants starts:

.pants.bootstrap
#!/bin/sh

VERSION="${VERSION:-$(git describe --tags --dirty --match "[0-9\.]*" || echo 0.0.1)}"
export VERSION

Now we can use the env var everywhere!

To set docker_image tag:

docker_image(
name="image",
image_tags=[env("VERSION")],
)

To pass docker_image build arg:

docker_image(
name="image",
extra_build_args=["VERSION=" + env("VERSION")],
)

To set python_distribution version:

python_distribution(
name="mydist",
provides=python_artifact(
name="mydist",
version=env("VERSION"),
),
)

To set helm_chart version:

helm_chart(
version=env("VERSION"),
)

· 3 min read
Joshua Cannon

Make builds more reliable and save time doing so. The upcoming Pants 2.16 introduces a couple of exciting changes to make Pants safer, faster, and more user-friendly. Here we preview a pair of changes which increase hermeticity.

· 7 min read
Christopher Neugebauer

"Blue Bill Duck" by Richard Ashurst licensed under CC BY 2.0

The 2.15 series represents the biggest change to Pants since version 2.0, and we're excited to share how it can let you complete more workflows, more easily, in more places. Including cross-platform builds, containerized builds with Docker, and easier configuration for local builds…

· 4 min read
Benjy Weinberger

Image by NTNU, Faculty of Natural Sciences (license)

Pants balances release velocity and end-user stability via judicious use of deprecation cycles. Experimental backends are a way to get quick feedback on new functionality, before "graduating" it to the formal deprecation policy. Experimental features are still well-supported, and not to be feared!

· 10 min read
Benjy Weinberger

Unlike earlier build systems, Pants v2 automatically infers your code's internal and external dependencies. And it does this at the file level, so that you get optimal invalidation, caching, and concurrency performance without having to manually create and maintain mountains of BUILD file metadata.

· 6 min read
Stu Hood

Highlights include: less boilerplate via hierarchical defaults for target field values, better Golang monorepo support, with multiple go.mods, do more of your workflows in Pants with the experimental deploy goal (with initial support for Helm), and much more…

· 5 min read
Benjy Weinberger

GraphMyRepo.com in action, graphing the dependencies and code structure of pantsbuild/pants. Source: Toolchain.com

To make it easier to understand the value and power of dependency inference, Toolchain (the lead sponsor of Pants) has built a new site: Graph My Repo. As its name suggests, Graph My Repo shows you an interactive graph of a public GitHub repo of your choice…

· 6 min read
Christopher Neugebauer

We're pleased to announce Pants 2.13.0. Highlights include better command line arguments for file sets, improved JVM support, easier access to parallel execution in CI, and lower barriers to adoption for Python projects that currently use existing distribution and build tools.

· 8 min read
Joshua Cannon

The Python and Docker logos, with a plus sign between them

Pants can build a PEX file, an executable zip file containing your Python code and all transitive dependencies. Deploying your application is as simple as copying the file. This post elaborates on how to get best performance out of the powerful combination of Pants+PEX+Docker.

· 8 min read
Benjy Weinberger

Image by Markus Spiske / CC0 1.0

Working effectively in a monorepo requires appropriate tooling. While Pants can be a really useful system in repos of all sizes and architectures, it has some features that make it particularly appealing in a monorepo setting…

· 5 min read

Pants 2.6 can now understand Poetry's pyproject.toml configuration for third-party dependency management, addressing one of our most requested features in the last year!

Pants Contributor Liam Wilson delves into this new feature as well as his experiences developing the macro as a Toolchain intern.

· 9 min read
Benjy Weinberger

There are so many tools in the Python development ecosystem. Installing, configuring and orchestrating them—all while not re-executing work unnecessarily—is a hard problem, especially as your codebase grows.

Fortunately, there is now a tailor-made (pun intended) solution: Pants v2!