👩🏻💻 This project has been created as part of the 42 curriculum by michoi.
🐳 A system administration project that deepens your understanding of Docker by building a web infrastructure from scratch entirely inside a virtual machine.
The objective of the project is to containerize a WordPress stack made of three interdependent services. Each service is running in its own dedicated Docker container, all orchestrated by Docker Compose (in docker-compose.yml file). No pre-built images from Docker Hub are used. Every image is built from a custom Dockerfile based on the stable version of Alpine Linux.
The infrastructure is composed of:
| Service | Role |
|---|---|
| NGINX | Reverse proxy and sole entry point (port 443, TLSv1.2/1.3 only) |
| WordPress + php-fpm | Application server (no NGINX inside) |
| MariaDB | Database backend (no NGINX inside) |
Two Docker volumes persist data across restarts:
- WordPress database files
- WordPress website files
All services communicate through a custom Docker network. NGINX is the only container exposed to the outside world.
Virtual Machines emulate a full operating system with dedicated kernel, hardware abstraction, and hypervisor overhead. They are heavy (GBs of disk, minutes to start) but provide strong isolation.
Docker containers share the host kernel and package only the application and its dependencies. They are lightweight (MBs), start in seconds, and are ideal for deploying isolated, reproducible services — which is why they suit this project. However, they offer a lower level of isolation than VMs, which is why this project itself runs inside a virtual machine.
Environment variables are convenient but can be exposed through process listings, log output, or Docker inspect commands. For sensitive data (passwords, API keys), Docker secrets are the recommended approach: they store values in an in-memory tmpfs, accessible only inside the container at /run/secrets/, and never appear in image layers or environment dumps.
This project uses a .env file for non-sensitive configuration (domain name, usernames) and Docker secrets (via files in secrets/) for passwords and credentials.
Using network: host removes all network isolation — the container shares the host's network stack directly, which defeats the purpose of containerization and exposes all ports. This is forbidden in this project.
A custom Docker bridge network is used instead, allowing containers to communicate with each other by service name (DNS resolution) while remaining isolated from the host. NGINX is the only container bound to a host port (443).
Bind mounts link a host directory directly into the container. They are simple but tightly coupled to the host's filesystem layout.
Docker volumes are managed by Docker itself, stored under /var/lib/docker/volumes/, and are more portable and production-friendly. This project uses named volumes (stored at /home/<login>/data/ on the host via Docker configuration) for both the database and WordPress files, ensuring data persists across container restarts.
- A Linux virtual machine (e.g., Debian or Alpine)
- Docker and Docker Compose installed
makeinstalled- Your login and domain configured in
.envand/etc/hosts
-
Clone the repository:
git clone <your-repo-url> cd <repo-name>
-
Configure environment variables by editing
srcs/.env:DOMAIN_NAME=<your_login>.42.fr WORDPRESS_DATABASE_USER=<your_db_user> WORDPRESS_DATABASE_NAME=wordpress # ... (see USER_DOC.md for full list)
-
Add your domain to
/etc/hostson the host machine:127.0.0.1 <your_login>.42.fr
make # Builds all Docker images and starts the stackmake down # Stops and removes containersmake clean # Stops containers and removes volumes
make fclean # Full cleanup including built imagesOnce running, open your browser and navigate to:
https://<your_login>.42.fr
Note: Since TLS uses a self-signed certificate, your browser will show a warning. Accept it to proceed.
- Docker official documentation
- Docker Compose reference
- Best practices for writing Dockerfiles
- Docker secrets documentation
- Understanding PID 1 in containers
- NGINX documentation
- Configuring TLS in NGINX
- WordPress CLI (wp-cli)
- MariaDB documentation
- php-fpm configuration
AI tools (ChatGPT, Claude) were used during this project for the following tasks:
- Understanding concepts: Clarifying the differences between Docker volumes and bind mounts, Nginx and Wordpress configuration options, and MariaDB initialization flows.
- Debugging assistance: Helping interpret Docker error messages and suggest causes for container restart loops.
- Documentation drafting: Assisting in drafting initial versions of this README and the accompanying documentation files.
All AI-generated content was reviewed, tested, and validated before inclusion. No code was copied without full understanding of its behavior.