Step 1: Download Docker Desktop
DOWNLOAD
Confirm installation in terminal: docker --version
Step 1.1: Create your username
Step 1.2 : Login to docker from terminal
Login with username: docker login -u [USERNAME]
Step 1.3: Run these commands
docker pull mariadb docker-compose -f docker-compose.dev.yml up -d
Step 2 : Identify the .docker folder and edit the following files: Dockerfile and init.sql
Dockerfile
FROM bitnami/minideb:bullseye
# ————————————————————————————————
# 1) Copy in config & init script
# ————————————————————————————————
COPY .docker/php.ini /tmp/php.ini
COPY .docker/jasperstarter.zip /tmp/jasperstarter.zip
COPY init-symfony.sh /usr/local/bin/init-symfony.sh
# ————————————————————————————————
# 2) Install base tools + JasperStarter
# ————————————————————————————————
RUN apt-get update && \
apt-get install -y git wget curl unzip htmldoc default-jre && \
cd /tmp && unzip jasperstarter.zip && \
mv jasperstarter /opt/jasperstarter && \
chmod -R 755 /opt/jasperstarter
# ————————————————————————————————
# 3) Add Sury PHP repo, install PHP 7.4+ + deps + Composer + Symfony CLI
# ————————————————————————————————
RUN apt-get update && \
apt-get install -y apt-transport-https lsb-release ca-certificates && \
wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" \
> /etc/apt/sources.list.d/php.list && \
apt-get update && \
apt-get install -y \
php7.4-cli php7.4-zip php7.4-gd php7.4-xml php7.4-ldap \
php7.4-mysql php7.4-mbstring mariadb-client fonts-liberation && \
cat /tmp/php.ini >> /etc/php/7.4/cli/php.ini && \
curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/local/bin --filename=composer && \
wget -qO - https://get.symfony.com/cli/installer | bash && \
mv /root/.symfony*/bin/symfony /usr/local/bin/symfony && \
rm -rf /var/lib/apt/lists/*
# ————————————————————————————————
# 4) JDBC driver for Jasper
# ————————————————————————————————
RUN wget -qO /usr/share/java/mariadb-java-client.jar \
https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.7.3/mariadb-java-client-2.7.3.jar && \
mkdir -p /opt/jasperstarter/jdbc && \
ln -s /usr/share/java/mariadb-java-client.jar /opt/jasperstarter/jdbc/mysql.jar
# ————————————————————————————————
# 5) Workdir + Entrypoint
# ————————————————————————————————
WORKDIR /home/project
# Make our init script executable
RUN chmod +x /usr/local/bin/init-symfony.sh
# On container startup, run the init script (which will bootstrap Symfony
# and then exec php -S 0.0.0.0:8000 -t public)
# important file to be added in root level
ENTRYPOINT ["sh", "/usr/local/bin/init-symfony.sh"] Refer to Step 2.2 to add init-symfony.sh
init.sql
-- Development database initialization -- Create and use development database CREATE DATABASE IF NOT EXISTS ind_test_dev; USE ind_test_dev; -- Grant privileges to the development user GRANT ALL PRIVILEGES ON *.* TO 'dev_user'@'%'; FLUSH PRIVILEGES; -- Run your existing build.sql USE ind_test_dev; source /docker-entrypoint-initdb.d/database/build.sql; source /docker-entrypoint-initdb.d/database/update.sql;
Step 2.2: Create init-symfony.sh:
#!/usr/bin/env sh
set -e
cd /home/project
# 1) Bootstrap Symfony if needed
if [ ! -f composer.json ]; then
echo "⏳ Initializing Symfony project..."
composer create-project symfony/website-skeleton . "6.3.*"
fi
# 2) Ensure public directory and minimal front controller
mkdir -p public
if [ ! -f public/index.php ]; then
cat > public/index.php << 'EOL'
<?php
use Symfony\Component\HttpFoundation\Request;
require __DIR__ . '/../vendor/autoload_runtime.php';
return function (Request $request) {
echo "Symfony project initialized!";
};
EOL
fi
# 3) Install/update dependencies
composer install --prefer-dist --no-interaction
# 4) Finally, hand over to PHP’s built-in server
echo "✅ Starting PHP dev server on 0.0.0.0:8000"
exec php -S 0.0.0.0:8000 -t public
Step 3: Change the file name from docker-compose.yml to docker-compose.dev.yml
Add .env.local but do not remove the .env file

