Docker data-only container permissions - php

I'm developing PHP app and I'm stuck with Docker volumes. I've tried to create a separate data-only container for my PHP app but couldn't make it work because of permission issues... I've googled and read all I could and the most close to working solution is described here
But it's a bit old and I couldn't make it work too.
I've created a repo with a simple test code:
https://github.com/oleynikd/docker-volumes-permissions/
This simple project uses docker-compose to run 2 containers:
For php fpm
For nginx
The php code is mapped to php container and lives in /src directory.
The main problem is that PHP has no rights to write to code's directory because it runs as www-data user but code's directory belongs to user with id 1000 and group staff.
After running docker-compose up and visiting /index.php you'll see the warning and ls -lah output that shows the permission issue. Here's the screenshot:
I've tried to fix this by adding RUN mkdir -p /src && chown -R www-data:www-data /src to php Dockerfile but that didn't helped.
So questions are:
Why the owner and the group of /src is 1000:staff?
How to fix this?
I'm sure the solution is simple but I can't find it.
Please help!
P.S. Feel free to contribute to repo if you know how to fix this issue.

The owner of the files is 1000:staff because 1000:1000 is the uid:gid of the owner of the files on the host machine.
You could avoid it using volumes without specifying the path of the files on the host machine and adding the files with a COPY instruction in the dockerfile. But maybe you need to easily access to theses files on the host?
For development environments (and development environment only), I use a hacky solution that I described in this answer to manage it.

Related

Move files from a docker container to an outside folder on the same server using php

I am fairly new to docker, please bear with me if its a basic question. I have a laravel project on a server, the project is dockerized. What I want to do is move a file from my project to another location on the same server that is not dockerized.
So, my project is setup on /var/www/my-project directory and I want to copy a file from my-project/storage/app/public/file.csv to /var/{destination_folder}. How can I do that in laravel? I think my issue is not related to laravel it is related to docker which is not allowing to move files out of it. Please don't add laravel or php file copy code snippets,I have tried plenty.
What I've tried?
1- I have tried copying file using:
Storage::disk('local')->put('/var/{destination_folder}', 'my-project/storage/app/public/file.csv' )
but, it does not copy the file.
2- I have also tried moving the file using bash script which I'm executing from my laravel controller using shell_exec or process but, it is also not working.
cp "/var/www/my-project/storage/app/public/file.csv" "/var/destination_folder"
What's hapening in this solution is that it is working when I run the command from terminal, but its not working when I call it from my controller and it gives me
cp: cannot create regular file '/var/destination_folder/file.csv': No such file or directory
After googling the above error it seemed that this is a permission issue wo, I changed the permission of the destination folder to 775 and I also checked the user from which I was running the laravel app and it gave me root when I ran whoami from the app.
Let me know how this could be achieved, thank you!
The entire point of docker is that it is isolated from the base host. You cannot simply copy the file out, as the docker host does not have access to any disk that is not mounted.
The easiest option is to create a destination directory and create a bind mount as per https://docs.docker.com/storage/bind-mounts/
You would then use the following argument for your docker run:
--mount type=bind,source=/var/destination_folder,target=/some_directory_inside_your_docker and copy the file to some_directory_inside_your_docker and it will appear in the parent host.
Another option is to generate a user account on the parent host, LOCK IT DOWN HARD for security reasons, and then have a private key inside your docker that would allow your docker to SSH to the parent host (note, this won't work with every network configuration). I don't think it's a good idea when you can do bind mounts, but it would work.

Symfony on Apache permission issues

I have made a lot of Symfony apps that work in production, but recently tried deploying one to Ubuntu 16 for the first time. var/logs/prod.log shows errors about not being able to find classes, so of course the app won't run.
I can "fix" this with chmod 777 /var/www/ -R, and everything starts working. Surely that's not safe... How can I fix this the right way?
Note: I am currently not logged in as a user but as root.
*EDIT
The app will not run after chmod 777 /var/www/var -R to change permissions for chache and logs, but only if I change the permissions for all the folders of the entire app.
You might try locating folders/files which are the problem and change ownership to www-data which is actually used by Apache.
For a whole directory with files recursively:
chown -R www-data:www-data [folder_path_and_name]
For a specific file:
chown www-data:www-data [file_path_and_name]
Symfony has a section in the documentation for file permissions
Mainly you need to adjust the apache user permissions for logging, and as root you can easily do that.
Just remember to ignore the logs + cache if you're using source control such as Github.

Specify umask in Dockerfile

I'm using Mac OS and recently I'm trying to set up a development environment with docker. Docker seems to be nice, but currently I'm facing the following problem:
PROBLEM:
Whenever PHP (in the docker container) is creating a folder with a subfolder, apache results in a 500-error. Apache-log: "... Can't create directory app/../../folder/subfolder/subsubfolder/"
I assume that this is caused by the environment variable umask, because whenever a folder is created, it doesn't have write permission. Because of that subfolders can't be created and so on.
To test this out, I wrote a little test-script (umask-test.php):
$umask = umask(0);
echo ("umask = $umask <br>");
And bingo! Every time I build and run the container and start the script via the browser, the result is:
umask = 18
GOAL:
So I would like to have umask always to be set to 000 (zero)
I figured out, the best place to set this variable would be the Dockerfile, so in the Dockerfile I stated the following:
FROM ubuntu:trusty
...
ENV UMASK 0
...
Problem is, that this results in nothing:
the test-script gives out 18 for umask
folders are still created with the wrong permission
subfolders can't be created.
QUESTIONS:
What am I doing wrong?
How can umask in docker containers always be set to zero?
How can I permit the apache-user (www-data) to create folders that always have write-permissions and in which subfolders can be created?
Problem solved
Since hopefully this is helpful for other, I want to provide the answer to my own question:
The problem is not docker and umask-settings in the container. The problem is the Mac and the umask-setting on the Mac OS!!
Example: If umask on the Mac is set to 022, then folders created on mounted directories by docker have the permissions 755. This causes, that no subfolders can be created.
This link is providing the information about how to set umask for the Mac: https://support.apple.com/en-us/HT201684
So if you type in your terminal
sudo launchctl config user umask 000
and reboot, all your folders will be created with 777-permissions.
Including the folders mounted to docker.
Before I was asking myself why running containers (initialized with run -v ...) are not really working. Now it seems to work all right! :-)
According to the Docker docs environment variables you set with ENV do persist to the running container, but Apache is probably very picky about which ones it pays attention to on start up on security grounds.
Try this answer.

