nickjj / docker-flask-example

A production ready example Flask app that's using Docker and Docker Compose.
MIT License
583 stars 101 forks source link

Frontend folder creation permissions issue #15

Closed c-mac closed 11 months ago

c-mac commented 11 months ago

Hi there, thanks for the wonderful project! When setting up and running the app locally, I'm getting an HTML page with no styles. It appears that none of the frontend public/ dirs are getting created.

I'm running on Pop_OS 22.04.

helloflask-css-1       | mkdir: cannot create directory '../public/css': Permission denied
helloflask-js-1        | mkdir: cannot create directory '../public/js': Permission denied

I am exporting linux ids in the env file as recommended:

export UID=1000
export GID=1000

I've also tried modifying the folder creation code in the Dockerfile as follows:

RUN mkdir -p /app/public \
  && chown node:node -R /app/public \
  && if [ "${NODE_ENV}" != "development" ]; then \
  ../run yarn:build:js && ../run yarn:build:css; fi

Since it seems to be a permissions error with the node user, I thought this might fix it but am unfortunately seeing the same error.

nickjj commented 11 months ago

Hi,

If you run the id command from your terminal do you get back 1000 for both your id and gid for your user?

c-mac commented 11 months ago

Yes:

uid=1000(cmac) gid=1000(cmac) groups=1000(cmac),4(adm),27(sudo),123(lpadmin)
nickjj commented 11 months ago

If you run ls -la in the root of the project what is the output? Is everything recursively owned by cmac:cmac?

