Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The quickest reproducible Drupal setup is a two-service Docker Compose project: a Drupal 10 Apache container and a PostgreSQL 16 container. Create a compose.yaml, start it with docker compose up, open http://localhost:8080, and enter postgres as Drupal’s database host. That hostname is the Compose service name; localhost would point back to the Drupal container and fail.

The short example below is suitable for local development. The guide then adds named volumes for Drupal files and PostgreSQL data, explains the installer fields, compares SQLite, MySQL, and PostgreSQL, and covers the failures most often encountered during first startup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What you need before installing

Docker and Compose

Install Docker Desktop on Windows or macOS, or install Docker Engine, the Docker CLI, and the Docker Compose plugin on Linux. Confirm that both commands work before creating the project:

docker --version
docker compose version

Docker Desktop is convenient for development because it bundles the engine and Compose. Linux is the usual choice for hosting; Drupal documentation describes Windows as supported for development environments. You do not need PHP or PostgreSQL installed directly on the host when both run in containers.

Hardware and Drupal requirements

  • Drupal’s 2025 requirements guidance lists about 100 MB for core files. A real site needs additional space for modules, themes, uploaded media, backups, logs, and generated files.
  • The same guidance lists PHP 8.3 or a higher PHP 8 version and a minimum PHP memory size of 64 MB. In a container deployment, the Drupal image supplies PHP, but every module still has to be compatible with the PHP version and extensions in that image.
  • Keep enough memory for both containers and for PostgreSQL’s working data. A small local site may start with modest resources, while imports, image processing, search, and large caches require more.

Create the Compose project

Make a directory

Create a new directory and change into it. Keeping the Compose file and any environment file together makes later upgrades and backups easier.

mkdir drupal-compose
cd drupal-compose

Write compose.yaml

Save the following as compose.yaml. It follows the Drupal Docker Official Image example and adds explicit named volumes, including a PostgreSQL data volume that the short example omits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
services:
  drupal:
    image: drupal:10-apache
    ports:
      - '8080:80'
    volumes:
      - drupal_modules:/var/www/html/modules
      - drupal_profiles:/var/www/html/profiles
      - drupal_themes:/var/www/html/themes
      - drupal_sites:/var/www/html/sites
    restart: always
  postgres:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: always

volumes:
  drupal_modules:
  drupal_profiles:
  drupal_themes:
  drupal_sites:
  postgres_data:

The Drupal service publishes container port 80 as port 8080 on your computer. The four Drupal mounts let the image initialize those directories while keeping modules, installation profiles, themes, and the sites tree when the container is recreated. The PostgreSQL mount stores the database cluster outside the writable container layer.

example is intentionally easy to recognize, not a production password. Replace it before exposing the stack beyond your own machine. If you change the value, use the same value in Drupal’s installer. For a shared project, place the password in an environment file and protect that file rather than committing a real secret to source control.

Start the containers

Run Compose

From the directory containing compose.yaml, run:

docker compose up

Compose pulls the Drupal and PostgreSQL images if they are not already present, creates a private network, creates the named volumes, and starts both services. The command stays attached so you can see initialization messages. When you prefer the terminal back, stop with Ctrl+C and restart in the background with docker compose up -d.

Wait for initialization to finish, then open http://localhost:8080. The Docker image documentation describes the same sequence: run docker compose up, wait for initialization to complete, and visit the published port. If port 8080 is already occupied, change the left side of the mapping, for example '8081:80', and browse to http://localhost:8081.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check service status and logs

In a second terminal, inspect the project:

docker compose ps
docker compose logs -f drupal
docker compose logs -f postgres

docker compose ps should show both services running. Log output is useful during the first database initialization; PostgreSQL can take longer than Apache to become ready. A Drupal page that appears before PostgreSQL is ready may show a connection error. Wait, refresh the browser, and check the PostgreSQL log before changing credentials.

Complete Drupal’s browser installer

Choose the installation profile

At http://localhost:8080, select the profile appropriate for your site, normally the standard profile for a general installation. Continue until Drupal displays the database configuration form.

Enter PostgreSQL settings

Select PostgreSQL and enter these values for the Compose file above:

Drupal field Value Why
Database name postgres The default database supplied by the PostgreSQL image when no alternate database name is configured.
Database username postgres The default PostgreSQL superuser created by the image.
Database password example Matches POSTGRES_PASSWORD in compose.yaml; use your replacement value if you changed it.
Database host postgres The Compose service name and an address resolvable by the Drupal container on the internal network.
Database port 5432, or the prefilled default PostgreSQL’s container port. It is not the host’s published web port.

