Skip to content
← All projects

2025

Inception

A Docker infrastructure that containerizes a complete WordPress site: NGINX with TLS 1.2/1.3, WordPress on PHP-FPM and MariaDB, each in its own Debian-based image and orchestrated with Docker Compose.

My role

1337 project. I wrote the three images, the Docker Compose setup and the configuration scripts.

Context

Inception is a 42 project about containerization, networking and data persistence: build a small, secure WordPress infrastructure with Docker Compose.

Problem

Run a WordPress site on three containers that talk only to each other, with NGINX as the single way in over HTTPS, no hardcoded passwords, and data that survives restarts.

Objectives

  • NGINX is the only entry point, on port 443 with TLS 1.2 or 1.3.
  • No hardcoded passwords: all configuration comes from environment variables.
  • Pinned base images with no latest tags (Debian here).
  • The database and the site files persist on the host.

What I built

NGINX

A debian:bullseye image that listens only on port 443. TLS 1.2 and 1.3 are enforced with a self-signed certificate that OpenSSL generates when the image is built. NGINX serves static files and passes PHP requests to WordPress over FastCGI on port 9000.

WordPress and PHP-FPM

A debian:bullseye image with PHP 7.4 and PHP-FPM. A startup script uses WP-CLI to download WordPress, write wp-config.php with the database connection, create an admin user and an editor user, and then run PHP-FPM on port 9000.

MariaDB

A debian:bullseye image with a custom 50-server.cnf that binds to 0.0.0.0 so the other containers can reach it. The mariadb.sh startup script creates the database and users, sets the root password and starts the server cleanly.

Compose, network and volumes

The three services share a bridge network called inception and reach each other by container name. They restart automatically, and only NGINX publishes a port. Two bind-mounted volumes keep the database and the WordPress files on the host. Credentials and site settings live in a .env file, and docker-compose up -d --build starts everything.

Architecture

Three containers on a custom bridge network. NGINX is the only one with a published port. It terminates TLS and forwards PHP to WordPress on port 9000, and WordPress talks to MariaDB on port 3306 by container name. NGINX and WordPress share the site files volume. Each service lives in srcs/requirements/ with its own Dockerfile, configuration and startup script, next to docker-compose.yml and .env, with a Makefile at the root.

Key decisions and trade-offs

  • Drive all configuration from a .env file.

    Trade-off: Passwords never appear in the Dockerfiles or scripts, and one file changes the whole setup. The cost is that the .env file has to exist and be kept private.

  • Expose only NGINX, on port 443 with TLS 1.2 and 1.3.

    Trade-off: All outside traffic goes through one encrypted entry point, and MariaDB and PHP-FPM stay on the internal network. The cost is a self-signed certificate, so browsers show a warning.

  • Persist data with bind mounts to host directories.

    Trade-off: The database and the site files survive rebuilds and sit in a known folder on the host. The cost is that the volumes are tied to host paths under /home/<login>/data.

Outcome

One command, docker-compose up -d --build, builds the three images and starts a working WordPress site over HTTPS, with an admin user and an editor user created automatically.

Stack

  • Docker
  • Docker Compose
  • NGINX
  • WordPress
  • MariaDB
  • PHP-FPM
  • Debian