I'm guessing maybe not since Docker isn't in the output of id, do you run Docker commands with sudo? You can fix that by running sudo groupadd docker and then re-logging into your X session (opening up a new terminal isn't enough) and verify Docker's group is attached to your user with id. Then you can run sudo chown -R cmac:cmac . in the root of your project to get files owned by your user.

Then if you run docker compose down && docker compose up you should be good to go.

c-mac commented 11 months ago

Yes, appears to be that way:

➜  helloflask git:(main) ✗ ls -la
total 140
drwxrwxr-x 12 cmac cmac  4096 Aug  1 14:21 .
drwxrwxr-x 12 cmac cmac  4096 Aug  1 11:30 ..
-rw-rw-r--  1 cmac cmac  1936 Aug  1 10:36 alembic.ini
drwxrwxr-x  5 cmac cmac  4096 Aug  1 10:36 assets
drwxrwxr-x  2 cmac cmac  4096 Aug  1 10:36 bin
-rw-rw-r--  1 cmac cmac 13327 Aug  1 10:36 CHANGELOG.md
drwxrwxr-x  2 cmac cmac  4096 Aug  1 14:26 config
drwxrwxr-x  3 cmac cmac  4096 Aug  1 10:36 db
-rw-rw-r--  1 cmac cmac  2511 Aug  1 10:36 docker-compose.yml
-rw-rw-r--  1 cmac cmac  2200 Aug  1 14:21 Dockerfile
-rw-rw-r--  1 cmac cmac   156 Aug  1 10:36 .dockerignore
-rw-rw-r--  1 cmac cmac  4857 Aug  1 10:48 .env
-rw-rw-r--  1 cmac cmac    36 Aug  1 10:36 .flake8
drwxrwxr-x  8 cmac cmac  4096 Aug  1 10:36 .git
drwxrwxr-x  4 cmac cmac  4096 Aug  1 10:36 .github
-rw-rw-r--  1 cmac cmac  2966 Aug  1 10:36 .gitignore
drwxrwxr-x  5 cmac cmac  4096 Aug  1 10:36 hello
drwxrwxr-x  2 cmac cmac  4096 Aug  1 10:36 lib
-rw-rw-r--  1 cmac cmac  1108 Aug  1 10:36 LICENSE
drwxrwxr-x  2 cmac cmac  4096 Aug  1 10:36 public
-rw-rw-r--  1 cmac cmac   104 Aug  1 10:36 pyproject.toml
-rw-rw-r--  1 cmac cmac 17802 Aug  1 10:36 README.md
-rw-rw-r--  1 cmac cmac   847 Aug  1 10:36 requirements-lock.txt
-rw-rw-r--  1 cmac cmac   355 Aug  1 10:36 requirements.txt
-rwxrwxr-x  1 cmac cmac  4243 Aug  1 10:36 run
drwxrwxr-x  3 cmac cmac  4096 Aug  1 10:36 test

I don't run docker commands with sudo. When running sudo groupadd docker, it says group 'docker' already exists.

When I do cat /etc/group I do see that:

Did the id get set incorrectly for docker, should it be 1000?

nickjj commented 11 months ago

Oh sorry, I meant to say to run sudo usermod -aG docker $USER, the first command only creates the group.

Docker being 999 is ok, it's a system level group. The files will still (or should be) still owned by cmac.

c-mac commented 11 months ago

My docker group is now as follows: docker:x:999:cmac

I blew away all the containers / volumes / images, restarted the computer, and unfortunately am still seeing the error despite this group and ls -la permissions looking OK.

I briefly tried moving the mkdir commands from out of the run scripts and into the Dockerfile, but then saw more permission issues with esbuild:

helloflask-js-1        | ✘ [ERROR] Failed to create output directory: mkdir /app/public/js: permission denied
helloflask-js-1        | 
helloflask-js-1        | ✘ [ERROR] Failed to create output directory: mkdir /app/public/js: permission denied
helloflask-js-1        | 
helloflask-js-1        | ✘ [ERROR] EACCES: permission denied, copyfile 'static/safari-pinned-tab.svg' -> '../public/safari-pinned-tab.svg' [plugin copy-static-files]
helloflask-js-1        | 
helloflask-js-1        |   This error came from the "onEnd" callback registered here:
helloflask-js-1        | 
helloflask-js-1        |     /node_modules/esbuild-copy-static-files/index.js:41:10:
helloflask-js-1        |       41 │     build.onEnd(() => fs.cpSync(src, dest, {
helloflask-js-1        |          ╵           ~~~~~
helloflask-js-1        | 
helloflask-js-1        |     at setup (/node_modules/esbuild-copy-static-files/index.js:41:11)
helloflask-js-1        |     at handlePlugins (/node_modules/esbuild/lib/main.js:1292:21)
helloflask-js-1        |     at buildOrContextImpl (/node_modules/esbuild/lib/main.js:978:5)
helloflask-js-1        |     at Object.buildOrContext (/node_modules/esbuild/lib/main.js:786:5)
helloflask-js-1        |     at /node_modules/esbuild/lib/main.js:2185:68
helloflask-js-1        |     at new Promise (<anonymous>)
helloflask-js-1        |     at Object.context (/node_modules/esbuild/lib/main.js:2185:27)
helloflask-js-1        |     at Module.context (/node_modules/esbuild/lib/main.js:2025:58)
helloflask-js-1        |     at file:///app/assets/esbuild.config.mjs:24:31
helloflask-js-1        | 
helloflask-js-1        | 3 errors
helloflask-css-1       | 
helloflask-css-1       | Rebuilding...
helloflask-css-1       | [Error: EACCES: permission denied, mkdir '../public/css'] {
helloflask-css-1       |   errno: -13,
helloflask-css-1       |   code: 'EACCES',
helloflask-css-1       |   syscall: 'mkdir',
helloflask-css-1       |   path: '../public/css'
helloflask-css-1       | }
nickjj commented 11 months ago

Who owns the public/js directory on your file system? Try running ls -la public.

Those mkdir commands only run inside of Docker btw, they are never executed directly on your host.

c-mac commented 11 months ago

public/js isn't getting created due to the mkdir commands failing.

Here's what public looks like:

➜  helloflask git:(main) ✗ ls -la public
total 8
drwxrwxr-x  2 cmac cmac 4096 Aug  1 10:36 .
drwxrwxr-x 12 cmac cmac 4096 Aug  1 16:26 ..
-rw-rw-r--  1 cmac cmac    0 Aug  1 10:36 .keep
nickjj commented 11 months ago

Ok, what if you run docker compose run web mkdir public/js. Does the directory get created or do you get the same permission error?

c-mac commented 11 months ago
➜  helloflask git:(main) ✗ docker compose run web mkdir public/js
[+] Creating 2/0
 ✔ Container helloflask-redis-1     Created                                                                                              0.0s 
 ✔ Container helloflask-postgres-1  Created                                                                                              0.0s 
[+] Running 2/2
 ✔ Container helloflask-postgres-1  Started                                                                                              0.3s 
 ✔ Container helloflask-redis-1     Started                                                                                              0.3s 
mkdir: cannot create directory ‘public/js’: Permission denied

Same error

nickjj commented 11 months ago

What does docker compose run web id return?

c-mac commented 11 months ago

uid=1000(python) gid=1000(python) groups=1000(python)

c-mac commented 11 months ago

Also ran these just to see:

➜  helloflask git:(main) ✗ docker compose run js id 
uid=1000(node) gid=1000(node) groups=1000(node)
➜  helloflask git:(main) ✗ docker compose run css id
uid=1000(node) gid=1000(node) groups=1000(node)
nickjj commented 11 months ago

Those outputs look good.

How did you install Docker on Linux? Was it through Docker Desktop or straight through Docker's installation for Ubuntu?

c-mac commented 11 months ago

I installed it via Docker Desktop

➜ helloflask git:(main) ✗ docker compose version Docker Compose version v2.19.1 ➜ helloflask git:(main) ✗ docker --version Docker version 24.0.5, build ced0996

https://docs.docker.com/engine/install/ubuntu/ Did the first four steps here, and then followed the Docker Desktop installation from the same site.

nickjj commented 11 months ago

If you installed Docker with Docker Desktop you don't need to follow any extra steps on https://docs.docker.com/engine/install/ubuntu/.

But I think I know what might be happening here. I know Docker Desktop on Linux has problems around file mounts and permissions. I've seen it add 100999:10099 permissions in the past and it resulted in permission errors. I wonder if something recently changed and now the file owner is labeled as correct but something else is still messed up.

You can confirm this by temporarily commenting out these volume lines from the docker-compose.yml file:

  volumes:
    - "${DOCKER_WEB_VOLUME:-./public:/app/public}"

  volumes:
    - ".:/app"

If you down and up the project, does it work then?

nickjj commented 11 months ago

If the above works I'd suggest completely removing all traces of Docker Desktop, opening a new terminal and then following https://docs.docker.com/engine/install/ubuntu/.

The TL;DR is you only need to run:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh

Then for good measure chown -R cmac:cmac in the root of the project and then build + up the project with the volume mounts in tact.

c-mac commented 11 months ago

Bingo! That did it, app is now running with styles.

Wow, thanks both for being a docker wizard and devoting so much time to this today!

nickjj commented 11 months ago

No problem. It's all working with volumes now too right?

Docker Desktop for Linux is still pretty new, there's a couple of rough edges. I'm sure it'll get fixed in due time.

c-mac commented 11 months ago

Yep, volumes are back in!