Do not enter localhost for the database host. Inside the Drupal container, localhost means that same Drupal container, where PostgreSQL is not running. Compose’s internal DNS resolves the service name postgres to the database container.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If you later rename the service, change the host in Drupal’s settings to the new service name. If you define POSTGRES_DB, a different PostgreSQL user, or a different password, enter those exact values instead of the defaults shown above.

Finish the site setup

Continue through the form and provide the site name, an administrator account, an administrator password, an administrator email address, and the requested regional settings. Drupal’s Composer documentation describes these database credentials, administrator fields, and basic site information as part of the web setup. Use a strong, unique administrator password even on a development machine if the machine is shared.

When installation completes, sign in and confirm that the front page loads. Check that the administration pages can write configuration and that the sites directory contains the installed site data. Those checks validate that the mounted Drupal volume is writable.

How persistence works

Drupal files

The named volumes in the example hold the directories most commonly changed after installation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • drupal_modules stores contributed or custom modules placed under modules.
  • drupal_profiles stores installation profiles.
  • drupal_themes stores themes.
  • drupal_sites stores site-specific settings, uploaded files, and other per-site data under sites.

Container recreation does not erase these volumes. A new Drupal container mounts the same data and can continue serving the installed site. The image’s original example uses volume mounts at these paths for the same initialization and retention behavior; naming them explicitly makes the data easier to identify and manage.

PostgreSQL data

postgres_data is mounted at PostgreSQL’s data directory. Without that mount, deleting and recreating the PostgreSQL container can remove the database stored in its writable layer. The short official example does not show a PostgreSQL volume, so add one before treating that example as durable.

Do not remove the volumes casually. docker compose down stops and removes the containers but normally leaves named volumes. docker compose down -v also removes the named volumes and therefore deletes the Drupal files and PostgreSQL database in this project. Use the latter only when you intentionally want a clean, irreversible local reset.

Backups are separate from volumes

A volume is persistence, not a backup. Protect the PostgreSQL database with regular PostgreSQL dump or snapshot procedures, and copy the Drupal sites data and any custom modules or themes. Test restoration on a separate project. A failed disk, mistaken volume deletion, or corrupted database can affect both containers even though the volumes are correctly configured.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a database for your use case

Drupal supports MariaDB, MySQL, PostgreSQL, and SQLite. The right choice depends on whether the project is disposable, how closely development should resemble production, and what database your hosting environment already provides.

Database Containers Operational complexity Existing-hosting compatibility Backup approach Development-to-production similarity
SQLite One Drupal container; no database service Lowest for a quick local demo Depends on whether production supports SQLite Back up the SQLite database file and Drupal files together Best when production also uses SQLite; otherwise limited
PostgreSQL Drupal plus a PostgreSQL service Requires a database container, credentials, volume, and database backups Strong when the target host uses PostgreSQL Use PostgreSQL’s dump and restore tooling plus file backups Good match for a multi-service PostgreSQL deployment
MySQL Drupal plus a MySQL service Similar two-service management and persistence concerns Strong when the target host uses MySQL or MariaDB Use the selected server’s dump and restore tooling plus file backups Good match when production is MySQL-compatible

SQLite is convenient for a disposable experiment because it avoids a second container. PostgreSQL or MySQL is usually the more representative choice for a site that will move to a multi-service deployment. Switching databases later is a migration project, not a simple change of one installer field, so choose based on the intended destination.

Use SQLite instead of PostgreSQL

The Drupal image supports SQLite without a second database container. Remove the PostgreSQL service and its volume, start only Drupal, and select SQLite in the installer. Drupal will ask for a database file location rather than a network host and password. Keep the Drupal sites volume because it must retain the SQLite file and uploaded files.

SQLite is a sensible choice for a throwaway demonstration or a very small local test. It is less suitable when you need to reproduce production behavior that depends on a separate database server, database-specific extensions, or operational tooling.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use MySQL or MariaDB

MySQL and MariaDB also require a separate database service. Add the matching official database image, configure its initialization variables, mount its data directory, and use the Compose service name as Drupal’s database host. The database type selected in Drupal must match the server you actually started, and the database name, username, password, and host must match the environment and service names in Compose.

