I have also noticed that files and folders in the NGINX server are owned by root. I have tried several options including building with --no-cache option but still NGINX tries to read exactly same non-existent file.
Mar 30, 2026
2
Level 2
NGINX server reading wrong css asset file in production following this guide https://docs.docker.com/guides/frameworks/laravel/production-setup/#create-a-docker-compose-configuration-for-production
For my setup, the Laravel app is inside src folder while all other docker setup files are outside src folder. My Dockerfile for NGINX container:
FROM node:22-alpine AS builder
WORKDIR /app
# Copy Laravel application code
COPY ./src/. /app
RUN npm install && npm run build
FROM nginx:1.21-alpine
COPY --from=builder /app/public /var/www/public
COPY ./nginx/nginx.conf /etc/nginx/conf.d/nginx.conf
WORKDIR /var/www/public
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
The main Dockerfile is:
FROM php:8.4-fpm AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
unzip \
libpq-dev \
libonig-dev \
libssl-dev \
libxml2-dev \
libcurl4-openssl-dev \
libicu-dev \
libzip-dev \
&& docker-php-ext-install -j$(nproc) \
pdo_mysql \
pdo_pgsql \
pgsql \
opcache \
intl \
zip \
bcmath \
soap \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /var/www
COPY ./src/. /var/www
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist
FROM php:8.4-fpm AS production
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq-dev \
libicu-dev \
libzip-dev \
libfcgi-bin \
procps \
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY ./php/uploads.ini /usr/local/etc/php/conf.d/uploads.ini
RUN curl -o /usr/local/bin/php-fpm-healthcheck \
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck \
&& chmod +x /usr/local/bin/php-fpm-healthcheck
COPY ./src/storage /var/www/storage-init
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
COPY --from=builder /usr/local/bin/docker-php-ext-* /usr/local/bin/
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
#COPY --from=builder /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN set -eux;{ echo '[www]'; echo 'pm.status_path = /status'; } > /usr/local/etc/php-fpm.d/my-fpm.conf
COPY --from=builder /var/www /var/www
WORKDIR /var/www
RUN chown -R www-data:www-data /var/www
USER www-data
RUN php artisan config:cache
RUN php artisan view:cache
RUN php artisan route:cache
#ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
And the docker-compose.yml file is:
version: "3.7"
services:
nginx:
build:
context: ./
dockerfile: ./nginx/Dockerfile
container_name: nginx
tty: true
restart: unless-stopped
ports:
- "8456:80"
env_file:
- ./src/.env
volumes:
- storage-production:/var/www/storage:ro
depends_on:
app:
condition: service_healthy
networks:
- laraapp
app:
build:
context: ./
dockerfile: Dockerfile
target: production
restart: unless-stopped
image: app-1
container_name: app
healthcheck:
test: ["CMD-SHELL", "php-fpm-healthcheck || exit 1"]
interval: 10s
timeout: 5s
retries: 3
depends_on:
db:
condition: service_healthy
env_file:
- ./src/.env
volumes:
- storage-production:/var/www/storage
ports:
- "9031:9000"
networks:
- laraapp
db:
image: mysql/mysql-server:8.0
container_name: db
restart: unless-stopped
tty: true
ports:
- "3336:3306"
env_file:
- ./src/.env
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "===Uy"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./mysql:/etc/mysql/conf.d/
- ./mysqlinit:/docker-entrypoint-initdb.d
- mysqldata:/var/lib/mysql
networks:
- laraapp
redis:
image: redis:alpine
restart: unless-stopped # Automatically restart unless the service is explicitly stopped
networks:
- laraapp
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
networks:
laraapp:
driver: bridge
volumes:
mysqldata:
storage-production:
The problem is that when I deploy the app, NGINX server is reading non-existent CSS file:
"GET /build/assets/app-6483e3d7.css HTTP/1.0" 404 6603
instead of the one actually deployed to the build assets folder, leading to a broken CSS page:
app-b3fca3b4.css
Please or to participate in this conversation.