Env.local
APP_ENV=dev APP_DEBUG=1 DATABASE_URL=mysql://dev_user:dev_password@sqldb_dev:3306/ind_test_dev # Change the email addresses to prevent accidental sending to real addresses CADORATH_EMAIL_NOTIFY_CONSIGNMENT_UPDATE=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_INVENTORY_UPDATE=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_ERP_DAYEND=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_WORKORDER_NEWPART=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_WORKORDER_QUOTE_CHANGED=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_WORKORDER_MOVED_ENGINEERING=dev-CADORATHing@example.com CADORATH_EMAIL_NOTIFY_WARRANTY_APPROVAL=dev-CADORATHing@example.com CADORATH_EMAIL_RPI_CONTRACT_REVIEW=dev-CADORATHing@example.com CADORATH_EMAIL_RPI_PROCEDURE_APPROVAL=dev-CADORATHing@example.com LDAP_ENABLED=false
Step 4: Create docker-compose.dev.yml and paste the below config.
Change the SQL DATABASE_URL to your local dev URL and SQL credentials in env.local
version: '3.8'
services:
app:
container_name: weberty_dev
build:
context: .
dockerfile: .docker/Dockerfile
ports:
- "127.0.0.1:8088:8000"
working_dir: /home/project # ensure entrypoint starts here
volumes:
- ./project:/home/project:delegated
depends_on:
- sql
environment:
APP_ENV: dev
APP_DEBUG: '1'
DATABASE_URL: mysql://dev_user:dev_password@sqldb_dev:3306/ind_test_dev
LDAP_ENABLED: 'false'SQL:
container_name: sqldb_dev image: mariadb:11 # keep 11 if you want that version ports: - "127.0.0.1:3307:3306" volumes: - ./.docker/init.dev.sql:/docker-entrypoint-initdb.d/init.sql:ro - ./database_local:/var/lib/mysql # ? use a *fresh* folder or a named volume restart: always command: --event-scheduler=ON environment: MYSQL_ROOT_PASSWORD: devrootpass MYSQL_DATABASE: ind_test_dev MYSQL_USER: dev_user MYSQL_PASSWORD: dev_password
Step 5: Edit the following config files:
project/config/cadorath.yaml: change all %env to %env.local
From
# Cadorath Aerospace specific configuration settings parameters: cadorath.id: "%env(CADORATH_ID)%" # used by legacy code cadorath.db: "%env(DATABASE_URL)%" cadorath.fqdn: "%env(CADORATH_FQDN)%" cadorath.serial: "%env(CADORATH_SERIAL)%" cadorath.locale: "%env(CADORATH_LOCALE)%" cadorath.date.format: "Y/m/d" cadorath.path.dayend: "%env(CADORATH_PATH_DAYEND)%" cadorath.path.status: "%env(CADORATH_PATH_STATUS)%" cadorath.path.document.rpi: "%env(CADORATH_PATH_DOCUMENT_RPI)%" cadorath.path.document.erp: "%env(CADORATH_PATH_DOCUMENT_ERP)%" cadorath.path.jasper.target: "%env(CADORATH_PATH_JASPER_TARGET)%" cadorath.path.jasper.source: "%env(CADORATH_PATH_JASPER_SOURCE)%" cadorath.path.report.legacy.source: "%env(CADORATH_PATH_LEGACY_REPORT_SOURCE)%" cadorath.app.smtp.host: "cadorath-com.mail.protection.outlook.com" cadorath.email.notify.consignment.update: "%env(CADORATH_EMAIL_NOTIFY_CONSIGNMENT_UPDATE)%" cadorath.email.notify.inventory.update: "%env(CADORATH_EMAIL_NOTIFY_INVENTORY_UPDATE)%" cadorath.email.notify.erp.dayend: "%env(CADORATH_EMAIL_NOTIFY_ERP_DAYEND)%" cadorath.email.notify.workorder.newpart: "%env(CADORATH_EMAIL_NOTIFY_WORKORDER_NEWPART)%" cadorath.email.notify.workorder.quote.changed: "%env(CADORATH_EMAIL_NOTIFY_WORKORDER_QUOTE_CHANGED)%" cadorath.email.notify.workorder.moved.engineering: "%env(CADORATH_EMAIL_NOTIFY_WORKORDER_MOVED_ENGINEERING)%" cadorath.email.notify.warranty.approval: "%env(CADORATH_EMAIL_NOTIFY_WARRANTY_APPROVAL)%" cadorath.email.rpi.contract.review: "%env(CADORATH_EMAIL_RPI_CONTRACT_REVIEW)%" cadorath.email.rpi.procedure.approval: "%env(CADORATH_EMAIL_RPI_PROCEDURE_APPROVAL)%"
To
# Cadorath Aerospace specific configuration settings parameters: cadorath.id: "%env.local(CADORATH_ID)%" # used by legacy code cadorath.db: "%env.local(DATABASE_URL)%" cadorath.fqdn: "%env.local(CADORATH_FQDN)%" cadorath.serial: "%env.local(CADORATH_SERIAL)%" cadorath.locale: "%env.local(CADORATH_LOCALE)%" cadorath.date.format: "Y/m/d" cadorath.path.dayend: "%env.local(CADORATH_PATH_DAYEND)%" cadorath.path.status: "%env.local(CADORATH_PATH_STATUS)%" cadorath.path.document.rpi: "%env.local(CADORATH_PATH_DOCUMENT_RPI)%" cadorath.path.document.erp: "%env.local(CADORATH_PATH_DOCUMENT_ERP)%" cadorath.path.jasper.target: "%env.local(CADORATH_PATH_JASPER_TARGET)%" cadorath.path.jasper.source: "%env.local(CADORATH_PATH_JASPER_SOURCE)%" cadorath.path.report.legacy.source: "%env.local(CADORATH_PATH_LEGACY_REPORT_SOURCE)%" cadorath.app.smtp.host: "cadorath-com.mail.protection.outlook.com" cadorath.email.notify.consignment.update: "%env.local(CADORATH_EMAIL_NOTIFY_CONSIGNMENT_UPDATE)%" cadorath.email.notify.inventory.update: "%env.local(CADORATH_EMAIL_NOTIFY_INVENTORY_UPDATE)%" cadorath.email.notify.erp.dayend: "%env.local(CADORATH_EMAIL_NOTIFY_ERP_DAYEND)%" cadorath.email.notify.workorder.newpart: "%env.local(CADORATH_EMAIL_NOTIFY_WORKORDER_NEWPART)%" cadorath.email.notify.workorder.quote.changed: "%env.local(CADORATH_EMAIL_NOTIFY_WORKORDER_QUOTE_CHANGED)%" cadorath.email.notify.workorder.moved.engineering: "%env.local(CADORATH_EMAIL_NOTIFY_WORKORDER_MOVED_ENGINEERING)%" cadorath.email.notify.warranty.approval: "%env.local(CADORATH_EMAIL_NOTIFY_WARRANTY_APPROVAL)%" cadorath.email.rpi.contract.review: "%env.local(CADORATH_EMAIL_RPI_CONTRACT_REVIEW)%" cadorath.email.rpi.procedure.approval: "%env.local(CADORATH_EMAIL_RPI_PROCEDURE_APPROVAL)%"
project/config/services.yaml
From
Symfony\Component\Ldap\Ldap:
arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
arguments:
- host: 192.168.1.27
port: 389
#encryption: tls
options:
protocol_version: 3
referrals: falseTo
Symfony\Component\Ldap\Ldap:
arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
arguments:
- host: 127.0.0.1
port: 389
#encryption: tls
options:
protocol_version: 3
referrals: false
Step 6: Setup Docker Build
docker-compose -f docker-compose.dev.yml up -d sql
Step 6.1: Verify database container
docker-compose -f docker-compose.dev.yml ps
Step 7: Test Database Connection
Host: 127.0.0.1
Port: 3307
User: dev_user
Password: dev_password
Database: ind_test_dev
Step 8: Build and Start App Container
Step 8.1: Build app container
docker-compose -f docker-compose.dev.yml build app
Step 8.2: Start app container
docker-compose -f docker-compose.dev.yml up -d app
Step 8.3: Verify both containers running
docker-compose -f docker-compose.dev.yml ps
Stop app container (optional -testing only)
docker compose -f docker-compose.dev.yml down


