kaniko: USER command should not require user or group IDs to exist

It is common for a Dockerfile to contain a USER directive of the form USER 1000:1000. docker build does not require a user and group with those ids to exist, nor does it create them. However, Kaniko errors.

Interestingly, while creating a minimal dockerfile to demonstrate this I discovered that Kaniko errors in two different ways:

Working example using Docker:

$ cat usertest1
FROM alpine
USER 1000:1000
CMD ["whoami"]
$ docker build --file usertest1 -t usertest:1 .
Sending build context to Docker daemon  23.46MB
Step 1/3 : FROM alpine
 ---> 196d12cf6ab1
Step 2/3 : USER 1000:1000
 ---> Using cache
 ---> 4794c572f720
Step 3/3 : CMD ["whoami"]
 ---> Using cache
 ---> 6ab640ab2641
Successfully built 6ab640ab2641
Successfully tagged usertest:1
$ docker run --rm usertest:1
whoami: unknown uid 1000

Kaniko failure mode 1

$ cat usertest1
FROM alpine
USER 1000:1000
CMD ["whoami"]

$ docker run --rm -it -v $PWD:/workspace gcr.io/kaniko-project/executor:latest --dockerfile=usertest1 --no-push --context=dir:///workspace
INFO[0000] Downloading base image alpine                
2018/12/04 13:25:52 No matching credentials were found, falling back on anonymous
INFO[0001] Taking snapshot of full filesystem...        
INFO[0001] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0001] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0001] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0001] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0001] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0001] USER 1000:1000                               
INFO[0001] cmd: USER                                    
error building image: error building stage: open /etc/passwd: no such file or directory

Kaniko failure mode 2: Note the addition of the RUN directive and the different error message from Kaniko

$ cat usertest2
FROM alpine
RUN test 0
USER 1000:1000
CMD ["whoami"]

$ docker run --rm -it -v $PWD:/workspace gcr.io/kaniko-project/executor:latest --dockerfile=usertest2 --no-push --context=dir:///workspace
INFO[0000] Downloading base image alpine                
2018/12/04 13:32:00 No matching credentials were found, falling back on anonymous
INFO[0001] Unpacking rootfs as cmd RUN test 0 requires it. 
INFO[0001] Taking snapshot of full filesystem...        
INFO[0001] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0001] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0001] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0001] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0001] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0001] RUN test 0                                   
INFO[0001] cmd: /bin/sh                                 
INFO[0001] args: [-c test 0]                            
INFO[0001] Taking snapshot of full filesystem...        
INFO[0001] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0001] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0001] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0001] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0001] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0001] No files were changed, appending empty layer to config. No layer added to image. 
INFO[0001] USER 1000:1000                               
INFO[0001] cmd: USER                                    
error building image: error building stage: user: unknown userid 1000

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 15
  • Comments: 30 (3 by maintainers)

Commits related to this issue

Most upvoted comments

based on what this issue is closed? this is critical issue for compatibility concern

It looks like this is also an issue when using --cache=true: When reaching a USER statement on a cached layer that is not available locally, it fails:

INFO[0000] Downloading base image openjdk:11            
2018/12/13 10:41:49 No matching credentials were found, falling back on anonymous
WARN[0001] Error while retrieving image from cache: getting image from path: open /cache/sha256:c7381bfd53670f1211314885b03b98f5e13fddf6958afeec61092b07c56ddef1: no such file or directory 
2018/12/13 10:41:50 No matching credentials were found, falling back on anonymous
INFO[0002] Executing 0 build triggers                   
INFO[0002] Checking for cached layer docker.company.io/project/cache:3bee254e641f46abcfa0822e3d1600938df2905e0aadba41756a7c6884cbd16d... 
INFO[0002] Using caching version of cmd: RUN groupadd -r $APPLICATION_USER && useradd --no-log-init -r -g $APPLICATION_USER $APPLICATION_USER 
INFO[0002] Checking for cached layer docker.company.io/project/cache:a1875d7dd74f1d18a37dab3e6e75f2f3f08cc58f1ded0d6d92e35647883c0686... 
INFO[0002] Using caching version of cmd: RUN mkdir /app 
INFO[0002] Checking for cached layer docker.company.io/project/cache:b9fafa07e45363ebd9db5304781b7536e15ad7bf028cdd60867fc55151c3cb4f... 
error building image: error building stage: open /etc/passwd: no such file or directory
INFO[0002] Using caching version of cmd: RUN chown -R $APPLICATION_USER /app 
INFO[0002] cmd: USER                                    

Happens for us as well and stops us from using Kaniko.

Any update on this?

For me, a USER command in a cached layer will produce the already mentioned error message. Is there some kind of workaround for this?

Anyone been able to work around this?

Using gcr.io/kaniko-project/executor:debug allowed me to workaround this issue

When using executor:latest

INFO[0000] USER 10400:10400
INFO[0000] cmd: USER
error building image: error building stage: open /etc/passwd: no such file or directory

