Laravel10+Docker环境注册用户时出现权限拒绝错误求助
Laravel 10 Docker环境日志文件权限问题修复方案
问题描述
搭建Laravel 10的Docker环境后应用可正常运行,但尝试向数据库添加新用户时触发权限错误:
The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: Failed to open stream: Permission denied The exception occurred while attempting to log
已在Dockerfile中添加RUN chown -R www-data:www-data /var/www修改目录所有者,但问题仍未解决。
相关配置文件
Dockerfile
FROM php:8.2-fpm COPY php.ini /usr/local/etc/php/ COPY docker.conf /usr/local/etc/php-fpm.d/docker.conf COPY .bashrc /root/ RUN apt-get update \ && apt-get install -y build-essential zlib1g-dev default-mysql-client curl gnupg procps vim git unzip libzip-dev libpq-dev \ && docker-php-ext-install zip pdo_mysql pdo_pgsql pgsql RUN apt-get update && apt-get install -y \ libfreetype-dev \ libjpeg62-turbo-dev \ libpng-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) gd RUN apt-get install -y libicu-dev \ && docker-php-ext-configure intl \ && docker-php-ext-install intl RUN pecl install xdebug-3.2.1 \ && pecl install pcov \ && docker-php-ext-enable xdebug pcov \ && echo ";;zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini RUN apt-get update && apt-get install -y libmemcached-dev libssl-dev zlib1g-dev \ && pecl install memcached-3.2.0 \ && docker-php-ext-enable memcached RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get install -y nodejs RUN npm install npm@latest -g RUN npm install yarn -g RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php composer-setup.php RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin RUN composer config --global process-timeout 3600 RUN composer global require "laravel/installer" WORKDIR /root RUN git clone https://github.com/seebi/dircolors-solarized RUN chown -R www-data:www-data /var/www EXPOSE 5173 WORKDIR /var/www
docker-compose.yml
version: '3' name: laravel-project services: ### PHP ### php: build: .docker/php ports: - 5173:5173 container_name: project_php restart: unless-stopped volumes: - ./src:/var/www:cached ### Nginx ### nginx: image: nginx ports: - 80:80 container_name: project_nginx restart: unless-stopped volumes: - ./src:/var/www - .docker/nginx/default.conf:/etc/nginx/conf.d/default.conf - .docker/nginx/nginx.conf:/etc/nginx/nginx.conf depends_on: - php - db - redis ### Database (MySQL) db: image: mysql:8.1 ports: - 3306:3306 container_name: project_db_MySQL restart: unless-stopped volumes: - .docker/db/data:/var/lib/mysql - .docker/logs:/var/log/mysql - .docker/db/my.cnf:/etc/mysql/conf.d/my.cnf - .docker/db/sql:/docker-entrypoint-initdb.d environment: MYSQL_ROOT_PASSWORD: M$08154711$b MYSQL_DATABASE: indeed_db MYSQL_USER: indeed_user MYSQL_PASSWORD: qKFHxzq4yvtisrlNxPvS ### Database (MariaDB) # db: # image: mariadb:latest # ports: # - 3306:3306 # container_name: project_db_mariaDB # volumes: # - .docker/db/data:/var/lib/mysql # - .docker/logs:/var/log/mysql # - .docker/db/my.cnf:/etc/mysql/conf.d/my.cnf # - .docker/db/sql:/docker-entrypoint-initdb.d # environment: # MYSQL_ROOT_PASSWORD: root # MYSQL_DATABASE: laravel_db_name # MYSQL_USER: laravel_db_user # MYSQL_PASSWORD: laravel_db_pass ### phpMyAdmin ### phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8080:80 links: - db container_name: project_phpMyAdmin environment: PMA_HOST: db PMA_PORT: 3306 PMA_ARBITRARY: 1 volumes: - .docker/phpmyadmin/sessions:/sessions ### Redis ### redis: image: redis:latest container_name: project_redis restart: unless-stopped volumes: - redis:/var/lib/redis - redis-data:/data - redis-config:/us/local/etc/redis/redis.conf ports: - 6379:6379 command: ["redis-server", "--appendonly", "yes"] ### Mailpit ### mail: image: axllent/mailpit:latest ports: - 8025:8025 - 1025:1025 restart: unless-stopped container_name: project_mail_mailpit ### Mailhog ### # mail1: # image: mailhog/mailhog:latest # logging: # driver: "none" # container_name: project_mail_mailhog # restart: unless-stopped # ports: # - 8025:8025 # - 1025:1025 ### Redis-Commander # redis-commander: # image: rediscommander/redis-commander:latest # restart: unless-stopped # environment: # REDIS_HOSTS: local:redis:6379 # REDIS_PASSWORD: $(REDIS_PASSWORD) # HTTP_USER: root # HTTP_PASSWORD: M$08154711$b # container_name: project_redis_commander # ports: # - 8081:8081 # depends_on: # - redis volumes: redis: redis-data: redis-config:
Nginx default.conf
server { listen 80; index index.php index.html; root /var/www/public; client_max_body_size 100M; # 413 Request Entity Too Large location / { root /var/www/public; index index.html index.php; try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_read_timeout 3600; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; send_timeout 3600; proxy_connect_timeout 3600; proxy_read_timeout 3600; proxy_send_timeout 3600; } }
Nginx nginx.conf
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; server_tokens off; chunked_transfer_encoding off; gzip on; gzip_types application/json; gzip_min_length 1000; include /etc/nginx/conf.d/*.conf; }
问题原因
Dockerfile中执行chown的时机错误——构建镜像时修改了/var/www权限,但启动容器时本地./src目录被挂载到/var/www,挂载操作会覆盖容器内原目录的权限设置,导致storage目录的所有者为本地系统用户,而非容器内的www-data。
修复方案
方案1:容器启动后手动修正权限
进入PHP容器执行命令:
docker exec -it project_php chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
直接修正Laravel需要写入权限的两个核心目录。
方案2:添加容器启动脚本自动修正权限
- 在
.docker/php目录下创建startup.sh脚本:
#!/bin/bash chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache php-fpm
- 给脚本添加执行权限:
chmod +x .docker/php/startup.sh
- 修改Dockerfile,添加复制脚本并设置为启动命令:
在Dockerfile末尾追加:
COPY startup.sh /usr/local/bin/startup.sh RUN chmod +x /usr/local/bin/startup.sh CMD ["startup.sh"]
每次容器启动时,会自动修正权限后再启动php-fpm。
方案3:调整本地目录权限(开发环境适用)
在本地项目目录执行:
sudo chown -R 33:33 ./src/storage ./src/bootstrap/cache
33是Debian/Ubuntu系统中www-data用户默认的UID,挂载后容器内的www-data即可正常读写目录。
方案4:使用Laravel自带命令修复
进入容器执行:
docker exec -it project_php php artisan storage:link docker exec -it project_php chmod -R 775 /var/www/storage docker exec -it project_php chown -R www-data:www-data /var/www/storage
内容的提问来源于stack exchange,提问作者Mario Basten
相关产品推荐
相关产品推荐