App is successful output in terminal:
weberty_dev | 88 packages you are using are looking for funding. weberty_dev | Use the `composer fund` command to find out more! weberty_dev | weberty_dev | Run composer recipes at any time to see the status of your Symfony recipes. weberty_dev | weberty_dev | ✅ Starting PHP dev server on 0.0.0.0:8000 weberty_dev | [Thu May 1 19:48:54 2025] PHP 7.4.33 Development Server (http://0.0.0.0:8000) startedSQL is running successfully:
sqldb_dev | 2025-05-01 19:48:56 0 [Note] Server socket created on IP: '0.0.0.0'. sqldb_dev | 2025-05-01 19:48:56 0 [Note] Server socket created on IP: '::'. sqldb_dev | 2025-05-01 19:48:56 0 [Note] mariadbd: Event Scheduler: Loaded 0 events sqldb_dev | 2025-05-01 19:48:56 1 [Note] Event Scheduler: scheduler thread started with id 1 sqldb_dev | 2025-05-01 19:48:56 0 [Note] mariadbd: ready for connections. sqldb_dev | Version: '11.7.2-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
Troubleshooting:
Check container logs: docker-compose -f docker-compose.dev.yml logs app
Reset the database if needed:
docker-compose -f docker-compose.dev.yml down
rm -rf ./database_dev
mkdir -p ./database_dev
docker-compose -f docker-compose.dev.yml up -d