Do not copy PostgreSQL-specific values blindly. PostgreSQL’s default user and port are not universal MySQL or MariaDB settings. Decide the database engine first, then use that engine’s image documentation for its supported environment variables and data path.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Install modules that need extra PHP extensions

The Drupal image does not contain every PHP extension that every contributed module may require. If Drupal reports a missing extension, first identify the module’s stated requirement and verify that the extension is absent from the image. Do not edit a running container as a permanent fix; those changes disappear when the container is replaced.

Build a custom image with a Dockerfile that starts with the Drupal image, installs the required extension using the image’s supported build procedure, and then changes the Compose service from image: drupal:10-apache to a local build: configuration. Rebuild and recreate the service after changing the Dockerfile. Keep the Dockerfile under version control so another developer or deployment system can reproduce the same PHP environment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Upgrade and operate the project

Inspect before changing anything

docker compose ps
docker compose images
docker compose logs --tail=100 drupal
docker compose logs --tail=100 postgres

Confirm which image tags are running and whether the site is healthy before an upgrade. Keep a database backup and a copy of Drupal files before changing major Drupal or database versions.

Pull newer image builds

docker compose pull
docker compose up -d

Pulling obtains newer images allowed by the tags, and up -d recreates services when their image changes while reusing the named volumes. Image updates do not automatically perform every Drupal application update; follow Drupal’s upgrade procedure for the specific core and module versions you use.

Stop without deleting data

docker compose down

This removes the project’s containers and network while retaining the named volumes. Start it again with docker compose up -d. The Drupal installer should not appear again because the site files and database remain.

Troubleshooting common failures

The browser cannot connect

  • Run docker compose ps and confirm the Drupal service is running.
  • Check that you opened the host port shown in the ports mapping, normally http://localhost:8080.
  • If another application owns port 8080, change the host side to an unused port such as 8081:80 and use the corresponding URL.
  • Read docker compose logs drupal for an image pull, Apache startup, permission, or PHP error.

Drupal cannot connect to PostgreSQL

  • Set the database host to postgres, not localhost or the host computer’s IP address.
  • Verify that the password in the installer exactly matches POSTGRES_PASSWORD.
  • Check that the PostgreSQL container is running and has finished initialization with docker compose logs postgres.
  • If you changed database environment variables after the first startup, remember that PostgreSQL initialization variables generally apply only when its data directory is first created. For a disposable project, stop the stack, remove the named volume deliberately, and start again; for a valuable site, migrate credentials without deleting the data.

The installer keeps reappearing

This usually means Drupal is seeing a new or empty sites volume, or it is connecting to a new empty database. Check that the Compose project directory and service names are unchanged, inspect the volumes with docker volume ls, and ensure you did not run docker compose down -v. Also verify that the PostgreSQL volume is mounted at /var/lib/postgresql/data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A module reports a missing extension

Read the module’s requirements, then build a custom Drupal image that includes the extension. Recreating the stock image will not add software that the image does not contain.

Files or configuration are not writable

Inspect the Drupal logs and the mounted paths. The sites volume must be writable by the web process, and custom bind mounts must have permissions that allow the container to read and write as required. Named volumes avoid many host filesystem permission surprises during an initial setup.

When this Compose setup is appropriate

  • Local development: Use the supplied file to create a repeatable Drupal and PostgreSQL environment without installing PHP or a database on the host.
  • Training and demonstrations: SQLite can reduce setup to one container when the database server itself is not part of what you are demonstrating.
  • Pre-production testing: PostgreSQL or MySQL in a second service is closer to a typical multi-service deployment and exposes networking, credentials, and persistence issues early.
  • Public production hosting: Harden passwords, protect the Docker host, configure backups and monitoring, pin and review image versions, use TLS through an appropriate front end, and follow Drupal’s production security and update practices. The simple file is a starting point, not a complete production architecture.

Final verification checklist

  • docker --version and docker compose version return successfully.
  • Both services are running in docker compose ps.
  • The Drupal page opens on the host port you selected.
  • The installer uses PostgreSQL with database host postgres.
  • The database name, user, and password match the PostgreSQL environment.
  • Named volumes exist for Drupal paths and PostgreSQL data.
  • docker compose down followed by docker compose up -d returns to the installed site.
  • You have a separate backup plan for the database and Drupal files before treating the environment as important.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.