Docker: How to solve Apache 403 Forbidden error?
It's a popular problem getting "403 Forbidden" errors from Apache. Even though it's working on the docker, it's the same but a little bit harder to investigate why it’s happened. However, most of the time, the cause of this problem is simple. Let’s take a look at some samples.
First, let me show you the correct way. Here is the vhost configuration file as vhost.conf.
1<VirtualHost *:80>
2 DocumentRoot /var/www/html
3</VirtualHost
And make a directory and put a text file for verifying.
1mkdir app/web
2echo "Hoge" > app/web/index.html
And make a docker-compose.yml file like this.
1version: '3'
2services:
3 app:
4 container_name: my-app
5 image: php:7.4-apache
6 ports:
7 - 8080:80
8 volumes:
9 - ./app/web:/var/www/html
10 - ./vhost.conf:/etc/apache2/sites-enabled/000-default.conf
Then, it’s ready for running. Execute it like this.
1docker-compose up
And open a new terminal and execute curl command for verifying.
1$ curl localhost:8080
2Hoge
This is what I expected. It’s totally no problem. But sometimes "403 Forbidden" errors appear. How it happens? Most of the time, the cause of the error is modifying document root directory. Here is a sample.
Modify the document root setting in vhost.conf
1<VirtualHost *:80>
2 DocumentRoot /srv/app
3</VirtualHost>
And modify docker-compose.yml too.
1version: '3'
2services:
3 app:
4 container_name: my-app
5 image: php:7.4-apache
6 ports:
7 - 8080:80
8 volumes:
9 - ./app/web:/srv/app
10 - ./vhost.conf:/etc/apache2/sites-enabled/000-default.conf
However, if I execute curl command the same as the last time, the error will be returned.
1$ curl localhost:8080
2<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
3<html><head>
4<title>403 Forbidden</title>
5</head><body>
6<h1>Forbidden</h1>
7<p>You don't have permission to access this resource.</p>
8<hr>
9<address>Apache/2.4.38 (Debian) Server at localhost Port 8080</address>
10</body></html>
The hint is Apache's default settings.
1$ docker run -it --rm --entrypoint sh php:7.4-apache -c "cat /etc/apache2/apache2.conf"
2 :
3 :
4<Directory />
5 Options FollowSymLinks
6 AllowOverride None
7 Require all denied
8</Directory>
9
10<Directory /usr/share>
11 AllowOverride None
12 Require all granted
13</Directory>
14
15<Directory /var/www/>
16 Options Indexes FollowSymLinks
17 AllowOverride None
18 Require all granted
19</Directory>
20 :
21 :
As you see above, the first setting is set "all denied" for the root directory. And then, "/usr/share" and "/var/www/" is granted. So, even though I modify the directory path in the vhost.conf and docker-compose.yml file, the modified directory is not granted. So, the response will be the error.
So, how to fix it when I need to modify the document root directory? It’s necessary to add a grant setting like this.
1<VirtualHost *:80>
2 DocumentRoot /srv/app/web
3
4 <Directory "/srv/app/web">
5 AllowOverride all
6 Require all granted
7 </Directory>
8</VirtualHost>
The error will disappear.
And also, mistakes of the mount point is also a popular cause of some problems. For example, confusing "sites-available" and "sites-enabled" directories. In the traditional way, add the configuration file to "sites-available" first, and then execute "a2ensite" command to make it enabled and then restart the Apache process with graceful option. However, when executing the Apache on docker, no need to do that. Just mount it to 000-default.conf file under the "sites-enabled." If it’s mounted under the "sites-available" as follows, it will not be loaded by Apache.
1 volumes:
2 - ./app/web:/srv/app
3 - ./vhost.conf:/etc/apache2/sites-available/000-default.conf