When using executor:debug

INFO[0002] Taking snapshot of full filesystem...
INFO[0002] USER 10400:10400
INFO[0002] cmd: USER
2019/04/28 07:34:31 existing blob: sha256:67ddbfb20a22d7c0ea0df56

Suffering from this as well on gcr.io/kaniko-project/executor:debug-v0.9.0 :

INFO[0000] cmd: USER                                    
error building image: error building stage: open /etc/passwd: no such file or directory

With the latest version:

error building image: error building stage: user: invalid userid <username>

I think it’s just this line https://github.com/GoogleContainerTools/kaniko/blob/b0b36ed85a9a85ffb1b2075622be3c4cd7111a82/pkg/util/command_util.go#L309 that calls os.user.LookupId which results in trying to read from /etc/passwd and similarly https://github.com/GoogleContainerTools/kaniko/blob/b0b36ed85a9a85ffb1b2075622be3c4cd7111a82/pkg/util/command_util.go#L309 does this for the group id.

Since all the code does is gets a User object and then returns the UID (which would match the userStr that we looked up in the first place) I feel like the correct behavior would be something like:

  1. If userStr is numeric, just use that as a userId (optionally try user.LookupId(userStr) and log a warning or something if the userid isn’t found?)
  2. If it is not numeric string try looking up userStr with user.Lookup, and if it is not found then return an error does that seem like it would give consistent behavior?

edit: playing around with this a little bit one issue seems to be that environment variables like HOME won’t be set automatically if you use a numeric userid but that can be worked around if needed.

Any news ?

Nope.

If anybody reading this is interested in digging into this and submitting a fix I’ll be happy to review it.

@hrobertson, i tried reproducing error cases Failure 1 and failure 2. I don’t see this error anymore for gcr.io/kaniko-project/executor:latest

tejaldesai@ $ kubectl logs kaniko -f
INFO[0000] Resolved base name alpine to alpine          
INFO[0000] Resolved base name alpine to alpine          
INFO[0000] Downloading base image alpine                
ERROR: logging before flag.Parse: E0809 05:31:37.759262       1 metadata.go:142] while reading 'google-dockercfg' metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg
ERROR: logging before flag.Parse: E0809 05:31:37.764295       1 metadata.go:159] while reading 'google-dockercfg-url' metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg-url
2019/08/09 05:31:37 No matching credentials were found, falling back on anonymous
INFO[0000] Error while retrieving image from cache: getting file info: stat /cache/sha256:57334c50959f26ce1ee025d08f136c2292c128f84e7b229d1b0da5dac89e9866: no such file or directory 
INFO[0000] Downloading base image alpine                
2019/08/09 05:31:38 No matching credentials were found, falling back on anonymous
INFO[0001] Built cross stage deps: map[]                
INFO[0001] Downloading base image alpine                
2019/08/09 05:31:38 No matching credentials were found, falling back on anonymous
INFO[0001] Error while retrieving image from cache: getting file info: stat /cache/sha256:57334c50959f26ce1ee025d08f136c2292c128f84e7b229d1b0da5dac89e9866: no such file or directory 
INFO[0001] Downloading base image alpine                
2019/08/09 05:31:39 No matching credentials were found, falling back on anonymous
INFO[0002] Unpacking rootfs as cmd RUN test 0 requires it. 
INFO[0002] Taking snapshot of full filesystem...        
INFO[0002] RUN test 0                                   
INFO[0002] cmd: /bin/sh                                 
INFO[0002] args: [-c test 0]                            
INFO[0002] Taking snapshot of full filesystem...        
INFO[0002] No files were changed, appending empty layer to config. No layer added to image. 
INFO[0002] USER 1000:1000                               
INFO[0002] cmd: USER                                    
INFO[0002] CMD ["whoami"]                               
2019/08/09 05:31:40 existing blob: sha256:0503825856099e6adb39c8297af09547f69684b7016b7f3680ed801aa310baaa
2019/08/09 05:31:41 pushed blob: sha256:09baf2d94f9afe6148bb4203991a5329ea4362c47c6c4e4f5a206e20791633e5
2019/08/09 05:31:42 gcr.io/tejal-test/test:latest: digest: sha256:5e7d175de7068f4276facbb0ab8ad18621df81790411af2a88e380fb01fe72d2 size: 428
tejaldesai@ $

Using gcr.io/kaniko-project/executor:debug allowed me to get past this issue when running both locally and on Cloud Build. Shasum: 5a6b3193506212ea7703214bf3b21cd898e5e2ec14d6b988cc9d11a9b34f32d4

same as @mamoit building first without USER & cache enabled and then using USER will trigger this

I have done some further investigation and the behaviour is even more erroneous than I first thought!

Here I build three images containing the kaniko executor binary. One pulls the binary into a scratch base, the next into an alpine base, and the next creates a user within the image.

