This document provides technical guidance for developers working with the Inception project. It covers environment setup, Docker/Makefile usage, container management, and data persistence architecture.
Before you begin, ensure you have installed:
# Check Docker
docker --version # v24.0+
# Check Docker Compose
docker-compose --version # v2.20+
# Check Make
make --version # v4.0+
# Check git
git --version # v2.30+System Requirements:
- Linux (tested on Debian 13, Ubuntu 20.04+)
- 4GB RAM minimum (8GB recommended)
- 20GB free disk space
- Internet connection (for downloading images)
git clone https://github.com/mkhavari/inception.git
cd inceptionCopy and configure .env:
cp srcs/.env.example srcs/.envEdit srcs/.env with your settings:
# Domain configuration
DOMAIN_NAME=https://mkhavari.42.fr
# WordPress admin
WP_ADMIN_USER=mkhavari
WP_ADMIN_EMAIL=your-email@example.com
# WordPress author user
WP_USER=javad
WP_USER_EMAIL=second-user@example.com
# Database configuration
WORDPRESS_DB_NAME=wordpress
WORDPRESS_DB_USER=wp_user
WORDPRESS_DB_HOST=mariadb
# FTP configuration
FTP_USER=ftpuser
# Data storage paths (adjust as needed)
WORDPRESS_DATA=/home/mkhavari/data/wordpress
MARIADB_DATA=/home/mkhavari/data/mariadbAdd your domain to the hosts file:
sudo nano /etc/hosts
# Add this line:
# 127.0.0.1 mkhavari.42.frOr use the Makefile:
make hostsCreate random passwords for all services:
make secretsThis generates:
secrets/db_root_password.txt— MariaDB root passwordsecrets/db_password.txt— WordPress database user passwordsecrets/wp_admin_password.txt— WordPress admin passwordsecrets/wp_user_password.txt— WordPress author passwordsecrets/ftp_password.txt— FTP user passwordsecrets/portainer_pass.txt— Portainer admin password
Files are created with mode 600 (readable only by owner).
make dataThis creates:
/home/mkhavari/data/wordpress/— WordPress files/home/mkhavari/data/mariadb/— Database files
make buildThis:
- Reads all Dockerfiles in
srcs/requirements/ - Downloads base images (Debian, Node.js, etc.)
- Installs packages and dependencies
- Creates custom Docker images
- Takes 5-10 minutes on first run
View build progress:
docker images | grep "inception\|mariadb\|nginx"make allThis executes in order:
make hosts— Configure /etc/hostsmake data— Create data directoriesmake secrets— Generate credentialsmake build— Build Docker imagesdocker-compose up -d— Start containers
Check status:
make psUse --no-cache to force rebuild dependencies:
docker compose -f srcs/docker-compose.yml build --no-cacheOr for a specific service:
docker compose -f srcs/docker-compose.yml build --no-cache wordpressdocker-compose -f srcs/docker-compose.yml up -ddocker-compose -f srcs/docker-compose.yml stopdocker-compose -f srcs/docker-compose.yml startdocker-compose -f srcs/docker-compose.yml restartdocker-compose -f srcs/docker-compose.yml downdocker-compose -f srcs/docker-compose.yml down --rmi all --volumesdocker ps -a# Latest logs
docker logs nginx
# Follow logs in real-time
docker logs -f wordpress
# Last 50 lines
docker logs --tail 50 mariadb
# With timestamps
docker logs -t redis# Interactive bash shell
docker exec -it wordpress bash
# Run single command
docker exec wordpress wp core version --allow-root
# Run with environment variables
docker exec -e VAR=value wordpress command# Full container info
docker inspect wordpress
# Just IP address
docker inspect -f '{{.NetworkSettings.IPAddress}}' wordpress
# Resource usage
docker stats wordpressdocker restart wordpress
docker restart mariadb
docker restart nginxdocker exec wordpress ps aux
docker exec mariadb ps auxDocker-managed volumes (for production data):
volumes:
wordpress:
driver: local
driver_opts:
type: none
o: bind
device: ${WORDPRESS_DATA}
mariadb:
driver: localBind mounts (for development):
volumes:
- ./requirements/bonus/static/portfolio:/app # React source codedocker volume lsdocker volume inspect inception_wordpress
docker volume inspect inception_mariadb# WordPress files
ls -la /home/mkhavari/data/wordpress/
# Database files
ls -la /home/mkhavari/data/mariadb/# Backup WordPress volume
docker run --rm -v inception_wordpress:/data \
-v $(pwd):/backup alpine \
tar -czf /backup/wordpress_backup.tar.gz -C /data .
# Backup Database volume
docker run --rm -v inception_mariadb:/data \
-v $(pwd):/backup alpine \
tar -czf /backup/mariadb_backup.tar.gz -C /data .# Create a temporary container and restore
docker run --rm -v inception_wordpress:/data \
-v $(pwd):/backup alpine \
tar -xzf /backup/wordpress_backup.tar.gz -C /datadocker volume rm inception_wordpressHost Machine
├── /home/mkhavari/data/
│ ├── wordpress/ # WordPress files, uploads, plugins
│ │ ├── wp-config.php
│ │ ├── wp-content/
│ │ ├── wp-admin/
│ │ └── index.php
│ └── mariadb/ # Database files (InnoDB tables)
│ ├── mysql/
│ ├── wordpress/
│ └── ibdata1
└── Docker-managed
└── portainer_data/ # Portainer configuration
Bind Mounts (WordPress & MariaDB):
${WORDPRESS_DATA}:/var/www/html— WordPress directory${MARIADB_DATA}:/var/lib/mysql— Database directory- Changes on host immediately visible in container
- Survives container deletion
Docker Volumes (Portainer):
- Managed by Docker daemon
- Stored in
/var/lib/docker/volumes/ - Requires
docker volumecommands to access
- Container Creation: Docker mounts existing volumes
- Container Running: All changes written to volumes
- Container Stopped: Data persists in volumes
- Container Deleted: Volumes persist (unless explicitly removed)
- Clean:
make fcleanremoves everything including data
Daily backup script:
#!/bin/bash
DATE=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_DIR="/backups"
# Backup WordPress
tar -czf $BACKUP_DIR/wordpress_$DATE.tar.gz /home/mkhavari/data/wordpress/
# Backup Database
docker exec inception_mariadb mysqldump -u root \
-p$(cat secrets/db_root_password.txt) wordpress \
> $BACKUP_DIR/wordpress_db_$DATE.sql| Target | Purpose |
|---|---|
make all |
Full setup and start (recommended for first run) |
make hosts |
Add domain to /etc/hosts |
make data |
Create data directories |
make secrets |
Generate random passwords |
make build |
Build Docker images |
make up |
Start containers (detached) |
make down |
Stop and remove containers |
make stop |
Stop containers (keep them) |
make start |
Start stopped containers |
make ps |
List containers and status |
make restart |
Restart all containers |
make clean |
Remove containers, images, volumes |
make fclean |
Remove everything including host data |
make re |
Full rebuild from scratch |
All containers communicate on custom bridge network inception:
┌─────────────────────────────────────────┐
│ Docker Network: inception │
├──────────┬──────────┬───────────────────┤
│ Nginx │WordPress │ MariaDB │
│ :443 │ :9000 │ :3306 │
│ port 443 │(internal)│ (internal) │
└──────────┴──────────┴───────────────────┘
Containers resolve service names automatically:
wordpress:9000— PHP-FPM from nginxmariadb:3306— Database from WordPressredis:6379— Cache from WordPress
Only exposed ports reach the host:
ports:
- "443:443" # Nginx HTTPS (public)
- "5173:5173" # React portfolio (dev)
- "8080:8080" # Adminer (admin)
- "9443:9443" # Portainer (admin)
- "21:21" # FTP (public)
- "21100-21110:21100-21110" # FTP passive portsInternal services (MariaDB, PHP-FPM, Redis) are not exposed.
# Is container running?
docker ps | grep wordpress
# What's the exit code?
docker inspect -f '{{.State.ExitCode}}' wordpress
# View startup logs
docker logs wordpress | head -50# Test connection from WordPress container
docker exec -it wordpress bash -c \
'mysql -hmariadb -u wp_user -p"$(cat /run/secrets/db_password)" -e "SELECT 1;"'
# Check MariaDB logs
docker logs mariadb | grep -i "error\|ready"# Test DNS resolution
docker exec wordpress nslookup mariadb
# Test port connectivity
docker exec wordpress nc -zv mariadb 3306
# View network details
docker network inspect inception# Check ownership in WordPress container
docker exec wordpress ls -la /var/www/html/
# Fix ownership
docker exec wordpress chown -R www-data:www-data /var/www/html/# Real-time stats
docker stats
# Limit container memory (after creation)
docker update --memory 512m wordpressReact Portfolio:
# Changes in ./srcs/requirements/bonus/static/portfolio/
# Automatically reload at http://localhost:5173 (HMR)WordPress Code:
# Changes in /home/mkhavari/data/wordpress/
# Immediately visible at https://mkhavari.42.frPHP/Config:
# Edit php-fpm config in ./srcs/requirements/wordpress/conf/www.conf
# Rebuild: docker compose build --no-cache wordpress
# Restart: docker restart wordpress# Rebuild specific service
make build
# Rebuild without cache (slower, cleaner)
docker compose -f srcs/docker-compose.yml build --no-cache wordpress
# Restart after rebuild
docker restart wordpress# Follow WordPress errors as they happen
docker logs -f wordpress
# All container logs simultaneously
docker compose -f srcs/docker-compose.yml logs -f# Verify WordPress is accessible
curl -k https://mkhavari.42.fr/
# Verify database
docker exec wordpress wp core is-installed --allow-root
# Verify Redis
docker exec redis redis-cli pingAdd to services for automated restarts:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3- Never commit
secrets/*.txtto git - Regenerate secrets for production
- Use strong passwords (generated with
openssl rand)
- No
network_mode: host✅ (isolated) - No
links:deprecated feature ✅ - Custom bridge network ✅
- Database files owned by
mysql:mysql - WordPress files owned by
www-data:www-data - Secrets readable only by root (600 permissions)
For technical questions, refer to:
- Project README.md
- Individual Dockerfile comments
- entrypoint.sh scripts for initialization logic
- USER_DOC.md for end-user features