I'm building a Docker image for my Symfony app and I need to give permission to apache server to write into cache and log folders

FROM php:7-apache

RUN apt-get update \
&& apt-get install -y libicu-dev  freetds-common freetds-bin unixodbc \
&& docker-php-ext-install intl mbstring \
&& a2enmod rewrite

COPY app/php.ini /usr/local/etc/php/
COPY app/apache2.conf /etc/apache2/apache2.conf
COPY ./ /var/www/html

RUN find /var/www/html/ -type d -exec chmod 755 {} \; 
RUN find /var/www/html/ -type f -exec chmod 644 {} \;
RUN chmod -R 777 /var/www/html/app/cache /var/www/html/app/logs

When I build this image with docker build -t myname/symfony_apps:latest . and run the container with docker run -p 8080:80 myname/symfony_apps:latest. Apache log is flooded by permission denied errors , the strange thing that I've checked with ls -a and permissions are fine. and when I run chmod from container's bash , apache permission issues are gone and the app works well

The situation

Running chmod commands from dockerfile: permissions are changed but apache still complains about permission denied. Running chmod same commands with bash inside the container: permissions are changed and my app is running

Any idea , Am I missing something, maybe I should add root user somewhere in the Dockerfile ?

  • It would be helpful to see your docker command that runs the built image.
    – Mike Park
    Commented Apr 22, 2016 at 13:55
  • I'm seeing an extra space in your last command (I'm on my phone, so I can't be sure). As the permission problem seems to be with the log directory, change the last line to: ``` RUN chmod -R 777 /var/www/html/app/cache /var/www/html/app/logs ```
    – Mike Park
    Commented Apr 22, 2016 at 13:58
  • 1
    Okay .. I edited the question :)
    – storm
    Commented Apr 22, 2016 at 13:59
  • that extra space was a typo
    – storm
    Commented Apr 22, 2016 at 14:37
  • I am unable to reproduce your problem. If I use your dockerfile and set up some dummy files locally, permissions are correct and everything Just Works. I can boot a container and access content via a web browser. Can you update your question to include specific error messages? Are you certain your Apache configuration (apache2.conf) is not causing a problem? Do the errors go away if you do not install apache2.conf?
    – larsks
    Commented Aug 4, 2016 at 20:01

5 Answers 5


I had the same issue and it seems that there is some bug in docker or overlay2 if directory content is created in one layer and its permissions are changed in other.

As a workaround you could copy sources to temporary directory:

COPY . /src

And then move it to /var/www/html and setup permissions (in one RUN command):

RUN rm -rf /var/www/html && mv /src /var/www/html &&\
    find /var/www/html/ -type d -exec chmod 755 {} \; &&\
    find /var/www/html/ -type f -exec chmod 644 {} \; &&\
    chmod -R 777 /var/www/html/app/cache /var/www/html/app/logs

Also I created GitHub issue.

  • I was going to dig into my old source code this night to see how I've solved this , then I remembered that tmp directory trick .. hope this didn't took you a lot of time to solve XD
    – storm
    Commented Jan 6, 2017 at 8:16
  • this is still an open issue?!
    – Ewoks
    Commented Dec 16, 2020 at 18:56

Try adding :

USER root

It worked for me.

  • 6
    If you switch to root, you should probably switch back to the previous user when you finish or you are decreasing the security and compatibility of the container. Some Kubernetes implementations by default won't run a container as root for example.
    – flickerfly
    Commented Oct 25, 2019 at 18:44
  • 1
    for me switching to root doesn't help
    – QkiZ
    Commented Jun 25, 2020 at 14:29
  • Alternative to switching user, you can also use a multistage build. Perhaps not as useful for PHP images, but anything that requires an application to be built before it is run could benefit from that approach. Commented Dec 14, 2021 at 11:47

The default shell of RUN in Docker is /bin/sh and this is where the permissions not being set correctly actually has a problem.

But you can change to just use /bin/bash instead to easily fix, notice before and after directory listing

Step 7/9 : RUN /bin/bash -c 'ls -la; chmod +x gitlab-properties-builder.sh; ls -la'
---> Running in dc57ae77aa67

drwxr-xr-x. 3 root root      103 Mar  8 17:56 .
drwxr-xr-x. 1 root root       46 Mar  8 17:57 ..
drwxr-xr-x. 2 root root        6 Mar  7 20:47 config
-rw-r--r--. 1 root root     2340 Mar  7 21:20 gitlab-properties-builder.sh
-rw-r--r--. 5 root root 57325770 Mar  5 14:39 gitlab-scm-collector-2.0.5-SNAPSHOT.jar

