Docker support in Pants 2.7
Photo by Ian Taylor / Unsplash
With Pants 2.7 comes a new experimental backend for building Docker images and linting Dockerfiles. This backend offers a seamless experience when bundling your code and files into Docker images - In a single invocation, Pants will build the code artifacts that need to be embedded into the Docker image, and then build the image itself.
Getting started
You represent your Dockerfiles to Pants using the new docker_image
target type in your Pants BUILD files.
But you don't need to create these by hand! The Pants tailor
goal will give you a head start by creating or updating the relevant BUILD files for you:
./pants tailor ::
With your docker_image()
targets in place, you simply run
./pants package path/to/Dockerfile
to build the Docker image for that Dockerfile. Of course you can also use wildcards, so for example you can run
./pants package ::
to build all packageable targets in your repo, such as PEX binaries, Python distributions, archives, AWS Lambdas, and now also Docker images!
There is also support for linting your Dockerfiles, to check for errors and get suggestions for potential mistakes or bad practices. This feature relies on hadolint
, and you invoke it just like any other linter in Pants, for example:
./pants lint path/to/Dockerfile
Read more about the Docker backend and how to enable it in the Pants documentation .
An example
To give a feel for how it works, here is a basic example, from the documentation.
Consider these files:
files(
name="msg",
sources=["msg.txt"]
)
docker_image(
name="helloworld",
dependencies=[":msg", "src/python/helloworld:bin"],
)
FROM python:3.8
ENTRYPOINT ["/bin/helloworld"]
COPY src/docker/helloworld/msg.txt /var/msg
COPY src.python.helloworld/bin.pex /bin/helloworld
Hello, Docker!
python_library(interpreter_constraints=["=3.8"])
pex_binary(
name="bin",
entry_point="main.py",
)
import os
if os.path.exists("/var/msg"):
with open("/var/msg") as fp:
msg = fp.read().strip()
else:
msg = "Hello"
print(msg)
When you run package
on the Dockerfile:
$ ./pants package src/docker/helloworld/Dockerfile
[...]
18:07:29.66 [INFO] Completed: Building src.python.helloworld/bin.pex
18:07:31.83 [INFO] Completed: Building docker image helloworld:latest
18:07:31.83 [INFO] Built docker image: helloworld:latest
To try out the image interactively:
docker run -it --rm helloworld:latest [entrypoint args...]
To push your image:
docker push helloworld:latest
Pants sees that the docker_image
target depends on a pex_binary
target, so it builds the executable .pex
file first, and then builds the Docker image, placing that .pex
file (as well as the direct .txt
file dependency) in the build's context so that the COPY
instructions can see them.
You can check that the packaged image works as expected:
$ docker run -it --rm helloworld:latest
Hello, Docker!
This underscores the big advantage of letting Pants build your Docker images: It can automatically and incrementally build any artifacts that your image needs prior to assembling the context and building the Docker image. So with a single package
command you can ensure all your images are up to date, without having to worry about first handling upstream dependencies. Pants takes care of that for you!
In fact, in the 2.8.0 version Pants will have the ability to infer those upstream dependencies for you, by looking at the COPY statements in your Dockerfiles. So the explicit dependencies on the docker_image
target in the example above can be deleted. Keep an eye out for this and other great features in the next Pants release.
Background
As a software developer in the Tooling department at Svenska Spel, I am part of creating the infrastructure required to deliver our products into production, as safely, reliably and quickly as possible. To do this, we rely on many tools developed both in-house and by third parties, which we integrate into a complete CI/CD platform. A big part of this platform runs Python code, and almost all of it in Docker containers.
It was in search of better tooling to support our Python code base that I came across Pants, and was drawn in by the features and welcoming community. The lack of Docker support was an invitation for us to contribute something back.
Conclusion
As an experimental backend, it is still not feature complete, and is being actively worked upon. Please do not hesitate to reach out with your use case for Docker support in Pants. We want this to work for as many as possible.
We are really excited by all the possibilities we can realize using the Pants+Docker combo!