|
| 1 | +# Container Troubleshooting: File Permissions issues |
| 2 | + |
| 3 | +This demo uses a fake web app called **Firebox** (sorry, Dropbox!) that allows you to upload files. The web app is written in Python using the Flask framework and runs in a Docker container. |
| 4 | + |
| 5 | +## To run |
| 6 | + |
| 7 | +```shell |
| 8 | +docker build -t file-permissions . |
| 9 | + |
| 10 | +docker run -p 5000:5000 file-permissions |
| 11 | +``` |
| 12 | + |
| 13 | +Now access the web app in your web browser: <http://localhost:5000> and try to upload a file. |
| 14 | + |
| 15 | +**You'll see that the file upload fails. But why?** |
| 16 | + |
| 17 | +### To debug |
| 18 | + |
| 19 | +To debug, we'll need to get the ID of the container. Run `docker ps` to get the container ID: |
| 20 | + |
| 21 | +```shell |
| 22 | +docker ps |
| 23 | +``` |
| 24 | + |
| 25 | +Look for the container that has the image `file-permissions` and copy the container ID. |
| 26 | + |
| 27 | +**Look at the logs.** First let's check out the logs: |
| 28 | + |
| 29 | +```shell |
| 30 | +docker logs <container-id> |
| 31 | +``` |
| 32 | + |
| 33 | +We see something like this: |
| 34 | + |
| 35 | +> 10.0.2.100 - - [10/Dec/2022 16:10:31] "POST /upload HTTP/1.1" 500 - |
| 36 | +> ... |
| 37 | +> PermissionError: [Errno 13] Permission denied: '/app/uploads/5sdfkhfweiohj.jpeg' |
| 38 | +
|
| 39 | +Oh no! |
| 40 | + |
| 41 | +**Look at the folder inside the container.** Perhaps the folder inside the container will give us some clues. Start a shell inside the container and see what's going on. |
| 42 | + |
| 43 | +```shell |
| 44 | +docker exec -it <container-id> sh |
| 45 | +``` |
| 46 | + |
| 47 | +Once inside the container, list the contents of the `/app/uploads` folder. Add the `-a` flag to show hidden files and folders and `-l` to show the permissions: |
| 48 | + |
| 49 | +```shell |
| 50 | +/ $ ls -al /app/uploads |
| 51 | +total 0 |
| 52 | +drwxr-xr-x 1 root root 0 Dec 10 16:09 . |
| 53 | +drwxr-xr-x 1 root root 18 Dec 10 16:10 .. |
| 54 | +``` |
| 55 | + |
| 56 | +The folder is empty! A-ha! But notice that the permissions are `drwxr-xr-x`, with the owner `root`. This means that the folder is owned by the `root` user, and that the `root` user has read, write, and execute permissions. |
| 57 | + |
| 58 | +**Check: is our app running as root in the container?** Let's check the user that we're running as. Staying inside the shell in the container, run this command: |
| 59 | + |
| 60 | +```bash |
| 61 | +/ $ whoami |
| 62 | +filebox |
| 63 | +``` |
| 64 | + |
| 65 | +So we're not running as `root`. But we are running as the `filebox` user. Let's check the permissions of the `filebox` user: |
| 66 | + |
| 67 | +```bash |
| 68 | +/ $ id filebox |
| 69 | +uid=100(filebox) gid=101(apps) groups=101(apps),101(apps) |
| 70 | +``` |
| 71 | + |
| 72 | +The `filebox` user has a UID of 1000 and is in the `apps` group. It's not `root`. |
| 73 | + |
| 74 | +Since the `uploads` folder is owned by the `root` user, the `filebox` user does not have permission to write to the folder. |
| 75 | + |
| 76 | +### To fix |
| 77 | + |
| 78 | +We can't just change the permissions of the folder inside the container while it's running, because the permissions will be reset when the container is restarted. We need to change the permissions of the folder every time the container starts. |
| 79 | + |
| 80 | +**Change the permissions of the folder in the Dockerfile.** Let's change the permissions of the `uploads` folder by editing the _Dockerfile_. Replace the line that says `RUN mkdir -p /app/uploads` with this: |
| 81 | + |
| 82 | +```dockerfile |
| 83 | +RUN mkdir -p /app/uploads && chown -R filebox:apps /app/uploads |
| 84 | +``` |
| 85 | + |
| 86 | +**Terminate and rebuild.** Now let's rebuild the image and run the container again. Press Ctrl+C to exit the container, then stop the container: |
| 87 | + |
| 88 | +```bash |
| 89 | +docker stop <container-id> |
| 90 | +``` |
| 91 | + |
| 92 | +Then rebuild the image and run the container again: |
| 93 | + |
| 94 | +```bash |
| 95 | +docker build -t file-permissions . |
| 96 | + |
| 97 | +docker run -p 5000:5000 file-permissions |
| 98 | +``` |
| 99 | + |
| 100 | +Now try to upload a file again at <http://localhost:5000> |
| 101 | + |
| 102 | +**Success!** |
| 103 | + |
| 104 | +**Confirm the file was saved.** Let's start a shell inside the container and find the file in the `/app/uploads` folder. (Don't forget that you can get the container ID by running `docker ps`). |
| 105 | + |
| 106 | +```bash |
| 107 | +docker exec -it <container-id> /bin/bash |
| 108 | +``` |
| 109 | + |
| 110 | +```bash |
| 111 | +/ $ ls -al /app/uploads/ |
| 112 | +drwxr-xr-x 1 filebox apps 82 Dec 10 16:32 . |
| 113 | +drwxr-xr-x 1 root root 14 Dec 10 16:31 .. |
| 114 | +-rw-r--r-- 1 filebox apps 2036567 Dec 10 16:32 henlobird.jpeg |
| 115 | +``` |
| 116 | + |
| 117 | +## Wrapping up |
| 118 | + |
| 119 | +In this demo, we saw how to debug a file permissions issue in a container. |
| 120 | + |
| 121 | +We saw that the problem was that the app was trying to write to a folder that was owned by the `root` user, and that the app's user (`filebox`) didn't have permission to write to the folder. We fixed the problem by changing the permissions of the folder in the _Dockerfile_. |
| 122 | + |
| 123 | +It's good security practice to run your container as a non-root user. But if you do, you can encounter some annoying permissions issues! So it's important to know how to debug these issues. |
| 124 | + |
| 125 | + |
0 commit comments