drwxr-xr-x. 1 root root       42 Mar  8 17:56 .
drwxr-xr-x. 1 root root       61 Mar  8 17:57 ..
drwxr-xr-x. 2 root root        6 Mar  7 20:47 config
-rwxr-xr-x. 1 root root     2340 Mar  7 21:20 gitlab-properties-builder.sh
-rw-r--r--. 5 root root 57325770 Mar  5 14:39 gitlab-scm-collector-2.0.5-SNAPSHOT.jar
---> 8b5de6e348d3
  • 9
    Why is /bin/bash -c 'chmod +x file' is working and not /bin/sh -c 'chmod +x file' ?
    – storm
    Commented Mar 14, 2018 at 16:27
  • your is better solution . it worked for me . thanks . Commented Oct 2, 2018 at 5:58
  • Also, using the new buildkit helps in a number of areas including this one. Give it a try. docs.docker.com/develop/develop-images/build_enhancements Commented May 18, 2019 at 1:15

This issue is likely the result of a VOLUME definition inside the upstream Dockerfile. When a volume is defined in the Dockerfile, you can add files with a COPY or ADD command directly into the image. However, a RUN line will:

  • Create a temporary container using the image definition as of the current point of the dockerfile
    • That temporary container will have an anonymous volume mounted as you or a parent image specified inside the Dockerfile
    • The anonymous volume will be initialized from the contents of the image
  • Your command will run inside the container
    • If you list the directory during this RUN command, you will see your changes applied, but those changes have been applied to the volume
  • When your run command completes, docker will capture the changes to the container
    • These changes can be seen with a docker diff if you do not delete the temporary containers (you can run a build with --rm=false to have them remain)
    • These changes will not include the anonymous volume contents because they do not exist inside the temporary container filesystem, volumes are separate

Because of this behavior, you have the options to:

  1. you can copy your files to a different directory and change the permissions there
  2. you can fix the permissions on your host so they get copied in with those permissions directly
  3. you can remove the volume from either your image, get the upstream image to remove their volume definition, or you can rebuild your own copy of the upstream image without the volume definition and base your images off of that

Note that inside the current php images, it appears that the volume has been removed, which means we effectively have option 3.

  • This volume/build behaviour is absolutly logical but I missed it : I'm really a dumb boy, shame on me ! - and thanks a lot for your very clear explanation Commented Oct 13, 2020 at 10:31
  • unfortunately you cant remove upstream volumes.
    – QkiZ
    Commented May 20, 2021 at 15:58
  • @QkiZ I was suggesting you talk to upstream, not that there's a technical way to have docker do that, other than the third part of the third option.
    – BMitch
    Commented May 20, 2021 at 17:16

I just made an experiment with the following:

FROM alpine

RUN apk add --no-cache inotify-tools
CMD [ "./script.sh" ]
WORKDIR /opt/app/
COPY src/ /opt/app/
RUN chmod a+x *.sh

And it just works great.


When I override that executable file through docker-compose volumes, the execute permission is simply like rolled-back - technically overrode to original file permission.

The fix for dev mode is simply to chmod a+x yourfile from host, which will be inherited at compose volume mounting.

  • 1
    The entire goal of a volume is to mount files from somewhere other than the image, so if you fix your image and mount a volume over top of that, by design you will not see your image changes. Depending on why you have a volume, the answer may be to simply not have a volume.
    – BMitch
    Commented Nov 19, 2018 at 14:12
  • Yes BMitch, I totally agree as for the effect of mounting volume that override container fs from docker built image, but... During development, you surely don't want to rebuild/restart your container in order to test each and every change you do. In this latter scenario do you want that mount a volume that overrides docker built image fs. And I faced the same issue before landing here. I wasn't convicted by either answer explanations and tested each of them. It is only then that I understood what it going on and posted my observations... Commented Nov 19, 2018 at 16:32
  • ...and I suspect the scenario I experienced is the same as that of he who asked the question. Commented Nov 19, 2018 at 16:39
  • The OP indicated they saw the issue with just a docker run command and no external volume mounts.
    – BMitch
    Commented Nov 19, 2018 at 16:57
  • Oups - I missed that aspect... The right answer for the right question title, but not the described scenario. Then may I mention that I could not reproduce the above mentioned issue. Commented Nov 19, 2018 at 18:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .