This project has been created as part of the 42 curriculum by amacarul.
- Docker technology
- Containers
- Service orchestration
- Networking
- Persistent storage
- Secure environment configuration
- Description
- Instructions
- Project description
- Resources
Inception is a Docker-based infrastructure project focused on building and orchestrating a complete web service stack using containerization.
The project consists of designing a modular and reproducible environment where each service runs inside its own container, built from scratch using Dockerfiles and managed with Docker Compose.
The deployed stack includes:
- NGINX as the secure HTTPS entry point
- WordPress + PHP-FPM as the application layer
- MariaDB as the database service
All services communicate through an internal Docker network, while persistent data is stored on the host system.
The goal of the project is to demonstrate fundamental DevOps concepts such as container isolation, service orchestration, networking, and data persistence in a controlled environment.
This section explains how to set up, build, and run the Inception project from scratch.
For more detailed explanations about development environment configuration, refer to the DEV_DOC.
- Access to a Linux machine / VM (see DEV_DOC)
- Docker and Docker Compose installed (see DEV_DOC)
-
Clone the repository:
git clone git@github.com:AnaMac3/42-Inception.gitOptions:
- Clone on your local machine and share the folder with the VM via VirtualBox Shared Folders (see DEV_DOC)
- Clone directly inside the VM (requires installing
gitin the VM)
-
Create the
.envfile insrcs/(see DEV_DOC) -
Create
secretsdirectory and files (see DEV_DOC)
-
Start all services:
make
Note:
makeprepares the host environment by creating the required persistent storage directories and setting proper permissions for Docker volume binding. It then builds the Docker images, creates the container stack, and starts all services defined in docker-compose.
-
Networking / SHH tunneling:
- As services run inside the VM, HTTPS traffic must be forwarded to your host to access the site from the browser.
- Domain configuration and SSH tunneling: see DEV_DOC.
-
Access to the website
-
Open in your browser:
https://<login>.42.fr
-
| Makefile command | Description |
|---|---|
make stop |
Stops all running containers without removing them. Containers, networks, images, and volumes remain intact. |
make down |
Stops and removes containers and Docker Compose networks. Persistent data stored in bind-backed host directories is preserved. Docker volumes are not removed. Images are not deleted. |
make clean |
Stops and removes containers, networks, and project images.Persistent data stored in bind-backed host directories is preserved. |
make fclean |
Performs clean, then deletes all persistent host data directories, removes all Docker volumes, and runs docker system prune -a --force. This fully resets the project to a fresh state. |
Important: Persistent data,
.envfiles andsecretswith sensitive credentials should never be pushed to Github. Only Makefile, Dockerfiles, docker-compose.yml, scripts, and configuration files are versioned.
Inception is a containerized web infrastructure built with Docker and Docker Compose.
The project deploys a complete WordPress stack composed of independent services that cooperate through an isolated network while keeping persistent application data outside contianers.
This section provides a high-level overview of the technologies used, the system architecture, how services communicate, and how data persistence is achieved.
For detailed theoretical explanations and implementation details, see the DEV_DOC.
Docker is a platform to run applications inside containers - isolated, lightweight, and reproducible environments that include only the necessary dependencies.
A container is an isolated, self-contained runtime instance of a Docker image. Each container includes:
- The application (e.g., WordPress, NGINX, MariaDB)
- Dependencies and libraries
- Configuration files
- Minimal runtime environment
Containers are isolated processes for each component of your app. Containers provide process, filesystem, and network isolation.
- Avoids dependency conflicts between projects
- Ensures reproducible environments
- Isolates services (web server, database, PHP) from the host system
- Fast startup and low resource usage compared to full VMs
| Virtual Machine | Contenedor Docker |
|---|---|
| Complete OS with kernel | Shares host kernel |
| Heavy and slow to start | Lightweight, starts in milliseconds |
| High RAM/CPU usage | Minimal resource usage |
| Full isolation | Process & network isolation, but shared kernel |
In Inception, Docker containers run inside a Debian VM. The VM provides an isolated host environment, while containers manage the application runtime. This combination allows efficient resource use while maintaining isolation and reproducibility.
A Docker image is an inmutable blueprint used to create containers. It contains:
- Application files
- System dependencies
- Configuration files
- Startup instructions.
Images are built once and reused to create one or multiple containers.
A container is a running instance of an image. Containers are ephemeral by default: removing a container deletes all runtime data unless persisted externally.
A Dockerfile is a text file that defines how a Docker image is built, specifying:
- Base Operating System (OS)
- Packages to install
- Configuration files to copy
- Commands to run at container start (
ENTRYPOINT,CMD)
A core Docker best practice is:
One container = one main service
In Inception, each service (mariadb,wordpress,nginx) runs in its own container, each with a dedicated Dockerfile.
The project follows a layered multi-container architecture, where each service has a single responsibility and runs in its own Docker container.
| Service | Role |
|---|---|
| NGINX | HTTPS reverse proxy and public entry point |
| WordPress (PHP-FPM) | Application logic and PHP execution |
| MariaDB | Persistent database storage |
Services communicate through a private Docker network, while only one service is exposed to the outside world.
- NGINX
- Terminates HTTPS connections
- Serves static files
- Forwards PHP requests to WordPress via FastCGI
- WordPress / PHP-FPM
- Executes PHP scripts
- Generates dynamic content
- Queries the database
- MariaDB
- Stores users, posts, configuration, and metadata
- Provides persistent storage for the application
Browser
↓ HTTPS (443)
NGINX
↓ FastCGI (9000)
WordPress (PHP-FPM)
↓ SQL (3306)
MariaDB
- The browser connect to NGINX via HTTPS
- NGINX serves static files or forwards PHP request
- PHP-FPM executes WordPress code
- WordPress (PHP-FPM) queries MariaDB via SQL using credentials defined in
wp-config.php - The generated HTML response is returned to the browser
Containers communicate over networks. There are two main types:
- Bridge network (default): private network for containers, allows secure communication using service names. Internal ports are not exposed to the host unless explicitly mapped, they are only accessible inside the Docker network.
- Host network: container shares the host's network stack; ports are exposed directly.
In Inception, all services uses a bridge network for security and isolation. This network is defined in the
docker-compose.ymlfile.
Thanks to the internal bridge network:
- WordPress connects to MariaDB using the service name
mariadb(setup.sh) - NGINX forwards PHP requests to WordPress using
fastcgi_pass wordpress:9000(defined innginx.conf) This ensures internal traffic is isolated, secure, and predictable.
Containers are ephemeral: deleting a container removes its filesystem. To persist data, Docker provides different storage mechanisms.
In this project, we use a hybrid approach based on Docker volumes configured with bind-backed storage.
There are two main concepts:
- Docker volumes: storage objects fully managed by Docker. The physical location on host filesystem location is abstracted internally by Docker, unless configured otherwise.
- Bind mounts: direct mapping between a specific directory on the host and a path inside the container. Host-controlled path, easy to inspect.
| Feature | Docker Volume | Bind Mount |
|---|---|---|
| Advantages | - Managed by Docker - Safer abstraction layer - Portable configuration - Standard in containerized apps - Recommended for production |
- Full control over host path - Easy direct inspection - Immediate visibility of files |
| Disadvantages | - Location on host is not directly visible, host path is abstracted - Requires Docker tooling to inspect |
- More prone to permission issues - Less portable - Strong dependency on host structure |
In this project, we do not use raw bind mounts in service definition. Instead, we define Docker volumes with bind-backend configuration (driver_opts). This means Docker volumes are defined and managed by Docker, but physically stored in specific host directories.
This project separates configuration data from sensitive credentials following Docker best practices.
Non-sensitive configuration (DB name, users, site title) is stored in the .env file.
Examples include:
- domain name
- database name
- database username
- WordPress site configuration
- email addresses
The.envfile: - contains configuration only
- allows dynamic container configuration without modifying source code
- must NOT be commited to versiol control
Environment variables are not considered secure because they are visible through container inspection.
For details about how environment variables are configured in this project, see:.envconfiguration
Sensitive data such as passwords are managed using Docker secrets.
A Docker secret is a file securely mounted inside a container at runtime only, specially designed to store confidential information.
Secrets protect credentials during container startup.
In this project, secrets are used for:
- MariaDB root and user passwords
- WordPress admin and user passwords
Unlike enviroment variables:
| Environment variables | Secrets |
|---|---|
| Stored as container variables | Mounted as protected files |
Visible via container inspection (docker inspect) |
Not exposed in container metadata |
| Suitable for configuration | Suitable for credentials |
| May appear in logs or environment dumps | Limited runtime exposure |
For implementation details, see: secrets configuration.
dockerdocs
dockerdocs - Overview
dockerdocs - Building best practices
Docker compose commands
Docker commands
Dockerfile keywords
SQL keywords
WordPress documentation
Grademe tutorial
Forstman1 repo
gemartin99 repo
During the development of this project, AI tools were used as an auxiliary learning and productivity resource.
AI assitance was used for:
- Understanding theoretical concepts related to Docker, networking, system architecture and the deployed stack
- Helping structure and organize the development workflow
- Debugging issues and analyzing errors
- Writting the documentation
All AI-generated suggestions were critically reviewed, tested, and validated manually. No code or configuration was blindly copied without full understanding of its behavior and implications.
The final implementation reflects personal understanding of all components.
AI tools were used strictly as a support mechanism to enhance learning, not as replacement for development work.