I have a docker image I’ve saved as a .tar using docker save
and I want to use it as a parent image FROM tarball_image.tar
inside a Dockerfile
without doing docker load
.
At deployment time, I only upload files to a Git Repo and an automated system that just takes a Dockerfile and builds the image based on the files in the repo. There’s no access to the docker engine nor can I do docker load
etc. The tarball image is managed with Git LFS
(although I can find the direct URL that points to the raw binary file). Additionally, the tarball image can’t be uploaded in a public repo/hub. I just have the Dockerfile and the tarball in the git repo and an automatic agent takes the Dockerfile and builds it.
Note that I do not have access to the docker
commands that are run to build the image so nothing can change there either.
2
Answers
The Dockerfile
ADD
directive has a couple of capabilities thatCOPY
doesn’t. Of note, it can unpack and uncompress tar files from the build context, without requiring any particular tools in the image. You can combine this with the specialscratch
image that contains absolutely nothing at all to produce an image that only contains the contents of your tar file.This is the same mechanism the various base images use; see for example the
debian
image Dockerfile.(You often don’t want
ADD
‘s extra behaviors; if youCOPY file.tar.gz ./
into your image, you expect the tar file and not to unpack it. Conventional wisdom is to preferCOPY
overADD
to avoid surprises. But here you do specifically want to unpack the tar file, andADD
is the right tool.)In a comment you clarify that the tar file isn’t actually in the build context but you need to fetch it. You can use a multi-stage build for this as another option. A first stage retrieves and unpacks the rootfs, using tools available in some normal image. You can then
COPY --from
an entire directory tree into the real image.There are a list of options, many of which aren’t available to you.
Typically, you would want to push the image to a registry, including free options like Docker Hub and GitHub’s ghcr.io. However, it sounds like you do not have the ability to do this.
The next best option, and the one that most closely matches your problem, is to pass an additional build context to buildx. And recent versions of the docker engine will include the OCI Layout files (
oci-layout
andindex.json
) in thedocker save
output, making this option even easier.Which you could then reference as
foo
in the Dockerfile:Details on using additional contexts are available at: https://docs.docker.com/reference/cli/docker/buildx/build/#source-oci-layout
However, since you do not control the build command line, I don’t believe this option is available to you either.
Without either of the above, and since it appears you can control the tar output, you’ll want to use a
docker export
instead ofdocker save
for generating the tar.If the content was in a registry, you could also use Google’s crane tool to perform a
crane export $image export.tar
. For details, see the crane documentation.With that tar file, the easiest way to use it would be if the file was available in your build context so that you can add it like:
If you need to pull the tar from an external URL, then I’d still recommend using ADD to pull the tar for better cache management (Docker will perform a conditional fetch of the tar, and use the cache if it has already seen the tar file):
If you didn’t have control of the tar file, and needed to import directly from the
docker save
output, then I’d look at building a tool for the task. The OCI image-spec documents the OCI Layout structure, the Index for parsing the index.json and potentially a nested index manifest, the Manifest for parsing the image specific manifest, and the Layer details including how change sets and whiteouts are applied. You would then run that tooling as the first stage of the build, to generate the/export
directory as before, and then use it in a later stage.