Apache is not respecting my default permissions when writing files

I'm using Laravel, and whenever the logs or the cache is being written to the storage folder, it's giving 755 permissions, and creating the owner as daemon. I have run sudo chown -R username:username app/storage and sudo chmod -R 775 app/storage numerous times. I have even added username to the group daemon and daemon to the group username.
But, it still writes files as daemon, and with 755 permissions, meaning that username can't write to it.
What am I doing wrong?
This one has also been bugging me for a while but I was too busy to hunt down a solution. Your question got me motivated to fix it. I found the answer on Stack Overflow.
In short, the solution is to change the umask of the Apache process. The link above mentions two possible places to make the change: you add umask 002 to
/etc/init.d/apache2
/etc/apache2/envvars (Debian/Ubuntu) or /etc/sysconfig/httpd (CentOS/Red Hat), or
Edit
I recently upgraded from Ubuntu 12.04 32-bit to 14.04 64-bit and, to my great irritation, I could not get this to work. It worked for some PHP scripts but not others - specifically, a short test script I wrote worked fine, but the Laravel caching code did not. A co-worker put me on to another solution: bindfs.
By mounting my project directory (/var/www/project) in my home directory (~/project) with the appropriate user mapping, all my problems were solved. Here's my fstab entry:
/var/www/project /home/username/project fuse.bindfs map=www-data/username:#www-data/#usergroup
Now I work in ~/project - everything looks like it's owned by username:usergroup and all filesystem changes work as if I own the files. But if I ls -la /var/www/project/, everything is actually owned by www-data:www-data.
Perhaps this is an overly-complicated solution, but if you have trouble getting the umask solution to work, this is another approach.
In this instance Apache isn't doing anything wrong. Apache reads and writes files based on the User and Group settings in its configuration file. The configuration file in question is like /etc/httpd/conf/httpd.conf but the location and even name differs depending on the system you're using.
It's also worth noting, that if you're running PHP as something such as FastCGI, then it'll use the user that FastCGI is set to use, seeing as that is the bit that modifies and creates files, not Apache.

php+nginx+vagrant - php fails to write

I have a vagrant box setup running my dev code which is a nginx/php setup.
(Quick info on vagrant - its a virtualbox wrapper: http://www.vagrantup.com/).
In the vagrant/virtualbox setup, it is using linux guest additions to mount a shared folder on my host computer (MAC OSX).
linux guest path: /var/www/local
OSX host path: ~/src/
On multiple occasions, I find that php can't seem to write anything through any command (file_put_contents, fwrite.. etc) to any path location on the mounted shared folder, However it is able to write outside of the /var/www/local (for example /var/www/not-mounted/..).
I find this very difficult to work with, as I am using a cache system and it keeps failing to write any of the cache javascript/css files to (/var/www/local/public/root/cache/) which I need to be in the root folder of my website which is (/var/www/local/public/root/index.php).
I have done a lot of research on this topic:
it seems, the folder mount has the right permissions:
When I type mount command in the linux guest, I get this:
/var/www/local on /var/www/local/ type vboxsf (uid=1000,gid=1000,rw)
Clarify:
This happens all the time, it is a known problem I encounter which I try to workaround.
From cat /etc/passwd:
vagrant:x:1000:1000:vagrant,,,:/home/vagrant:/bin/bash
Can anyone help me on this?
I have figured out the problem.
I have forgot to give PHP the correct user-privileges and permissions to write to the folder. Basically, my PHP user/user-group was www-data/www-data however, vagrant has its own user/group (vagrant/vagrant) which mounts the folder /local/.
Since I did not want to mess with my vagrant mounting behaviour, I just simply changed my php config to start PHP with the user/group - vagrant/vagrant.
This fixed the issue for me.
Thanks for the help!

Categories