nickjj / docker-django-example

A production ready example Django app that's using Docker and Docker Compose.
MIT License
1.22k stars 265 forks source link

Update README.md about need to "chown 1000 ./public*" #18

Closed westbywest closed 2 years ago

westbywest commented 2 years ago

The error in #9 occurs under Ubuntu 20, and likely similar platforms enforcing non-root write privileges for the active user, due to hardcoded uid 1000 in the container images pulled during build. This explains build errors like these:

hellodjango-js-1        | mkdir: cannot create directory '../public/js': Permission denied
hellodjango-js-1        | 
hellodjango-js-1        | Task completed in 0m0.001s
hellodjango-css-1       | mkdir: cannot create directory '../public/css': Permission denied
hellodjango-css-1       | 
hellodjango-css-1       | Task completed in 0m0.001s

Resolution is to chown ./public* prior to first build with docker-compose. Likely have to do with sudo if the active user doesn't have root privileges.

$ sudo chown 1000 {public,public_collected}
nickjj commented 2 years ago

Hi,

The containers run as a non-root user and Docker by default will bind mount files as uid/gid 1000:1000 when you set USER xxx in your Dockerfile with no other details.

Is your user not 1000? You can check by running id from your Docker host. I do run native Linux and have deployed this app on many Linux systems without issues on various VPSs since the first user you create on a Linux system will be 1000:1000 by default. No using of sudo should be needed.

westbywest commented 2 years ago

The active user running docker-compose having uid 1000 won't be guaranteed. Mine is 1001 due to presence of other local users, and similar for systems with centralized user management like via LDAP. For an active user with uid != 1000 to chown something to that id, sudo is required.

Recommendation is to add mention of default uid.gid = 1000:1000 to the README, and Linux users with different ids need to update Dockerfile with USER xxx or chown 1000 {public,public_collected}.

nickjj commented 2 years ago

You are correct in that it's not guaranteed, but it is the default behavior of Docker.

If you chown those directories as 1000, chances are your 1001 user won't have write access to those directories and you'll end up with the same permission denied error. Basically this ends up being very system specific but works out of the box 98% of the time. I wish I had a better answer but Docker doesn't make this process any more portable and the benefits of running things as a non-root user vastly out weigh having everything owned by root.

nickjj commented 2 years ago

Hey, I know it's been a while but can you try out this PR and report back whether it works or not in that PR? https://github.com/nickjj/docker-flask-example/pull/7

It should be a generic solution that will let you run things without permission errors by customizing the UID and GID in the .env file if your user account isn't set to 1000:1000.

I know it's a Flask app and not Django but I can port the same change over to this Django example app if it works.

nickjj commented 2 years ago

This is fixed in: https://github.com/nickjj/docker-django-example/commit/b269057cd7df996ffa479d76e3b441435c3af5d9