The stack consists of:
- PHP 8.4 (FPM) under Debian Bullseye
- MariaDB 11.8.8 under Debian
- Caddy 2.11.4
- Redis 8.2.7
The compose stack will take care of building a customized PHP container image with the necessary extensions.
- Pre-configured Caddy server (except domain)
- Dotfiles blocked (except
.well-known/) - HTTPS ready; easy to set up with a reverse proxy
- Dotfiles blocked (except
- Pre-configured MariaDB 11.8.8
- Secure access - inaccessible from outside, even the host itself
- Pre-configured PHP 8.4 for Shopware
- Pre-installed modules:
mbstring,gd,intl,pdo_mysql,zip,exif,redis - Pre-configured and enabled opcache
- GD compiled with WebP, JPEG, PNG, AVIF and XPM support
- Increased memory limit to 512M
- Increased execution time limit to 3m
- Pre-installed modules:
- Pre-configured background service runners for Shopware 6
messenger:consume- Runs as a separate container
- Memory limit: 512MB
scheduled-task:run- Runs as a separate container
- Memory limit: 512MB
All Docker images are version-locked to ensure maximum stability. Caddy and MariaDB are strictly locked and need to be manually updated in the Compose file. PHP is is only locked to version 8.3, so minor updates are available automatically when rebuilding the image.
| Shopware version | Supported |
|---|---|
| 6.6.10.5 | ✅ |
| 6.7.0.1 | ✅ |
| 6.7.1.2 | ✅ |
| 6.7.2.2 | ✅ |
| 6.7.6.2 | ✅ |
| 6.7.7.1 | ✅ |
| 6.7.10.1 | ✅ |
| 6.7.11.1 | ✅ |
| 6.7.12.1 | ✅ |
| 6.7.12.2 | ✅ |
| 6.7.13.0 | ✅ |
Legend
- ✅: Supported, tested
- ❌: Unsupported, tested
- ❓: Unknown, not tested
Supported plugins
The following plugins have been tested and are known to work with this stack:
- PayPal for Shopware 6 - 10.4.1
- Shopware Language Pack - 5.36.0
- Tools - 3.2.5
- Migration Assistant - 15.0.4
- Stripe Payments for Shopware 6 App - 1.4.4
- Shopware Store - 4.1.1
- Shopware GMV Reporting - 1.0.0
- Custom JavaScript/CSS Manager for Shopware 6 - 5.0.3
- Custom Template Manager - 4.0.0
- [[moori]] Foundation - 1.7.59
Note that this does not mean that other plugins will not work, these are just the ones that have been tested.
Before you start, you may change the default database password in the compose file. Do not attempt to create additional database users, you cannot grant permissions due to how restricted the database is. If you really want this, you'll need to at least temporarily open the MariaDB port on the container.
ℹ️ If you are running on a slow system, you can also use pre-built images from the CI. You can find the latest images here.
Simply replace the
buildsection in the compose file withimage: ghcr.io/tesyl-sro/shopware-stack:latestand rundocker compose pullto download the latest image.
-
Install Docker using these instructions.
-
Download this repo as a zip to your server.
-
Extract the archive.
-
cdinto the extracted folder.cd shopdock2 -
Edit the
Caddyfileaccording to your domain(s). Also make sure that the root folder is/app/public. -
Create a
sitedirectory:mkdir site
-
Change ownership of the
sitedirectory to thewww-datauser and group:chown -hR www-data:www-data site
-
Run the stack using Docker Compose, without
shopware_sched_task_runnerandshopware_messenger_runner.docker compose up caddy php-fpm database
You can add
-dto run it in the background.The latest Shopware installer will be automatically downloaded to
site/public/shopware-installer.phar.phpon the first run. If you want to use a specific version of Shopware, you can download the installer manually and place it in that location. -
Complete the initial Shopware setup at
http://[host]:8888/shopware-installer.phar.php. -
Edit the
Caddyfileso that the root folder is/app/public/public. -
Restart Caddy using
docker compose restart caddy. -
Complete the Shopware database configuration at
http://[host]:8888/installer. Wait until the page is no longer loading after clickingNextduring theConfigurationstep. -
Open the admin panel by going to
/admin(e.g.http://[host]:8888/admin). -
Complete the first-time setup.
-
Shut down the server according to step 11.
-
Restart the server as well as all services using
docker compose up.
Note that during the installation, you should not start shopware_sched_task_runner and shopware_messenger_runner. These services should only ever be started after Shopware is fully installed, including the OOBE setup. Running these services with an incomplete installation of Shopware may brick your installation and you have to start over.
Use http://localhost:8888 to access the Shopware store and http://localhost:8888/admin to access the admin panel.
On some systems, the www-data user and group may not exist. In this case, use the UID 33 and GID 33 in the chown commands. Additionnaly, you may need to use sudo.
⚠️ As of July 2026, we have removed automatic HTTPS configuration from this stack.The original setup forced Caddy as the main web server, making it more difficult to run other services on the same server. You'll now need to set up a reverse proxy in front of this stack to provide HTTPS.
⚠️ You will need to complete the installation of Shopware before setting up HTTPS!
This stack only provides an HTTP server. For production use, you should set up a reverse proxy in front of this stack to provide HTTPS. The simplest setup is a separate docker-compose.yml wuth a Caddy container.
Firstly, make sure that your sales channel already has the HTTPS URL set in the Shopware admin panel. If you already started messing with HTTPS configuration, and you no longer have access to the admin panel, use the command docker compose exec database mariadb -uroot -pshopware shopware -e "SELECT url FROM sales_channel_domain;" to check the current URLs.
Additionally, you can look up commands to change the sales channel URL using the CLI.
After that, shut down the stack using docker compose down and follow the steps below.
In a separate directory, create a docker-compose.yml file with the following content:
services:
caddy:
image: caddy:2.11.4-alpine
restart: unless-stopped
ports:
- 80:80
- 443:443
- 443:443/udp
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-data:/data
- ./caddy-config:/configThen create a Caddyfile in the same directory with the following content:
https://example.com {
reverse_proxy host.docker.internal:8888
}Replace example.com with your store domain.
If you are using Cloudflare, you can also use a Cloudflare Tunnel to provide HTTPS.
In a separate directory, create a docker-compose.yml file with the following content:
services:
cloudflared:
image: cloudflare/cloudflared:2026.7.2
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=__YOUR_TOKEN_HERE__
- TUNNEL_METRICS=127.0.0.1:2000
healthcheck:
test: ["CMD", "cloudflared", "tunnel", "--metrics", "127.0.0.1:2000", "ready"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
tmpfs:
- /tmp
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 64M
extra_hosts:
- "host.docker.internal:host-gateway"Continue with the setup on your Cloudflare dashboard to create a new tunnel and get the TUNNEL_TOKEN. Replace __YOUR_TOKEN_HERE__ with your actual token.
You need to make Shopware trust the reverse proxy. Do the following steps to configure this.
Next, edit the site/.env and site/.env.local files to set the APP_URL and TRUSTED_PROXIES variable to your domain, e.g.:
APP_URL=https://[domain]
TRUSTED_PROXIES="REMOTE_ADDR"Lastly, create or edit the site/config/packages/framework.yaml:
framework:
trusted_proxies: '%env(TRUSTED_PROXIES)%'
trusted_headers:
- 'x-forwarded-for'
- 'x-forwarded-host'
- 'x-forwarded-proto'
- 'x-forwarded-port'Then re-apply ownership of the site directory using chown -hR www-data:www-data site and restart the stack using docker compose up caddy php-fpm database.
Also reset all caches using the commands in the Useful commands section.
You can run multiple Shopware instances on the same server by creating a new directory for each instance.
You need to change all container_name values in the docker-compose.yml file to avoid conflicts. You also need to change the port for the Caddy container.
Before performing these steps:
- Make sure you're in the root directory of this repo.
- Shut down the stack (unless stated otherwise).
- Set up HTTPS as described above.
The following steps are not required, but may help improve security and performance.
Perform the following steps to optimize Shopware for production use:
-
Disable the admin worker using a new config file.
nano site/config/packages/shopware.yml
Add the following:
shopware: admin_worker: enable_admin_worker: false
Clear all caches AND THEN restart the stack to apply the changes!
-
Use
zstdinstead ofgzipfor cache and cart compression. (Read more)You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/shopware.yml
Add the following under
shopware:cart: compress: true compression_method: zstd cache: cache_compression: true cache_compression_method: 'zstd'
-
Disable App URL external check (Read more)
Make sure that
APP_URLis set correctly, e.g.https://mystore.comin both.envand.env.local.nano site/.env
Add the following:
APP_URL_CHECK_DISABLED=1Repeat the same for
.env.local.Clear all caches AND THEN restart the stack to apply the changes!
-
Set the log level of
monologtoerrorand limit it's buffer size:You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/monolog.yml
Add the following:
monolog: handlers: main: level: error buffer_size: 30 business_event_handler_buffer: level: error
-
Disable Symfony Secrets
You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/secrets.yml
Add the following:
framework: secrets: enabled: false
-
Prevent mail data updates
You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/shopware.yml
Add the following under
shopware:mail: update_mail_variables_on_send: false
-
Enable sending mails over queue
You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/framework.yml
Add the following:
framework: mailer: message_bus: 'messenger.default_bus'
-
Disable the Increment Storage
You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/shopware.yml
Add the following under
shopware:increment: user_activity: type: 'array' message_queue: type: 'array'
-
Disable Product Stream Indexing
You need to clear all caches and then stop the stack before doing this! Run all commands from
Reset all cachesunder theUseful commands sectionfirst.docker compose down nano site/config/packages/shopware.yml
Add the following under
shopware:product_stream: indexing: false
-
Set a fixed cache ID
nano site/.env
Add the following:
SHOPWARE_CACHE_ID=mystoreYou can replace
mystorewith any other valid name.Repeat the same for
.env.local.Clear all caches AND THEN restart the stack to apply the changes!
-
(Not recommended) Enable OPCache preloading.
This can noticably improve loading times, but it may cause stability issues for unknown reasons.
Add/Uncomment the following 2 lines in
Dockerfile-php'sOPCache tuningsection:RUN echo 'opcache.preload = /app/public/var/cache/opcache-preload.php' >> /usr/local/etc/php/conf.d/docker-php-opcache.ini; RUN echo 'opcache.preload_user = www-data' >> /usr/local/etc/php/conf.d/docker-php-opcache.ini;
Rebuild AND restart the stack after modifying these files!
Note: This may cause stability issues, however it also noticably improves (loading) performance. If this is unstable for you, undo this change. You may also sometimes see a lot of errors from
shopware_sched_task_runnerandshopware_messenger_runnerduring startup. This is normal, and it should be automatically fixed after a few seconds, and if not, undo this change. -
Update
pm.max_children,pm.max_requestsandlisten.backlogThese values allow limiting how much processing can PHP-FPM do. These values have to be adjusted according to your server's hardware.
Our default values provide a good base for most small instances. For larger stores with more traffic, they may not be adequate.
Improper configuration of these values can trigger warnings in Shopware (Tools), specifically:
PHP FPM max listen queue: This indicates how many times has PHP-FPM reachedpm.max_childrensince it's been started. Ideally, this value should never be reached, therefore the "recommended" value is0.PHP FPM max children reached: This simply indicates if PHP-FPM has ever reachedpm.max_childrensince it's been started. Ideally, this value should never betrue.
Note: Do not increase these values too much, or it will overload your server. If you can't find values that don't trigger any warnings, then your hardware may not be performant enough.
-
Enable Redis message queue.
You need to shut down the stack before doing this!
nano site/.env.local
At the end of the file, add the following:
MESSENGER_TRANSPORT_DSN=redis://redis:6379/messages?auto_setup=falseNext, inside the
php-fpmcontainer, install thesymfony/redis-messengerpackage:docker compose exec php-fpm bash cd /app/public ./composer require "symfony/redis-messenger:^7.4" -W
Next, still inside the
php-fpmcontainer, run the following command to clear caches and create the necessary Redis tables:./bin/console cache:clear:all ./bin/console messenger:setup-transports
Finally, restart the stack.
-
Optimize service limits to your hardware
Change
pids_limit,mem_limitandcpusaccording to your preference and hardware configuration. The defaults are optimized for a 2 vCore + 4GB RAM server.
Updating Shopware should be done using the Shopware admin panel. Updating PHP can be done by cleaning up the old image and rebuilding it.
Clean up unused Docker containers
docker container prune -fView containers and their statuses
docker container ls -aRun a shell inside the PHP-FPM container
docker compose exec php-fpm bashRun a shell inside the database container
docker compose exec database bashUse PHP CLI
docker compose exec php-fpm php [COMMAND]Example:
docker compose exec php-fpm php -vUse MariaDB CLI
docker compose exec database mariadb -u root --password=shopware -D shopwareNote: If you changed the database name and/or password, you need to adjust the -D and --password arguments.
Dump the database
docker compose exec database mariadb-dump -u root --password=shopware --skip-set-charset --default-character-set=utf8mb4 shopware > database_dump.sqlNote 1: If you changed the database name and/or password, you need to adjust the --password argument and/or replace the database name shopware.
Import an SQL file
docker compose exec database mariadb -u root --password=shopware -D shopware < [SOURCE]Example:
docker compose exec database mariadb -u root --password=shopware -D shopware < my_backup_file.sqlNote: If you changed the database name and/or password, you need to adjust the -D and --password arguments.
Use Shopware CLI
docker compose exec php-fpm /app/public/bin/console [COMMAND]Example:
docker compose exec php-fpm /app/public/bin/console aboutRun messenger tasks
docker compose exec php-fpm /app/public/bin/console messenger:consume async low_priority --time-limit=60 --memory-limit=512M --no-interaction --no-ansi --quietCheck scheduled tasks
docker compose exec php-fpm /app/public/bin/console scheduled-task:listRun scheduled tasks
docker compose exec php-fpm /app/public/bin/console scheduled-task:run --time-limit=60 --memory-limit=512M --no-interaction --no-ansiReset all caches
docker compose exec php-fpm /app/public/bin/console cache:clear:all
docker compose exec php-fpm /app/public/bin/console cache:clear
docker compose exec php-fpm /app/public/bin/console cache:warmup
docker compose exec php-fpm /app/public/bin/console theme:compile
chown -hR www-data:www-data siteNote that if your system does not have the www-data user and group created, you can use chown -hR 33:33 site instead.
Some of these commands may require root/sudo.
Clean up Docker
⚠️ WARNING⚠️ This will irrecoverably delete ALL VOLUMES AND IMAGES.
This will NOT detele your database, shopware data, Caddy configuration from this stack.
You can use this to clean up old image layers that are no longer used and free up disk space.
Make sure to shut down the stack before running these commands.
docker builder prune -a -f
docker buildx prune -a -f
docker image prune -a -f
docker container prune -fYou will need to re-pull and rebuild the images after this.
To create a backup of your Shopware stack (inc. Shopware data, database and Caddy configuration), simply shut down the stack and archive the data directories mentioned in the compose file.
The commands listed below assume that you are inside the root of this repository on your system:
# Shut down all containers
docker compose down
# Create a tar archive in the parent directory
tar cvzf ../my-shopware-backup.tar.gz .
# Check the contents (remove the pipe to head to see all files)
tar tvf my-shopware-backup.tar.gz | headAlternatively, if you want to create the smallest possible archive, you can use LZMA2 with maximum compression using the following command. Note that while LZMA2 decompression is fast, compression can be very slow and may require a lot of RAM.
XZ_OPT="-9e -T0" tar cvJf ../my-shopware-backup.tar.xz .You could also use zip or 7-Zip to create a backup archive.
It is recommended that you use tar, as it keeps track of permissions and ownerships.
If you just want to import a database from a SQL dump file, check the
Useful commandssection above.
To restore your Shopware stack from a backup, run the following steps:
-
Extract the backup archive.
tar xvzf my-shopware-backup.tar.gz
-
cdinto the new directory.cd my-shopware-backup -
Ensure that the
sitedirectory is owned bywww-data:ls -lh site
If not, perform step 8 from the
Getting startedsection. -
Start the stack.
docker compose up -d
This section is dedicated to issues we encountered over time, with potential fixes.
Shopware tools displays Open Queues warning, but message processing works.
Firstly, check if messages and tasks are actually being executed. If containers shopware_sched_task_runner and shopware_messenger_runner are running, then go to the admin panel, Settings, Caches & indexes and click Update indexes.
Now go back to Shopware Tools, open Queue tab and check if the size of the async and default queues is decreasing as you keep refreshing. If the numbers drop to 0, it means that message processing works.
If the Open Queues warning is still displayed, click Reset Queue and confirm. This should clear the warning.
Unknown, but it could be that if the messenger does not consume a message fast enough, and the message gets somehow dropped or lost from Redis/Doctrine queue, and the database still has that message marked as queued, then Shopware Tools will count that as an unprocessed message. This is likely to happen after an update, not sure why.
Redis configuration is lost after an update
Make sure you configured the Redis queue in the .env.local file, and not .env.