Spiegando l’uso delle variabili d’ambiente in Docker

L’utente chiede come configurare Laravel per usare le variabili d’ambiente direttamente dal container Docker, non dal file “.env” all’interno del codice. Quando definisci variabili d’ambiente nel Docker tramite env_file: .env, Docker carica quei valori nel container. Per Laravel, puoi usare $_ENV o getenv() per accedere a queste variabili. Docker gestisce l’invio delle variabili automaticamente all’interno del container, quindi Laravel riceverà quest’ultime senza bisogno di un file .env separato.

Spiegando l’ambiente in container con Laravel

Per Laravel in un container, possiamo passare variabili d’ambiente al container e Laravel le legge tramite getenv() o dal file .env. Se il file .env non è presente, Laravel cercherà le variabili d’ambiente dell’OS. Se usiamo Docker, possiamo passare le variabili dal file docker-compose.yml o dal parametro env_file. È importante che Dotenv di Laravel non sovrascriva le variabili già impostate nel container. Per evitare conflitti, possiamo evitare di usare un file .env all’interno del container.

Soluzione per l’uso delle variabili d’ambiente in container

Per utilizzare le variabili d’ambiente del container con Laravel, ti consiglio di montare il file .env nel container tramite docker-compose.yml, definendo le variabili nel file env_file. Puoi anche evitare di usare un .env all’interno del container e affidarti solo alle variabili d’ambiente, modificando la configurazione di Laravel per leggere direttamente da env() senza config. Docker caricherà le variabili al momento dell’avvio, e Dotenv non sovrascriverà le variabili già presenti.

Soluzione pratica — passare le variabili dal container a Laravel

  1. Crea un file di variabili solo per il container (teniamolo fuori dalla cartella src per non committarlo):

    # ./larapuk.env       (stesso livello di docker‑compose.yml)
    APP_ENV=production
    APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxx
    APP_URL=https://larapuk.lpuk.it
    
    DB_CONNECTION=mysql
    DB_HOST=db
    DB_PORT=3306
    DB_DATABASE=larapuk
    DB_USERNAME=larapuk
    DB_PASSWORD=super‑password
    
    CACHE_DRIVER=redis
    QUEUE_CONNECTION=redis
    REDIS_HOST=redis
    
  2. Collega quel file al servizio aggiungendo (o sostituendo) la sezione nel tuo docker-compose.yml:

    services:
      larapuk:
        build:
          context: .
          dockerfile: Dockerfile
        image: larapuk
        container_name: larapuk
        restart: unless-stopped
     
        env_file:
          - ./larapuk.env          # ← puntiamo al file appena creato
     
        networks:
          - proxy
          - core
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.larapuk.rule=Host(`larapuk.lpuk.it`)"
          - "traefik.http.routers.larapuk.entrypoints=websecure"
          - "traefik.http.routers.larapuk.tls=true"
          - "traefik.http.routers.larapuk.tls.certresolver=letsencrypt"
          - "traefik.http.services.larapuk.loadbalancer.server.port=80"
        expose:
          - "80"
  3. (Opzionale ma consigliato) rimuovi o rinomina il file .env dentro src quando costruisci l’immagine di produzione, così eviti conflitti e non hai segreti nel repository.

    • In locale puoi continuare a usare .env; basta non copiarlo nell’immagine (.dockerignore, COPY selettivo o RUN rm .env nel Dockerfile).
  4. Ricostruisci e avvia di nuovo:

    docker compose up -d --build
  5. Verifica dentro al container che le variabili ci siano:

    docker exec -it larapuk printenv | grep APP_

Perché funziona — il percorso delle variabili in Docker + Laravel

MomentoDove viene impostata la variabileHa la precedenza su …
docker run / docker‑compose environment:riga di comando, variabili passate direttamentetutto il resto
env_file nel docker-compose.ymlfile che hai appena creato (larapuk.env)ENV definite nel Dockerfile
istruzione ENV nel Dockerfilevariabili “di default” dell’immaginenessuna (è il livello più basso)

Nota: ARG nel Dockerfile esiste solo in fase di build (serve a passare parametri al Dockerfile), non sopravvive nel container.

Quando il container parte:

  1. Il kernel prepara lo “environment” del processo PID 1 (nel tuo caso php-fpm o artisan …) con tutte le variabili dei livelli mostrati sopra.

  2. Laravel bootstrap: prima carica eventualmente il file .env con vlucas/php‑dotenv; questa libreria per default non sovrascrive variabili già presenti.

  3. Ogni chiamata env('FOO') in un file di configurazione legge prima dall’environment di sistema, poi dal .env, poi dal valore di default fornito nel codice.

Quindi, se nel container esiste DB_HOST=db, quel valore vince sullo stesso nome presente nel .env. Se elimini il .env dentro l’immagine, il passaggio (2) non fa nulla e avrai un’unica sorgente di verità: le variabili del container.


Attenzione a config:cache

Se nel Dockerfile esegui php artisan config:cache (ottimo per performance) ricorda che il comando deve avvenire dopo che le variabili sono già presenti. In pratica:

# (estratto)
COPY . /var/www/html
# NON copiare .env qui, se lo usi solo in locale
 
# qui le variabili da env_file NON esistono ancora
RUN composer install --no-dev --optimize-autoloader
 
# sposta config:cache in un entrypoint o script di startup
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

docker-entrypoint.sh (semplificato):

#!/bin/sh
php artisan config:cache
exec php-fpm   # o supervisord, ecc.

In questo modo la cache viene creata con i valori reali.


  • env_file in compose → carica KEY=VALUE nel runtime del container.

  • Laravel preferisce quei valori rispetto al .env interno.

  • Evita di copiare .env sensibili nella build e gestisci l’eventuale config:cache dopo che le variabili esistono.
    Così hai una pipeline pulita: un’unica fonte di configurazione per produzione, nessun segreto nel repository e comportamento prevedibile.