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.
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 ::
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 .
To give a feel for how it works, here is a basic example, from the documentation.
Consider these files:
# src/docker/helloworld/BUILD files( name="msg", sources=["msg.txt"] ) docker_image( name="helloworld", dependencies=[":msg", "src/python/helloworld:bin"], )
# src/docker/helloworld/Dockerfile FROM python:3.8 ENTRYPOINT ["/bin/helloworld"] COPY src/docker/helloworld/msg.txt /var/msg COPY src.python.helloworld/bin.pex /bin/helloworld
# src/docker/helloworld/msg.txt Hello, Docker!
# src/python/helloworld/BUILD python_library(interpreter_constraints=["=3.8"]) pex_binary( name="bin", entry_point="main.py", )
# src/python/helloworld/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.
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.
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!