skip to Main Content

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


  1. The Dockerfile ADD directive has a couple of capabilities that COPY 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 special scratch image that contains absolutely nothing at all to produce an image that only contains the contents of your tar file.

    FROM scratch
    ADD tarball_image.tar /
    

    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 you COPY file.tar.gz ./ into your image, you expect the tar file and not to unpack it. Conventional wisdom is to prefer COPY over ADD to avoid surprises. But here you do specifically want to unpack the tar file, and ADD 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.

    FROM busybox AS rootfs
    RUN wget -O /rootfs.tar.gz http://.../rootfs.tar.gz
    WORKDIR /rootfs
    RUN tar xzf /rootfs.tar.gz
    
    FROM scratch
    COPY --from=rootfs /rootfs/ /
    
    Login or Signup to reply.
  2. 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 and index.json) in the docker save output, making this option even easier.

    docker buildx build --build-context foo=oci-layout:///path/to/local/layout:<tag> ...
    

    Which you could then reference as foo in the Dockerfile:

    FROM foo
    ...
    

    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 of docker save for generating the tar.

    docker create --name container-to-export $image
    docker export container-to-export >export.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:

    FROM scratch
    ADD export.tar /
    

    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):

    FROM busybox as export
    ADD http://$url/export.tar /export.tar
    RUN mkdir /export && tar -xvf /export.tar -C /export
    
    FROM scratch
    COPY --from=export /export /
    # ...
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search