Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

raloseq's avatar

403 Forbidden docker laravel+nginx+mariadb

Hello, i want to dockerize my application but im getting 403 Forbidden and my dockerfile don't see entrypoint.sh File structure:

exec docker/entrypoint.sh: no such file or directory
project-name
	app
	bootstrap
	...
	docker
		entrypoint.sh

My dockerfile:

FROM php:8.1

RUN apt-get update -y && apt-get install -y \
    nodejs \
    npm \
    curl \
    zip \
    unzip \
    && docker-php-ext-install pdo pdo_mysql

RUN apt-get clean && rm -rf /var/lib/apt/lists/*

COPY . /var/www
WORKDIR /var/www

COPY --from=composer:2.4.2 /usr/bin/composer /usr/bin/composer

RUN useradd www -u 1000 -ms /bin/bash
RUN usermod -aG sudo www
RUN chown -R www:www /var/www

RUN npm init -y
RUN npm install -g n && n 16.17.0
RUN npm install

USER www
#RUN curl -sS https://getcomposer.org/installer | php
#RUN php composer.phar install
#
#RUN composer install --no-interaction --no-progress

RUN cd public && ln -sf ../storage/app/public/ storage

ENV PORT=8000
ENTRYPOINT [ "docker/entrypoint.sh" ]

and my docker-compose

version: "3.8"

networks:
  laravel:

services:
  nginx:
    image: nginx:stable-alpine
    container_name: ${APP_NAME}-nginx
    ports:
      - "80:80"
    volumes:
      - .:/var/www/html
      - ./default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
      - mysql
    networks:
      - laravel

  mysql:
    image: mariadb:latest
    container_name: ${APP_NAME}-db
    restart: unless-stopped
    tty: true
    ports:
      - "${DB_PORT}:3306"
    environment:
      - MYSQL_DATABASE=${DB_DATABASE}
      - MYSQL_USERNAME=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
    networks:
      - laravel

  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: ${APP_NAME}-app
    volumes:
      - .:/var/www/html
    ports:
      - "8000:8000"
    networks:
      - laravel

  composer:
    image: composer:latest
    container_name: ${APP_NAME}-composer
    volumes:
      - .:/var/www/html
    working_dir: /var/www/html
    networks:
      - laravel


nginx configuration this is copy paste from laravel docs

server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    root /var/www/html;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

0 likes
19 replies
cwhite's avatar
cwhite
Best Answer
Level 19

Might be because you're copying everything to /var/www in your Dockerfile (which I would advise against), and then you're mounting to /var/www/html in your nginx and php containers.

A couple of things you can do to clean things up:

  1. Don't copy everything in your Docker file, mount your code into the container in your docker-compose.
  2. Copy your entrypoint to /entrypoint.sh and make sure it's executable.
  3. Why do you have a separate composer container when you're installing composer in your php container?
  4. Your php container needs to expose port 8000.
  5. Your nginx config needs to fast_pass php:8000 instead of trying to use the php8.0 sock (which you don't even have installed).
1 like
raloseq's avatar

@cwhite Ok, thank you for tips. Deleted composer from docker-compose, changed /var/www to /var/www/html. Mount code u mean volumes or what?

2. I did this but nothing happens, still cant find entrypoint
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]
4. Like this?
ENV PORT=8000
EXPOSE 8000
ENTRYPOINT [ "docker/entrypoint.sh" ]
5. changed to this
fastcgi_pass php:8000;
cwhite's avatar

@raloseq I believe the path to the entrypoint is relative to the Dockerfile.

1 like
cwhite's avatar

@raloseq, And yes, I mean to use volumes so your changes in the Docker container are persisted to your local storage.

1 like
raloseq's avatar

@cwhite Ok my containers are "green" now in docker dekstop, and entrypoint is running but im getting directory index of "/var/www/html/" is forbidden. Do u know whats going on?

cwhite's avatar

@raloseq, your web root in nginx config should be something like root /var/www/html/public, not your laravel installation.

1 like
raloseq's avatar

@cwhite Ur right, but this docker is kinda problematic for me. Now i have Vite manifest not found at: /var/www/html/public/build/manifest.json

so i added npm run dev before php artisan serve --port=$PORT --host=0.0.0.0 in entrypoint.sh but that didn't solve the problem

cwhite's avatar

@raloseq, Why are you using artisan serve with nginx?

What are the contents of your entrypoint.sh?

1 like
raloseq's avatar

@cwhite Idk why i was just doing some tutorial.

#!/bin/bash

if [ ! -f "vendor/autoload.php"]; then
    composer install --no-progress --no-interaction
fi

if [ ! -f ".env" ]; then
    cp .env.example .env
fi

php artisan key:generate
php artisan migrate:fresh --seed
php artisan cache:clear
php artisan config:clear
php artisan route:clear

npm run dev
php artisan serve --port=$PORT --host=0.0.0.0
cwhite's avatar

@raloseq, have you tried using Laravel Sail? It's not for use in production but it should give you a good starting point to start tinkering with your containers.

If you're adamant about doing it yourself then there's a couple of things to clear up:

  1. php artisan serve starts a PHP development server...which is not necessary if you're trying to use nginx. The last command in entrypoint.sh should be php -a. Or you could just redefine CMD (you have to redefine the CMD command after defining an entrypoint) to be CMD ["php" "-a"]. However, I would use the php8.1-fpm image, so the command would just be CMD ["php-fpm"].
  2. You're using the entrypoint.sh file wrong (or at least I wouldn't place those commands in the entrypoint). You don't necessarily want all of those commands run every time you bring up the container (especially when you start to persist the database state with volumes). The contents of my entrypoint.sh file is below, and is used to a) create a non-root user with the same user id as the files in the host system (this is important to avoid permission issues, and b) run the CMD command as the non-root user so that the container properly responds to kill signals.

Config

entrypoint.sh

#!/bin/sh
set -e

USER=${USER:-www}
USER_ID=${USER_ID:-1000}

if [ -z $(id -u $USER 2>/dev/null) ]; then
    adduser --disabled-password --gecos '' --uid ${USER_ID} ${USER}

    mkdir -p /home/${USER}/.composer

    chown ${USER}:${USER} -R /home/${USER}
    chown ${USER}:${USER} /mnt
fi

# allow user to write to stdout and stderr
chown --dereference ${USER} /proc/self/fd/1
chown --dereference ${USER} /proc/self/fd/2

exec gosu ${USER} "$@"

Dockerfile

FROM php:8.1-fpm-buster

ENV WORKDIR=${WORKDIR:-/var/www}
ARG NODE_VERSION=18

RUN apt-get update \
    # apt complains this is missing
    && apt-get install -y apt-utils \
    && apt-get upgrade -y \
    && apt-get install -y --no-install-recommends \
        ghostscript \
        git \
        gpg \
        imagemagick \
        libc-client-dev \
        libfreetype6-dev \
        libjpeg-dev \
        libkrb5-dev \
        libltdl* \
        libmagickwand-dev \
        libpng-dev \
        libpq-dev \
        libx11-dev \
        libxml2-dev \
        libzip-dev \
        openssh-client \
        postgresql-client \
        rsync \
        supervisor \
        unzip \
        xfonts-base \
        xfonts-75dpi \
        zip \
    ;

# Configure PHP extensions
RUN docker-php-ext-configure gd --with-jpeg --with-freetype \
    && docker-php-ext-configure imap --with-kerberos --with-imap-ssl

# Install PHP extentions
RUN docker-php-ext-install \
    bcmath \
    gd \
    imap \
    opcache \
    pcntl \
    pdo_pgsql \
    zip

# Install the PECL PHP extensions
RUN pecl install imagick pcov \
    && pecl install -o -f redis \
    && rm -rf /tmp/pear \
    && docker-php-ext-enable imagick pcov redis

# Add composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Install NodeJS
RUN curl -sLS https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \
    && apt-get update \
    && apt-get install -y nodejs \
    && npm install -g npm

# Install gosu
RUN set -eux; \
	apt-get update; \
	apt-get install -y gosu; \
    # verify that the binary works
	gosu nobody true

RUN apt-get -y clean \
    && apt-get -y autoclean \
    && apt-get -y purge man \
    && apt-get -y autoremove \
    && rm -rf /var/lib/apt/{apt,dpkg,cache,log,lists}/* /tmp/* /var/tmp/* /usr/share/doc/*

COPY ./entrypoint.sh /
RUN chmod +x /entrypoint.sh

WORKDIR ${WORKDIR}

ENTRYPOINT ["/entrypoint.sh"]

CMD ["php-fpm"]
1 like
raloseq's avatar

@cwhite Thank you for the help but I'm thinking of staying with xampp for now because now i have another problem with nginx

[crit] 30 30: *2 connect() to unix:/var/run/php/php8.1-fpm.sock failed (2: No such file or directory) while connecting to upstream, client

server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    root /var/www/html/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # location = /favicon.ico { access_log off; log_not_found off; }
    # location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm-buster.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
cwhite's avatar

@raloseq, you're trying to connect to the .sock instead of the docker container

// this line
 fastcgi_pass unix:/var/run/php/php8.1-fpm-buster.sock;
// should be <docker_service_name>:<port>
 fastcgi_pass php:8000;
1 like
raloseq's avatar

@cwhite Ye ur right but it works with php:9000 for me. I hope that is the last question, where should i put npm run dev because when im trying to go into login page im getting Vite manifest not found at: /var/www/html/public/build/manifest.json

cwhite's avatar

@raloseq, I have a bash script that I run manually after bringing my containers up, if I'm starting fresh:

./docker/startup.sh (could probably think of a better name):

#!/bin/sh

docker exec -it -u www app composer install
docker exec -it -u www app npm install
docker exec -it -u www app npm run build

where www is the non-root user and app is the container name.

The reason why I do it this way is because I have volumes in my docker-compose that persist the state...so just because I bring the containers down/up doesn't mean I want these commands to run.

1 like
raloseq's avatar

@cwhite Thats weird but i was trying to run this command

docker exec -it -u www <container-name> npm run dev

and it gives me npm ERR! Missing script: "dev"

when i can see that in my project i have npm run dev

cwhite's avatar

@raloseq, what does the output of docker exec -it -u www <container-name> npm run show?

1 like
raloseq's avatar

@cwhite

npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /var/www/package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/var/www/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/www/.npm/_logs/2022-11-30T19_55_34_365Z-debug-0.log

cwhite's avatar

@raloseq, are you loading your files into /var/www or /var/www/html? I think there's a broken path...

1 like
raloseq's avatar

@cwhite Ok i changed

ENV WORKDIR=${WORKDIR:-/var/www}
to
ENV WORKDIR=${WORKDIR:-/var/www/html}

and its working now i have to figured out why are css not loading, why this app runs slow and fix some database errors but this is for another post or gonna fix it by myself. Thank you for the time that u spend here to help me :)

Please or to participate in this conversation.