Abstract

When Dockerizing a Laravel application, it’s easy to end up with large, bloated images or frustrating permission errors. In this guide, you’ll learn how to properly configure your .dockerignore, manage file permissions, and keep your Laravel app working smoothly inside containers.

Understanding .dockerignore

The .dockerignore file is used to tell Docker which files and directories to ignore when building an image with docker build. It works similarly to .gitignore and helps optimize the image build process by:

  • reducing build context size (fewer files sent to the Docker daemon);
  • speeding up build times;
  • preventing sensitive files (e.g., .env, SSH keys) from being copied into the image;
  • avoiding unnecessary cache invalidation due to unrelated file changes.

.dockerignore must be placed in the Docker build context directory.

If your folder structure looks like this:

project-root/
├── Dockerfile
├── .dockerignore
└── src/ (your Laravel project)

And you run:

docker build -f Dockerfile .

Then project-root/ is the build context — so .dockerignore belongs there. All ignore rules will be relative to this context. This means paths like src/vendor in .dockerignore will correctly match project-root/src/vendor.

Laravel-Specific .dockerignore example

Here is an example of .dockerignore tailored for Laravel, assuming Laravel app lives in src/:

# Laravel vendor and frontend deps
src/vendor
src/node_modules
 
# Laravel cache and logs
src/storage/logs
src/storage/framework/cache/**
!src/storage/framework/cache/
 
# Environment files
src/.env
src/.env.*
 
# PHPUnit and tests (for production builds)
src/phpunit.xml
src/phpunit.xml.dist
src/tests
 
# Bootstrap cache
src/bootstrap/cache/**
!src/bootstrap/cache/
 
# Lock files
src/composer.lock
src/yarn.lock
src/package-lock.json
 
# Editor & OS junk
*.swp
*.swo
*.bak
*.tmp
*.log
*.idea
*.vscode
.DS_Store
Thumbs.db
 
# Git
.git
.gitignore

Preserving empty directories

Laravel expects certain directories to exist:

  • storage/framework/cache
  • bootstrap/cache

If you want to ignore the contents but keep the folders, use negation:

src/storage/framework/cache/**
!src/storage/framework/cache/
 
src/bootstrap/cache/**
!src/bootstrap/cache/

This ensures Docker keeps the folder structure but skips the files inside.

Fixing “permission denied” error

You might see this error when running the container:

The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: Failed to open stream: Permission denied

This means the user running PHP doesn’t have write permission to storage/, and we need to fix permissions. Add the following after copying your project:

RUN chown -R www-data:www-data storage bootstrap/cache \
    && chmod -R ug+rwX storage bootstrap/cache

This command ensures the web server user (www-data) owns the necessary directories and has the correct write permissions.

Recap

  • Place .dockerignore in the build context, not just next to the Dockerfile.
  • Ignore the vendor and logs folders.
  • Preserve Laravel folder structure with negation (!folder/).
  • Fix permissions for storage/ and bootstrap/cache.