Skip to main content
Version: v1

Environment

Your local environment is a Docker Compose stack built from Lagoon container images, the images Lagoon runs in production. Ahoy wraps the longer docker compose commands into short ones.

This section is for developers working day to day on a project built from Vortex. After reading this page, you can do the following:

  • Tell which files Git, the image build and the deployment artifact leave out
  • Switch branches without a full rebuild
  • Reset the project to a clean state
  • Change an environment variable and get the new value into the containers

In this section​

Each layer of the stack has its own page in this section:

PageWhat it covers
DockerThe container stack and the docker-compose.yml anatomy
PygmyThe shared proxy, DNS, SSH agent and mail catcher services
AhoyCommand shortcuts, configuration and running CLI commands
DoctorStack diagnostics and system information
DrushThe Drupal CLI, its configuration and aliases
LogsContainer logs and the Drupal watchdog log
DebuggingXdebug, authenticated requests and container debugging
TroubleshootingCommon local stack failures and fixes

Ignored files​

Vortex writes its 3 ignore files as deny lists. Every file is included by default, and each ignore file lists only what must stay out of its target. This follows the "avoid silent errors" principle: a file you add is visible by default. With an allow list, a new file would stay excluded until someone remembered to allow it.

The .gitignore file controls which paths Git ignores in the project repository. It excludes the following:

  • Directories that Composer and npm generate, such as web/core, web/modules/contrib, vendor and node_modules
  • The Drupal scaffold files that the build copies into web/
  • Compiled theme assets in web/themes/**/build
  • With Storybook, the generated *.stories.json files and the storybook-static output
  • Local overrides: .env.local, .ahoy.local.yml, docker-compose.override.yml, settings.local.php and services.local.yml
  • Content files and test artifacts in web/sites/*/files and web/sites/simpletest
  • Caches, data, logs and temporary artifacts in .artifacts, .data, .logs, .phpunit.cache and .twig-cs-fixer.cache

.gitignore keeps 2 sections as small allow lists, because a deny rule can't express them:

  • recipes/ - Composer installs contributed recipes next to your custom ones, so each custom recipe is un-ignored explicitly.
  • .claude/ - Claude writes machine-local state here, so only .claude/settings.json and .claude/skills/ are un-ignored by default. This section is present when the installer adds the AI agent instructions.

The other 2 ignore files apply the same deny-list model to different targets:

A new file or directory that no entry matches is included in all 3 targets. Git tracks it after you commit it. Add an entry to an ignore file only when a file must stay out of that target.

Switch branches​

After you switch branches, skip the full rebuild. Run only the commands that match what changed:

# Update Composer packages (only if composer.json/composer.lock changed)
ahoy composer install
# Rebuild frontend assets (only if theme files changed)
ahoy fe
# Provision site (only if database or configuration changes expected)
ahoy provision

If the branch changes docker-compose.yml or a file in .docker/, rebuild the images and recreate the containers with ahoy up --build, or docker compose up -d --build without Ahoy.

Confirm that the stack is healthy: ahoy doctor ends with [ OK ] All required checks have passed.

Reset the project​

ahoy reset takes the stack down and deletes what the build installed, so your next ahoy build starts clean. After you confirm, it runs ahoy down, which removes the containers and their volumes, your local database included. ahoy reset then deletes the following:

  • vendor
  • Every node_modules directory
  • web/core
  • The contrib directories in web/modules, web/profiles and web/themes

ahoy reset --hard also returns the repository to a freshly cloned state at the current commit. After the soft reset, it runs these steps:

  1. Deletes every file that .gitignore matches.
  2. Discards uncommitted changes to tracked files (git reset --hard).
  3. Removes every other untracked file (git clean -f -d).
  4. Removes empty directories.

The hard reset deletes your .env.local, the database dumps in .data and every other local override, so copy out anything you want to keep first.

The following commands run each kind of reset:

# Reset local environment
ahoy reset
# Fully reset repository to a state as if it was just cloned
ahoy reset --hard

Confirm that the reset finished: the last line it prints is [ OK ] Finished reset.

Environment variables​

.env holds the values for the whole team, and .env.local holds the values for your machine only. A value in .env.local overrides the one in .env. A variable exported in your shell overrides both.

To change a variable that docker-compose.yml passes to the containers, such as DRUPAL_THEME:

  1. Set the new value in .env.local or in .env.
  2. Recreate the containers (a plain restart keeps the old value):
ahoy up

ahoy up loads both files before it calls Docker Compose. Docker Compose on its own reads only .env, so the Docker Compose command applies only .env changes. To include .env.local without Ahoy, pass both files: docker compose --env-file .env --env-file .env.local up -d.

Confirm that a container has the new value with docker compose exec cli printenv VARIABLE_NAME, where VARIABLE_NAME is the name of the variable you changed.

Drupal also reads variables that docker-compose.yml doesn't pass, such as DRUPAL_CLAMAV_ENABLED. For web requests, PHP-FPM loads them from .env when its container starts and never reads .env.local. To apply a change to .env, run ahoy restart or docker compose restart. A change to these variables leaves the container's configuration as it was, so ahoy up keeps the container running.

To set such a variable on your machine only, such as a credential that must stay out of the committed .env:

  1. Pass the variable to the php service in docker-compose.override.yml:

    docker-compose.override.yml
    services:
    php:
    environment:
    DRUPAL_EXAMPLE_API_KEY: ${DRUPAL_EXAMPLE_API_KEY:-}
  2. Set its value in .env.local.

  3. Run ahoy up.

A variable that only the vendor/bin/vortex-* scripts use, such as VORTEX_PROVISION_OVERRIDE_DB, takes effect without recreating anything, because the scripts read both files each time they start. The Docker page explains how each value reaches a container.

➡️ See Variables for the full variable reference.