I know that it is impossible to change the permissions of a file shared via volume, because a matter of default, and from what I understand, the permissions of the docker container, reflect the permissions of the host, however, this is not happening in my case, the docker simply changes permissions on all files to 755, and some files must have specific permissions.
HOST:
Docker Container:
Docker File:
FROM ubuntu:18.04
ARG DEBIAN_FRONTEND=noninteractive
#Updating operating system
RUN apt-get update && apt-get -y upgrade && apt-get -y dist-upgrade
##Installing essential packages
RUN apt-get -y install apt-utils software-properties-common curl bash-completion vim git supervisor
## Add Scripts
ADD ./start.sh /start.sh
EXPOSE 80
STOPSIGNAL SIGTERM
#CMD ["/start.sh"]
ENTRYPOINT echo $XDEBUG_CONFIG >> /etc/php/7.3/fpm/php.ini && service php7.3-fpm start && nginx -g "daemon off;"
docker-compose.yml
volumes:
- ${DOCUMENT_ROOT-./www}:/usr/share/nginx/html
- ${VHOSTS_DIR-./config/nginx/sites-enabled}:/etc/nginx/sites-enabled
- ${PHP_INI-./config/php/php.ini}:/etc/php/7.3/fpm/conf.d/php.ini
- ${LOG_DIR-./logs/nginx}:/var/log/nginx
Your assumption
I know that it is impossible to change the permissions of a file shared via volume
Is only partially correct, there is actually a set of modes — :ro & :rw – you can use when mounting a volume via docker-compose that are described in the documentation:
Standard modes are ro for read-only and rw for read-write (default).
Source: https://docs.docker.com/compose/compose-file/#short-syntax-3
You can also use the :Z and :z modes if your host uses selinux.
If you use selinux you can add the z or Z options to modify the selinux label of the host file or directory being mounted into the container. This affects the file or directory on the host machine itself and can have consequences outside of the scope of Docker.
The z option indicates that the bind mount content is shared among multiple containers.
The Z option indicates that the bind mount content is private and unshared.
Use extreme caution with these options. Bind-mounting a system directory such as /home or /usr with the Z option renders your host machine inoperable and you may need to relabel the host machine files by hand.
Source: https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label
Here is an example, on my host, here are the permissions of my files:
~ # ls -la ro rw
ro:
total 0
drwxr-xr-x 3 ben staff 96 May 23 23:06 .
drwxr-xr-x 9 ben staff 288 May 23 23:16 ..
-rw-r--r-- 1 ben staff 0 May 23 23:06 file
rw:
total 0
drwxr-xr-x 3 ben staff 96 May 23 23:06 .
drwxr-xr-x 9 ben staff 288 May 23 23:16 ..
-rwxr-xr-x 1 ben staff 0 May 23 23:06 file
Then with this docker-compose.yml
version: '3.8'
services:
test:
image: alpine
volumes:
- ./ro:/root/ro:Z
- ./rw:/root/rw:Z
command: sleep 100000000000
Here is the result on the container
~ # ls -la ro rw
ro:
total 4
drwxr-xr-x 3 root root 96 May 23 21:06 .
drwx------ 1 root root 4096 May 23 21:17 ..
-rw-r--r-- 1 root root 0 May 23 21:06 file
rw:
total 4
drwxr-xr-x 3 root root 96 May 23 21:06 .
drwx------ 1 root root 4096 May 23 21:17 ..
-rwxr-xr-x 1 root root 0 May 23 21:06 file
Related
So I have gotten a folder to rename in a directory. Every other folder I put in that mounted directory says:
Warning:
rename(/app/public/CoverImages/S3-Uploaded/subfolder-for-depth/2019-01-15-Uploaded,/app/public/CoverImages/S3-Uploaded/subfolder-for-depth/2019-01-15-Uploaded-AWS):
Permission denied in /app/src/S3CoverImages.php on line 260
My php code is the following:
if(is_dir($dirPath)) {
$success = rename(rtrim($dirPath, " -/"), rtrim($dirPath, " -/") . "-AWS");
My dockerfile code for permissions is as follows:
RUN chown www-data:www-data /usr/local/etc/php-fpm.conf && \
chown -R www-data:www-data /app && \
chmod -R 755 /app && \
chown -R www-data:www-data /var/www && \
chmod +x /usr/local/bin/start.sh; sync
In docker-compose.yml we have it mounting the directory we need:
version: '3.4'
services:
nginx:
image: americanreading/someproject:dev
restart: on-failure:3
ports:
- 8001:8080
php:
image: americanreading/bisapi-php:dev
environment:
#lots of server details here.
volumes:
- /mnt/coverimages/S3-Uploaded/subfolder-for-depth:/app/public/CoverImages/S3-Uploaded/subfolder-for-depth/
Is there something else I need to make sure any folder put into this mounted directory will have php permission to rename the folder? Is there anything evident that I am not doing at the moment?
Almost forgot, here are the current permissions we looked up in bash:
arcit#arcvm13:~/arcbis-dev$ docker-compose run --rm php bash
www-data#9a78e9799427:/app$ ls -la /app/public/CoverImages/S3-Uploaded/subfolder-for-depth/
total 16
drwxrwxrwx 2 root root 4096 Feb 25 14:31 .
drwxr-xr-x 3 root root 4096 Feb 25 14:38 ..
-rwxrwxrwx 1 root root 6148 Feb 25 14:32 .DS_Store
drwxrwxrwx 2 root root 0 Oct 20 2015 2010-02-15
drwxrwxrwx 2 root root 0 Feb 25 14:30 2019-01-15-Uploaded
drwxrwxrwx 2 root root 0 Feb 25 14:31 2019-02-07-Uploaded-AWS
drwxrwxrwx 2 root root 0 Feb 22 16:24 2019-02-18
Here is the ls -la on the subfolder-for-depth itself:
drwx------# 1 toddcoulson staff 16384 Oct 20 2015 2010-02-15
drwx------# 1 toddcoulson staff 16384 Feb 25 09:30 2019-01-15-Uploaded
drwx------ 1 toddcoulson staff 16384 Feb 25 09:31 2019-02-07-Uploaded-AWS
drwx------# 1 toddcoulson staff 16384 Feb 22 11:24 2019-02-18
The volume is created when you run the container, not when you build it. By default the permissions on that directory will be root.
An other issue here is that you are binding your volume to a host path "/mnt/coverimages/S3-Uploaded/subfolder-for-depth".
So that directory is going to have the permissions of your host (for example user 1000).
A solution is to add that user the the www-data group, in your Dockerfile.
I'm trying to read a file in PHP and I'm getting a permission denied error although everybody has read access to the file.
The PHP code:
$config=file_get_contents('/opt/jenkins/home/config.xml');
The error:
Warning: file_get_contents(/opt/jenkins/home/config.xml): failed to open stream: Permission denied in [...]
The filesystem permission:
There is a symlink pointing /opt/jenkins/home/ to /var/lib/jenkins and everybody has read permission on the symlink, actual folder, and file.
$ ls -lh /opt/jenkins/
lrwxrwxrwx 1 sysadmin sysadmin 16 2011-08-04 08:12 home -> /var/lib/jenkins
$ ls -lh /var/lib/ | grep jenkins
drwxr-xr-- 6 jenkins adm 4.0K 2011-08-04 10:04 jenkins
$ ls -lh /var/lib/jenkins/config.xml
-rwxr-xr-- 1 jenkins adm 3.9K 2011-08-04 10:05 /var/lib/jenkins/config.xml
Apache configuration
Configured to folllow symlinks (Options All). Adding a Directory directive for /var/lib/jenkins/ makes no difference.
<Directory /opt/jenkins/home/>
Options All
AllowOverride All
Order Allow,Deny
Allow from All
</Directory>
Additional info
Whether I use the path through the symlink ("/opt/jenkins/home/config.xml") or the real path ("/var/lib/jenkins/config.xml") I have the same problem.
apache2 version=2.2.14-5ubuntu8.4
php version=5.3.2-1ubuntu4.9
Any idea as to why I'm getting the error?
Your directory needs execute permission for this to work. It does not seem to have world execute, and since jenkins is probably not the apache user, and the apache user is not in the adm group, it wouldn't work:
$ ls -lh /var/lib/ | grep jenkins
drwxr-xr-- 6 jenkins adm 4.0K 2011-08-04 10:04 jenkins
Per example:
netcoder#netcoder:~$ mkdir foo
netcoder#netcoder:~$ echo hello > foo/bar
netcoder#netcoder:~$ chmod 777 foo/bar
netcoder#netcoder:~$ ls -lsah foo/bar
4.0K -rwxrwxrwx 1 netcoder netcoder 6 2011-08-04 08:22 foo/bar
netcoder#netcoder:~$ chmod 444 foo/
netcoder#netcoder:~$ ls -lsah | grep foo
4.0K dr--r--r-- 2 netcoder netcoder 4.0K 2011-08-04 08:22 foo
netcoder#netcoder:~$ cat foo/bar
cat: foo/bar: Permission denied
Even though foo/bar has 0777 permission, if the directory does not have the execute permission, reading its contents is denied.
You'll need the permission to be set for both the target directory and the symbolic link.
You need the execute bit set on all directories in the hierarchy up to that file.
chmod o+x /var/lib/jenkins
should do the trick.
(Note: ls -lhd /var/lib/jenkins is a bit better than ls -lh ...|grep jenkins)
Lots of modern boxes (digital ocean, rackspace etc) ship with SELinux (Security Enhanced Linux) for RedHat compatible OSs (like CentOS). This throws another wrench into the works which you need to keep in mind. You can have your permissions perfectly set and it will still say permission denied. You need to define a writable context for SELinux:
sudo chcon -t httpd_sys_rw_content_t /data/www/html/sites/mysite -R
Most likely your apache user is not allowed to read or access the web files
Check what user is apache running as:
$ ps aux | grep [a]pache
root 40283 0.0 0.2 472548 21116 ? Ss 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40287 0.0 0.1 472760 8800 ? S 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40288 0.0 0.1 472760 8540 ? S 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40289 0.0 0.1 472776 8540 ? S 14:38 0:00 /usr/sbin/apache2 -k start
Check the path ownership of your web files:
$ namei -mol /home/john/app2/
f: /home/john/app2/
drwxr-xr-x root root /
drwxr-xr-x root root home
drwx------ john john john # <== Ahaa, no access for apache user!
drwxr-xr-x john john john app2
Adjust permissions accordingly:
Well in this step I will leave it up to you, you can either (a) the make apache user 'john' in this example. Or you could (b) move the web folder to a place outside home. Where the execute access can be given to the group or to even others without breaking security good practices.
a. Make apache user john (ONLY FOR DEV SITES or if you know what you are doing)
sudo vi /etc/apache2/envars
# replace
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
# with
export APACHE_RUN_USER=john
export APACHE_RUN_GROUP=john
b. Move that folder out of home... what is it doing there anyways?
sudo mv /home/john/app2 /var/www/
Remember to change the site to match this directory and to restart the apache server.
Here are some references:
https://wiki.apache.org/httpd/13PermissionDenied
http://wiki.apache.org/httpd/FileSystemPermissions
I am developing symfony inside of a vagrant box. Recently I tried to boost performance (10k latency) and found this article.
It is suggesting to use /dev/shm/ for cache and logs.
This works like a charm, but comes with a problem. Lets say, I create the assets. Then the created files belong to the wrong user, because I am logged in as a vagrant user.
[05:33 ]-[vagrant#machine1]-[/var/www/backend]-[git dippingbird/master]
$ ls -lsah /dev/shm/appname/
total 0
0 drwxrwxr-x 4 vagrant vagrant 80 Mar 21 05:28 ./
0 drwxrwxrwt 3 root root 80 Mar 21 05:28 ../
0 drwxrwxr-x 3 vagrant vagrant 60 Mar 21 05:28 cache/
0 drwxrwxr-x 2 vagrant vagrant 60 Mar 21 05:29 logs/
When I want to visit the page in dev environment, it clearly does not work. It says in the browser:
If I change the permissions to -R 777 it clearly works.
So I figured out, that I want apache run as the vagrant user. But internet documentation is vague. I want to do it via my puphpet config.yaml so it is available for all developers in the team.
Or do I have a braintwist? Why is this permission error not occuring when I am using the dirname(__DIR__).'/var/logs'; for logs / cache.
I use Docker to run my PHP app. Now I want Travis CI to test my app. But all my builds fail, because containers can not open files in /temp directory of my app.
I have data container:
FROM ubuntu
COPY ./ /project
VOLUME /project
CMD ["true"]
I use my own PHP fpm container based on php:7.0-fpm - only with some extensions installed. Same for nginx.
My docker compose looks like this
version: '2'
services:
data:
build: ./
volumes:
- .:/project
command: "true"
nginx:
image: myNginx
ports:
- "80:80"
- "443:443"
volumes_from:
- data
links:
- php
php:
image: myPhp
ports:
- "9000:9000"
volumes_from:
- data
You can see that I use shared volume with host. Everything works on my local machine (windows) but not on travis.
And finaly my travis.yml
sudo: required
language: php
services:
- docker
before_script:
- docker-compose up --build -d
# Run firefox
- docker run -d -p 4444:4444 -p 5900:5900 --name firefox --link my_nginx:nginx --net myapp_default selenium/standalone-firefox-debug:2.53.0
script:
# Run Codeception
- docker run --rm --volumes-from my_data --link firefox --net myapp_default --name codeception codeception/codeception run accept
All codeception tests fails because app can not write to /log and can not open files in /temp. It is interesting because it writes some files but later it can not open it.
I ls -la with result:
# ./temp
drwxrwxr-x 3 travis travis 4096 Nov 4 15:55 .
drwxrwxr-x 14 travis travis 4096 Nov 4 15:56 ..
drwxr-xr-x 4 root root 4096 Nov 4 15:55 cache
-rw-rw-r-- 1 travis travis 14 Nov 4 15:49 .gitignore
# ./temp/cache
drwxr-xr-x 4 root root 4096 Nov 4 15:55 .
drwxrwxr-x 3 travis travis 4096 Nov 4 15:55 ..
drwxr-xr-x 2 root root 4096 Nov 4 15:55 Nette.Configurator
drwxr-xr-x 2 root root 4096 Nov 4 15:55 _Nette.RobotLoader
# ./temp/cache/Nette.Configurator
drwxr-xr-x 2 root root 4096 Nov 4 15:55 .
drwxr-xr-x 4 root root 4096 Nov 4 15:55 ..
-rw-r--r-- 1 root root 116093 Nov 4 15:55 Container_70d15d6361.php
-rw-r--r-- 1 root root 0 Nov 4 15:55 Container_70d15d6361.php.lock
-rw-r--r-- 1 root root 52913 Nov 4 15:55 Container_70d15d6361.php.meta
I ma pretty sure that I have bad permissions set in travis or in container, but I don`t know how to fix it.
The files that Travis pulls will be owned by the travis user and group, while the processes running inside the container expect the active user to be the owner. I had this issue with a docker-compose file that was running fine on my Mac, but failed on Travis.
For me, this was fixed by adding this to the install step in my .travis.yaml (edit: you'll probably want it in your before_script section instead):
install
- docker-compose run --user='root' --entrypoint chown worker_test -R myuser:myuser .
This writeup on UID/GID bits was helpful: Understanding user file ownership in docker: how to avoid changing permissions of linked volumes
I'm trying to read a file in PHP and I'm getting a permission denied error although everybody has read access to the file.
The PHP code:
$config=file_get_contents('/opt/jenkins/home/config.xml');
The error:
Warning: file_get_contents(/opt/jenkins/home/config.xml): failed to open stream: Permission denied in [...]
The filesystem permission:
There is a symlink pointing /opt/jenkins/home/ to /var/lib/jenkins and everybody has read permission on the symlink, actual folder, and file.
$ ls -lh /opt/jenkins/
lrwxrwxrwx 1 sysadmin sysadmin 16 2011-08-04 08:12 home -> /var/lib/jenkins
$ ls -lh /var/lib/ | grep jenkins
drwxr-xr-- 6 jenkins adm 4.0K 2011-08-04 10:04 jenkins
$ ls -lh /var/lib/jenkins/config.xml
-rwxr-xr-- 1 jenkins adm 3.9K 2011-08-04 10:05 /var/lib/jenkins/config.xml
Apache configuration
Configured to folllow symlinks (Options All). Adding a Directory directive for /var/lib/jenkins/ makes no difference.
<Directory /opt/jenkins/home/>
Options All
AllowOverride All
Order Allow,Deny
Allow from All
</Directory>
Additional info
Whether I use the path through the symlink ("/opt/jenkins/home/config.xml") or the real path ("/var/lib/jenkins/config.xml") I have the same problem.
apache2 version=2.2.14-5ubuntu8.4
php version=5.3.2-1ubuntu4.9
Any idea as to why I'm getting the error?
Your directory needs execute permission for this to work. It does not seem to have world execute, and since jenkins is probably not the apache user, and the apache user is not in the adm group, it wouldn't work:
$ ls -lh /var/lib/ | grep jenkins
drwxr-xr-- 6 jenkins adm 4.0K 2011-08-04 10:04 jenkins
Per example:
netcoder#netcoder:~$ mkdir foo
netcoder#netcoder:~$ echo hello > foo/bar
netcoder#netcoder:~$ chmod 777 foo/bar
netcoder#netcoder:~$ ls -lsah foo/bar
4.0K -rwxrwxrwx 1 netcoder netcoder 6 2011-08-04 08:22 foo/bar
netcoder#netcoder:~$ chmod 444 foo/
netcoder#netcoder:~$ ls -lsah | grep foo
4.0K dr--r--r-- 2 netcoder netcoder 4.0K 2011-08-04 08:22 foo
netcoder#netcoder:~$ cat foo/bar
cat: foo/bar: Permission denied
Even though foo/bar has 0777 permission, if the directory does not have the execute permission, reading its contents is denied.
You'll need the permission to be set for both the target directory and the symbolic link.
You need the execute bit set on all directories in the hierarchy up to that file.
chmod o+x /var/lib/jenkins
should do the trick.
(Note: ls -lhd /var/lib/jenkins is a bit better than ls -lh ...|grep jenkins)
Lots of modern boxes (digital ocean, rackspace etc) ship with SELinux (Security Enhanced Linux) for RedHat compatible OSs (like CentOS). This throws another wrench into the works which you need to keep in mind. You can have your permissions perfectly set and it will still say permission denied. You need to define a writable context for SELinux:
sudo chcon -t httpd_sys_rw_content_t /data/www/html/sites/mysite -R
Most likely your apache user is not allowed to read or access the web files
Check what user is apache running as:
$ ps aux | grep [a]pache
root 40283 0.0 0.2 472548 21116 ? Ss 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40287 0.0 0.1 472760 8800 ? S 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40288 0.0 0.1 472760 8540 ? S 14:38 0:00 /usr/sbin/apache2 -k start
www-data 40289 0.0 0.1 472776 8540 ? S 14:38 0:00 /usr/sbin/apache2 -k start
Check the path ownership of your web files:
$ namei -mol /home/john/app2/
f: /home/john/app2/
drwxr-xr-x root root /
drwxr-xr-x root root home
drwx------ john john john # <== Ahaa, no access for apache user!
drwxr-xr-x john john john app2
Adjust permissions accordingly:
Well in this step I will leave it up to you, you can either (a) the make apache user 'john' in this example. Or you could (b) move the web folder to a place outside home. Where the execute access can be given to the group or to even others without breaking security good practices.
a. Make apache user john (ONLY FOR DEV SITES or if you know what you are doing)
sudo vi /etc/apache2/envars
# replace
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
# with
export APACHE_RUN_USER=john
export APACHE_RUN_GROUP=john
b. Move that folder out of home... what is it doing there anyways?
sudo mv /home/john/app2 /var/www/
Remember to change the site to match this directory and to restart the apache server.
Here are some references:
https://wiki.apache.org/httpd/13PermissionDenied
http://wiki.apache.org/httpd/FileSystemPermissions