Muhammad Yasir Amin

Loading websiteโ€ฆ

More from Muhammad Yasir Amin

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Subscribe on YouTube

Laravel Docker: Set Up Environment Variables for Production

๐Ÿ› ๏ธ Laravel Tutorials4 min read

Laravel Docker: Set Up Environment Variables for Production

Muhammad Yasir Amin

Muhammad Yasir Amin

Senior Full Stack Engineerโ€ขNov 6, 2026
Laravel Docker: Set Up Environment Variables for Production

To set environment variables for Laravel in Docker production, do not bake your .env file into the image. Pass the values when the container starts, using environment or env_file in Docker Compose, --env-file with docker run, or your platform's secret store. Then run php artisan config:cache so Laravel reads configuration from a cached file. This keeps one image usable across staging and production.

This guide targets Laravel 13 on PHP 8.3 or newer. The same ideas apply to Laravel 12.

Why not copy .env into the image?

  • Anyone who can pull the image can read the secrets in its layers.
  • The same image can no longer be promoted from staging to production, because the values are fixed.
  • Rotating a password means rebuilding and redeploying the image.

Laravel's own documentation says .env should not be committed to source control, because each environment may need a different configuration. The same reasoning applies to image layers.

Step 1: Which variables does production need?

At minimum, set these. Generate a key once with php artisan key:generate --show and store it safely.

Shell
APP_NAME=MyApp
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:generate-this-once
APP_URL=https://example.com

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=use-a-strong-secret

LOG_CHANNEL=stderr
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

APP_DEBUG=false is essential in production. With debug on, error pages can expose configuration values. LOG_CHANNEL=stderr sends logs to the container output so docker logs and your log collector can see them.

Step 2: How do I pass variables with Docker Compose?

Keep a production file, for example .env.production, on the server and outside Git. Reference it from compose:

YAML
services:
  app:
    image: yourname/laravel-app:1.0.0
    env_file:
      - .env.production
    environment:
      APP_ENV: production
    restart: unless-stopped

Values under environment win over values from env_file, which is handy for small overrides. I did not deploy this file for the article; it follows the Compose documentation.

How do I pass variables with docker run?

Code
docker run -d --name laravel-app \
  --env-file /srv/laravel/.env.production \
  -e APP_ENV=production \
  yourname/laravel-app:1.0.0

Avoid long -e DB_PASSWORD=... arguments on a shared machine. They can show up in the shell history and in process listings.

Step 3: How do I cache the configuration?

Run these when the container starts, after the variables exist. An entrypoint script is a good place:

Code
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

Do not run them during docker build for secrets that only exist at runtime. The cached config would contain the values available at build time, which may be empty or wrong.

Why does env() return null after config:cache?

Once the configuration is cached, the .env file is no longer loaded for each request, and env() calls outside config files return null. Use env() only inside files in the config directory, and read values elsewhere with config('app.name'). This is the most common production surprise.

How can I handle secrets more safely?

  • Use Docker or Compose secrets, or your cloud provider's secret manager, and inject them at runtime.
  • Laravel can encrypt an environment file with php artisan env:encrypt so the encrypted copy may be stored with the code, and decrypt it with php artisan env:decrypt using a key you keep elsewhere. Check the configuration docs for options and flags.
  • Limit who can read the server's env file with file permissions.

How do I verify the values inside the container?

  1. Start the container.
  2. Run docker compose exec app php artisan about. It prints the environment, debug flag and cache status.
  3. Run docker compose exec app php artisan config:show app to see the resolved app configuration. Avoid pasting this output anywhere public.
  4. Open the site and confirm that no debug page appears for a missing route.

What are the common mistakes?

  • Committing .env. Add it to .gitignore and .dockerignore.
  • APP_DEBUG=true in production. It leaks details on errors.
  • Changing .env and expecting an effect. With cached config, run php artisan config:clear or restart the container so the entrypoint rebuilds the cache.
  • Quoting problems in env files. Compose treats quotes in env_file values literally in some versions. Test a value that contains spaces or #.
  • Missing APP_KEY. Encrypted cookies and sessions fail without it.
  • Changing APP_KEY later. It invalidates sessions and encrypted data.

FAQ

Can I use the same image for staging and production?

Yes, that is the goal. Build once, tag it, and start it with a different env file in each environment.

Where should migrations run?

Run php artisan migrate --force as a deployment step before or while switching traffic. The --force flag is required to run migrations in production.

Does Laravel read the .env file in Docker automatically?

Yes, if the file exists in the application directory. Real environment variables set by Docker take precedence over the file, which is why runtime injection works.

References

Article Index & Topic Tags
DockerLaravelDeploymentEnvironment

YouTube Channel

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Muhammad Yasir Amin
Available for Contracts
Author & Solutions Architect

Senior Full Stack Engineer

Independent Senior Full Stack Engineer working on Laravel, React and Next.js applications, APIs and delivery workflows.

Laravel & PHP ApplicationsReact & Next.js InterfacesREST APIs & IntegrationsDatabase Queries & DebuggingDocker Development WorkflowsClear Scope & Handover
Discuss Your Next Step

What Does Your Application Need Next?

Share your current system, the problem you want to solve and what a useful result looks like. We can identify the right starting point and agree on a practical scope.

Technical Audit

Find the Next Useful Fix

Application Development

Scoped, Reviewable Milestones

Ongoing Support

Agreed Capacity and Priorities

Share your goals, current stack and requirements before the call.