docker / cli

The Docker CLI
Apache License 2.0
4.83k stars 1.9k forks source link

Make content trust play nicely with multi-stage builds and "FROM $ARG" #933

Open thaJeztah opened 6 years ago

thaJeztah commented 6 years ago

Docker Content Trust currently parses Dockerfiles client-side to resolve the image-digest for all images that are used.

However, with the addition of multi-stage builds, and dynamically changing the Dockerfile (FROM $ARG), resolving the image is not always possible without evaluating the Dockerfile.

Some examples:

Dockerfile with FROM $ARG

DOCKER_CONTENT_TRUST=1 docker image build -<<'EOF'
ARG HELLOWORLD=busybox:latest
FROM $HELLOWORLD
RUN echo "foo"
EOF

Which produces:

Sending build context to Docker daemon 

error during connect: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.37/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&session=517905e9f0e6436308357abb85be2348e8b42a39c5fbd3f9d32085a85af133fa&shmsize=0&target=&ulimits=null: invalid reference format: repository name must be lowercase

error is:

invalid reference format: repository name must be lowercase

Dockerfile using names of build-stages

Another case is multi-stage builds:

When using FROM <something> in a multi-stage build, <something> can be ambiguous (if the Dockerfile is not processed correctly):

Docker content trust will attempt to resolve digests for image names, so in the example below:

Without DCT, FROM helloworld is treated as the name of the first build-stage:

docker image build -t foo:notrust -<<'EOF'
FROM busybox AS helloworld
RUN touch /stage.one

FROM helloworld
RUN touch /stage.two
CMD ls -la /stage.*
EOF
docker run --rm foo:notrust
-rw-r--r--    1 root     root             0 Mar  9 10:39 /stage.one
-rw-r--r--    1 root     root             0 Mar  9 10:39 /stage.two

But with DCT enabled, the Dockerfile is parsed first, and the client will likely attempt to resolve the digest for helloworld:latest:

DOCKER_CONTENT_TRUST=1 docker image build -t foo:trust -<<'EOF'
FROM busybox AS helloworld
RUN touch /stage.one

FROM helloworld
RUN touch /stage.two
CMD ls -la /stage.*
EOF

Which results in some obscure error:

Sending build context to Docker daemon 

error during connect: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.37/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&session=c5cbe3de2fd22ff77602f8c1898b7efa575cd21ae3f91bdf0d0622b814d77127&shmsize=0&t=foo%3Atrust&target=&ulimits=null: you are not authorized to perform this operation: server returned 401.

Error:

you are not authorized to perform this operation: server returned 401.

What's needed

We should:

/cc @gbarr01 for docs

thaJeztah commented 6 years ago

/cc @n4ss @vdemeester @endophage

tonistiigi commented 6 years ago

https://github.com/moby/buildkit/issues/4255 https://github.com/moby/buildkit/issues/4255

ahh-docker commented 5 years ago

@tonistiigi Is this still something we need to document? Let me know, and I'll update the docs accordingly. Thanks!

tonistiigi commented 5 years ago

The server side validation is now in docker-ee and is a better approach for this.