canonical / docker-snap

https://snapcraft.io/docker
MIT License
52 stars 27 forks source link

`docker build` fails with `unable to evaluate symlinks in Dockerfile path` #34

Open Hi-Angel opened 3 years ago

Hi-Angel commented 3 years ago

Plain docker build doesn't work with docker installed from snap. See also: https://github.com/thenativeweb/wolkenkit/issues/54

This is packaging bug, because installing docker with apt from this repo has no problem.

Steps to reproduce (in terms of terminal commands)

$ cat Dockerfile
FROM docker.io/library/ubuntu:bionic
RUN echo hello
$ docker build -t test .
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /var/lib/snapd/void/Dockerfile: no such file or directory

Expected

The commands succeeds

Actual

The command failed

Additional information

Output of snap info docker:

``` name: docker summary: Docker container runtime publisher: Canonical✓ store-url: https://snapcraft.io/docker contact: https://github.com/docker-snap/docker-snap/issues?q= license: (Apache-2.0 AND MIT AND GPL-2.0) description: | Build and run container images with Docker. **Usage** * This build can only access files in the home directory. So Dockerfiles and all other files used in commands like `docker build`, `docker save` and `docker load` need to be in $HOME. * You can change the configuration of this build by modifying the files in `/var/snap/docker/current/`. * Additional certificates used by the Docker daemon to authenticate with registries need to be added in `/var/snap/docker/common/etc/certs.d` (instead of `/etc/docker/certs.d`). **Running Docker as normal user** By default, Docker is only accessible with root privileges (`sudo`). If you want to use docker as a regular user, you need to add your user to the `docker` group. sudo addgroup --system docker sudo adduser $USER docker newgrp docker sudo snap disable docker sudo snap enable docker **Warning:** if you add your user to the `docker` group, it will have similar power as the `root` user. For details on how this impacts security in your system, see https://docs.docker.com/engine/security/#docker-daemon-attack-surface **Authors** This snap is built by Canonical based on source code published by Docker, Inc. It is not endorsed or published by Docker, Inc. Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries. Docker, Inc. and other parties may also have trademark rights in other terms used herein. commands: - docker.compose - docker - docker.help - docker.machine services: docker.dockerd: simple, enabled, active snap-id: sLCsFAO8PKM5Z0fAKNszUOX0YASjQfeZ tracking: latest/stable refresh-date: today at 12:59 MSK channels: latest/stable: 19.03.13 2021-02-12 (796) 137MB - latest/candidate: 19.03.13 2021-02-10 (796) 137MB - latest/beta: 19.03.13 2021-02-05 (796) 137MB - latest/edge: 19.03.15 2021-04-01 (860) 138MB - 17.03/stable: 17.03.2-ce-1 2017-07-20 (159) 42MB - 17.03/candidate: 17.03.2-ce-1 2017-06-30 (159) 42MB - 17.03/beta: ↑ 17.03/edge: 17.03.2-ce-1 2017-06-30 (159) 42MB - installed: 19.03.13 (796) 137MB - ```
anonymouse64 commented 3 years ago

What is the current directory you are building from when you run docker build . ?

Hi-Angel commented 3 years ago

What is the current directory you are building from when you run docker build . ?

It was /tmp/bar (basically an arbitrary directory inside /tmp/)

anonymouse64 commented 3 years ago

Strictly confined snaps like docker do not have access to /tmp from the host, /tmp/bar inside the docker snap will end up resolving to somewhere like /tmp/snap.docker/bar. It should work if you use a different directory like /home.

Hi-Angel commented 3 years ago

Strictly confined snaps like docker do not have access to /tmp from the host, /tmp/bar inside the docker snap will end up resolving to somewhere like /tmp/snap.docker/bar. It should work if you use a different directory like /home.

Right, seems to work from home directory…

Okay, so, /tmp/ is a popular location for, well, temporary stuff, and I don't really understand why would you restrict an application from accessing this specific directory. But then again, I'm not a maintainer, probably there is some reason. I think however, there should at least be an error explaining the problem, or some other means of communication to the user. Like, I don't know, big red warning upon installation that this version won't work by default with your /tmp/ directory.

Because right now all users see is that snap version of docker has some odd problems with symlinks (because the error says something about symlinks), which is not present on non-snap version. If it's a feature of the snap version, its presence should be made clear to the users.

anonymouse64 commented 3 years ago

It's a security feature of snaps, many applications store sensitive data in /tmp, many even unintentionally, and as such to protect users from having secrets or other data leaking from one snap application to another (or from something in the host to a malicious snap), each snap gets it's own /tmp.

AFAIK, it's not feasible to change the internals of docker to surface this error better, but perhaps we could call it out in the snap description that it will only work to build images from somewhere in /home, and not from somewhere in /tmp.

Fuseteam commented 3 years ago

would perhaps an interface that users can connect to /tmp be an idea? i kinda like to keep my source code out of my home directory to the point that i chown'ed /usr/local/src to be owned by my user......

bugslifesolutions commented 2 years ago

Thank you @anonymouse64 for highlighting the snaps security feature. Thought I'd share my scenario, as it is yet another practical example of a need to use a non /home directory, yet not the same as using a /tmp mount path.

I ran out of disk space (inodes ext4) in the root mounted volume /, so moved the application from home/me/gitrepo/example to a another XFS mounted volume /data in directory /data/gitrepo/example.

Using /data path

Error report (as me):

me@talosctl-1:/data/gitrepo/example$ docker build .
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /var/lib/snapd/void/Dockerfile: no such file or directory
me@talosctl-1:/data/gitrepo/example$

Error report (as root):

root@talosctl-1:/data/gitrepo/example# docker build .
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /var/lib/snapd/void/Dockerfile: no such file or directory
root@talosctl-1:/data/gitrepo/example# exit
exit

Context:

root@talosctl-1:/data/gitrepo/example# snap services docker
Service         Startup  Current  Notes
docker.dockerd  enabled  active   -
root@talosctl-1:/data/gitrepo/example# ll Docker
DockerBuildAndPush.sh  Dockerfile             
root@talosctl-1:/data/gitrepo/example# ll Dockerfile
-rw-rw-r-- 1 me me 1969 Dec 20 06:50 Dockerfile
root@talosctl-1:/data/gitrepo/example# ps aux|grep dockerd
root         835  0.1  3.9 2385524 81004 ?       Ssl  13:36   0:04 dockerd --group docker --exec-root=/run/snap.docker --data-root=/var/snap/docker/common/var-lib-docker --pidfile=/run/snap.docker/docker.pid --config-file=/var/snap/docker/1524/config/daemon.json

Using /home path

Success result !

me@talosctl-1:/data/gitrepo$ cp -R example/ /home/me
me@talosctl-1:/data/gitrepo$ cd /home/me/example
me@talosctl-1:~/example$ docker build .
Sending build context to Docker daemon  9.657MB
Step 1/32 : FROM node:12-alpine as npm-package-fetcher
...
...
anonymouse64 commented 2 years ago

@bugslifesolutions the issue you are seeing is that dockerd is not permitted to read /data. If you bind mounted /data/ somewhere inside /home/me/... then the command would work. Bind mounting is the preferred way to support directories outside of /home for strictly confined snaps.

bradraj commented 1 year ago

Adding a bind mount solved the issue. mount --bind /nonstandard_mountpoint /media/$USER/directory

Reference page: https://askubuntu.com/questions/1033344/how-to-give-snaps-access-to-somedir

firesh commented 1 year ago

My Solution:

snap remove docker
apt install docker.io