docker-compose-laravel
docker-compose-laravel copied to clipboard
The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied
I got the following error.
Currently I'm working on the Ubuntu 18.04 and created a laravel project with the version ^7.0.
On the console, the containers and the initial configuration ran well.
I have the same issue. I am running Debian 10, my Laravel project source code in stored in a home subdirectory, owned by my user. I've already tried over 10 solutions proposed by various Stackoverflow posts and other sites, but the problem persists. I understand that the problem due to my local username, who owns the source directory, is different from php container's user, but I don't know how to fix it.
When I ran migration in the artisan container, there were a few migration errors which were written successfully in Laravel's log file. This also works:
- (from the local machine):
docker-compose run --rm artisan tinker
- (inside the Artisan container, running tinker):
Log::debug('Test')
The above procedure creates a new log file on my local drive. The new file is owned by root:root.
It seems like the artisan container runs with user root, which is able to modify local files, but the php container running my app uses the www-data user, which can't modify local files.
Furthermore, I added my local user to the www-data group, but the issue persists.
Try to give permissions to the storage folder.
sudo chmod -R 777 storage
- local
Edit 2y later bcs i saw few emails on this:
Production: sudo chmod -R a+rw storage
after that run:
php artisan cache:clear
php artisan config:clear
php artisan config:cache
Dear @vladutt, thank you for responding quickly.
The above solution works. Exact steps are:
-
sudo chmod -R 777 storage
-
docker-compose run --rm artisan cache:clear
-
docker-compose run --rm artisan config:clear
-
docker-compose run --rm artisan config:cache
I am concerned about security of the proposed solution though. On local development environment, this is not a problem. But for public testing and production, when app is exposed publicly, should there be a different approach of setting up the storage directory permissions?
You should set the user
in docker-compose.yml: https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15
Then, a chmod 755 will work
After searching for hours and a lot of trial and error, I found a solution that doesn't require the dreaded chmod 777
!
Adding RUN apk add shadow && usermod -u 1000 www-data && groupmod -g 1000 www-data
to the Dockerfile seems to make all the permissions play nice. I'm not sure if there are undesired consequences to this, but working for me.
Found from: https://stackoverflow.com/questions/36824222/how-to-change-the-nginx-process-user-of-the-official-docker-image-nginx
After searching for hours and a lot of trial and error, I found a solution that doesn't require the dreaded
chmod 777
!Adding
RUN apk add shadow && usermod -u 1000 www-data && groupmod -g 1000 www-data
to the Dockerfile seems to make all the permissions play nice. I'm not sure if there are undesired consequences to this, but working for me.Found from: https://stackoverflow.com/questions/36824222/how-to-change-the-nginx-process-user-of-the-official-docker-image-nginx
do we need to set any permissions on /src folder also? adding user in docker file only doesn't resolve the problem.
After searching for hours and a lot of trial and error, I found a solution that doesn't require the dreaded
chmod 777
! AddingRUN apk add shadow && usermod -u 1000 www-data && groupmod -g 1000 www-data
to the Dockerfile seems to make all the permissions play nice. I'm not sure if there are undesired consequences to this, but working for me. Found from: https://stackoverflow.com/questions/36824222/how-to-change-the-nginx-process-user-of-the-official-docker-image-nginxdo we need to set any permissions on /src folder also? adding user in docker file only doesn't resolve the problem.
Just adding RUN apk add shadow && usermod -u 1000 www-data && groupmod -g 1000 www-data
to the php container doesn't solve the issue. (note: the code is for alpine containers which I use)
Same goes for RUN deluser www-data && adduser -DH -h /home/www-data -s /sbin/nologin -u 1000 www-data
, as suggested in one of the comments here: https://stackoverflow.com/questions/36824222/how-to-change-the-nginx-process-user-of-the-official-docker-image-nginx
I wishfully tried running both commands, but the same problem occurs.
Update: it seems I've figured it out.
Running RUN deluser www-data && adduser -DH -h /home/www-data -s /sbin/nologin -u 1000 www-data
in the PHP container is important, but it is not the full solution.
The problem is also cause by the composer container. The composer container initially creates the Laravel application, with all the directories and files. This image is, by default, run as root. As a consequence, all the directories and files created by composer are owned by root:root. The solution is to also run the composer image as user 1000. For now, I do it when I run docker-compose run on composer image.
docker-compose run --rm --user 1000:1000 composer create-project --prefer-dist laravel/laravel .
If you already have a directory with Laravel application, the above solution won't work, as the directories and files are already created and owned by root:root. You need to delete the directory containing Laravel application and then re-install the application using the above docker-compose command.
I would also suggest a PR to improve the entire docker-compose setup in this repo.
P.S.: On MacOS, I has no problem with file permissions. Only on Windows 10. The above solution was tested on Windows 10 2004, Docker using WSL 2. I have Debian installed in WSL. Will verify the proposed solution on Debian machine later.
The solution is to also run the composer image as user 1000
Yeah this is precisely what I said here: https://github.com/aschmelyun/docker-compose-laravel/issues/49#issuecomment-651131620
For your existing files, you just need to run chown -R 1000:1000 /yourproject && chmod -R 755 /yourproject
in your projects folder
You should do that for the artisan and app containers
The solution is to also run the composer image as user 1000
Yeah this is precisely what I said here: #49 (comment)
For your existing files, you just need to run
chown -R 1000:1000 /yourproject && chmod -R 755 /yourproject
in your projects folderYou should do that for the artisan and app containers
I have cloned the project, startup the envirorment and I have create via composer container a new laravel app, but after I have the same issue I have applied this but i receive a 404 error, I have tried to launch a docker-compose run --rm artisan route:cache but this is the result:
Starting mysql ... done
Route cache cleared!
LogicException
Unable to prepare route [api/user] for serialization. Uses Closure.
at vendor/laravel/framework/src/Illuminate/Routing/Route.php:1150
1146| */
1147| public function prepareForSerialization()
1148| {
1149| if ($this->action['uses'] instanceof Closure) {
> 1150| throw new LogicException("Unable to prepare route [{$this->uri}] for serialization. Uses Closure.");
1151| }
1152|
1153| $this->compileRoute();
1154|
+15 vendor frames
16 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
@paranoiasystem this is a different issue, unrelated to permission. It simply means that you need to remove any closure route before caching routes. The error message is self explanatory.
https://stackoverflow.com/a/45266424/11989865
Hey all! This issue is a bit old, but I wanted to give an update. Sorry it took me a while to get around to it.
I've pushed out a large update to this repo, specifically involving permissions. There's now a .env.example
file, which contains two sets of user/group names. This file should be copied to .env
, and modified to match the username and group of the src
directory that stores your Laravel application's source files. Then, run docker-compose build --no-cache
before spinning your container network up again.
What the main permissions issue was:
Since we're using mounted volumes, Docker was overwriting any permissions or chown
s in the Dockerfiles, and instead was using the username and group from the host system. This was only occurring on Linux and Windows WSL-2 systems as far as I can tell, since MacOS uses a virtualization layer that masks that ownership. PHP was expecting a www-user
user and group, likewise with Nginx.
How it's solved now:
The best way I figured around it is either dropping the volumes and using ADD
in the dockerfiles to copy over the source code, modifying the permissions at build-time. The problem with this was that you lost the ability to work on your application and have your changes update in real-time.
Instead, during build-time I take the values from the .env
file for username/group, and create them in the containers. By matching the user and group that exists on the host system with the same one in the container(s), the application doesn't encounter any read/write errors and can proceed smoothly. There was also a fix to allow php to run as root, even if it's not recommended, since some webservers have their single user set to root/root.
Let me know if you have any questions about this, or if it's still a problem after using the updated repo!
Hi @aschmelyun thank you for your recent last update on this! When you say to copy the .env and modify to match username and group (www-data / www-data). How do we get to know what are the username and group? For instance using the laravel/laravel default app you suggest from your video example: https://www.youtube.com/watch?v=5N6gTVCG_rw&list=RDCMUCc07-IBVwRlOsMg2WMdd8Sg&index=26
Thank you!
I still have this problem after the update
It worked for me following the steps:
The username to be used, is the username of your linux/computer: username@repertory Then you need to create a new .env directly where you found the .env-example file Then I needed to replace "127.0.0.1" to "mysql" in the .env file of my application.
Thank you!
It worked for me following the steps:
The username to be used, is the username of your linux/computer: username@repertory Then you need to create a new .env directly where you found the .env-example file Then I needed to replace "127.0.0.1" to "mysql" in the .env file of my application.
Thank you!
Thank you ! Now it works for me .
thanks
I'm getting this same problem in Ubuntu 22.04. I've checked the .env and .env.example files, but neither have anything that looks like user/group names. What exactly do I need to add/change?
Here's my .env-example file.
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=example_app
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
It worked for me following the steps:
The username to be used, is the username of your linux/computer: username@repertory Then you need to create a new .env directly where you found the .env-example file Then I needed to replace "127.0.0.1" to "mysql" in the .env file of my application.
Thank you!
Following this advice should work going forward. If you have any other issues that aren't fixed by this, the advice above, or what's in the README file under "Permissions Issues" please open up another ticket!
I use Ubuntu 22.04. The solution is:
SSH into Docker container:
docker exec -it app_name-laravel.test-1 /bin/bash
Change the owner of storage/framework and storage/logs to sail
not www-data
:
chown -R sail:sail storage/framework
chown -R sail:sail storage/logs
If it still don't work, try to install htop inside that docker container. Run htop. Find the user of /var/www/artisan serve
. Then repeat the commands above but with that user, not sail
. Good luck!
Update
Or much better, create a group for root and user from docker (mine is sail):
groupadd sailroot
then add both root and sail to the group:
usermod -a -G sailroot sail
usermod -a -G sailroot root
Change group owner of storage logs and framework to the group:
chown root:sailroot -R storage/framework
Change file permission to 775 for both:
chmod 775 -R storage/framework
In this way, you can using php artisan serve
using php installed locally, or with docker using sail. Remember to leave the user to root, and group sailroot (or whatever you named)
Use this technique for Ubuntu 22.04
You need to start your Laravel Sail container like this
docker exec -it app_name-laravel.test-1 /bin/bash
h1 Next create storage file by
mkdir /.storage
cd /storage
mkdir -p framework/{sessions,views,cache}
Get back to root file or root container by
cd ..
chmod -R ugo+rw /.storage || chmod 775 -R storage/
- This means storage file will be ready for new addition
Thank you Hope your problem solved!