$ cat Dockerfile
FROM gcr.io/kaniko-project/executor:latest as kaniko

FROM scratch as scratch
COPY --from=kaniko /kaniko/executor /kaniko/executor
COPY --from=kaniko /kaniko/ssl/certs/ca-certificates.crt /kaniko/ssl/certs/
ENV SSL_CERT_DIR=/kaniko/ssl/certs
WORKDIR /workspace

ENTRYPOINT ["/kaniko/executor"]

FROM alpine as alpine
COPY --from=kaniko /kaniko/executor /kaniko/executor
COPY --from=kaniko /kaniko/ssl/certs/ca-certificates.crt /kaniko/ssl/certs/
ENV SSL_CERT_DIR=/kaniko/ssl/certs
WORKDIR /workspace

ENTRYPOINT ["/kaniko/executor"]

FROM alpine as alpine-with-user
RUN addgroup -g 1000 test && adduser -D -u 1000 -G test test

I build the three separate images:

$ docker build -t kaniko:scratch --target scratch .
$ docker build -t kaniko:alpine --target alpine .
$ docker build -t kaniko:alpine-with-user --target alpine-with-user .

And here I build the usertest3 image using kaniko inside each of those images.

$ cat usertest3
FROM scratch
USER 1000:1000
CMD ["whoami"]

kaniko binary in scratch

$ docker run --rm -it -v $PWD:/workspace --entrypoint=/kaniko/executor kaniko:scratch --dockerfile=usertest3 --context=dir:///workspace --no-push
INFO[0000] No base image, nothing to extract            
INFO[0000] Taking snapshot of full filesystem...        
INFO[0000] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0000] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0000] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0000] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0000] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0000] USER 1000:1000                               
INFO[0000] cmd: USER                                    
error building image: error building stage: open /etc/passwd: no such file or directory

kaniko binary in alpine

$ docker run --rm -it -v $PWD/test:/workspace --entrypoint=/kaniko/executor kaniko:alpine --dockerfile=usertest3 --context=dir:///workspace --no-push 
INFO[0000] No base image, nothing to extract            
INFO[0000] Taking snapshot of full filesystem...        
INFO[0000] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0000] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0000] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0000] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0000] Skipping paths under /var/run, as it is a whitelisted directory 
INFO[0000] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0000] USER 1000:1000                               
INFO[0000] cmd: USER                                    
error building image: error building stage: user: unknown userid 1000

As you can see, kaniko is erroneously looking for the /etc/passwd file in the environment in which kaniko is running, not the filesystem of the image it’s building! Note it shouldn’t even look for a passwd file at all when IDs are specified rather than names.

kaniko binary in alpine with an existing user: Note this user does not exist in the image kaniko is building, but in the environment in which kaniko itself is running.

$ docker run -it --rm -v $PWD:/workspace kaniko:alpine-with-user --dockerfile=usertest3 --context=dir:///workspace --no-push
INFO[0000] Downloading base image alpine                
2018/12/05 13:32:25 Unable to read "/root/.docker/config.json": open /root/.docker/config.json: no such file or directory
2018/12/05 13:32:25 No matching credentials were found, falling back on anonymous
INFO[0001] Taking snapshot of full filesystem...        
INFO[0001] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0001] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0001] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0001] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0001] Skipping paths under /var/run, as it is a whitelisted directory 
INFO[0001] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0001] USER 1000:1000                               
INFO[0001] cmd: USER                                    
INFO[0001] CMD ["whoami"]                               
INFO[0001] Skipping push to container registry due to --no-push flag

Until the first RUN directive causes Unpacking rootfs , kaniko is using the filesystem of the environment that Kaniko is in rather than that of the base image. As you can see below, using kaniko in the kaniko:alpine-with-user image to build the usertest2 dockerfile (see the initial post), again fails to find the user. Contrast this with the above output building the usertest3 dockerfile.

$ docker run -it --rm -v $PWD:/workspace kaniko:alpine-with-user --dockerfile=usertest2 --context=dir:///workspace --no-push
INFO[0000] Downloading base image alpine                
2018/12/05 19:12:18 No matching credentials were found, falling back on anonymous
INFO[0001] Unpacking rootfs as cmd RUN test 0 requires it. 
INFO[0001] Taking snapshot of full filesystem...        
INFO[0001] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0001] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0001] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0001] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0001] Skipping paths under /var/run, as it is a whitelisted directory 
INFO[0001] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0002] RUN test 0                                   
INFO[0002] cmd: /bin/sh                                 
INFO[0002] args: [-c test 0]                            
INFO[0002] Taking snapshot of full filesystem...        
INFO[0002] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0002] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0002] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0002] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0002] Skipping paths under /var/run, as it is a whitelisted directory 
INFO[0002] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0002] No files were changed, appending empty layer to config. No layer added to image. 
INFO[0002] USER 1000:1000                               
INFO[0002] cmd: USER                                    
error building image: error building stage: user: unknown userid 1000