project-image
devops

Jul 18, 2024

    docker
    nginx
    mariadb
    wordpress

Developer Documentation

This document describes how to set up, build, run, and manage the Inception stack as a developer.

1. Setting up the environment from scratch

Prerequisites

  • A Linux virtual machine (the subject requires the whole project to run inside a VM, not directly on bare metal).
  • docker and docker-compose installed on that VM.
  • make.

Repository layout

.
├── Makefile
└── srcs/
    ├── docker-compose.yml
    ├── .env                       # not committed — you must create this
    └── requirements/
        ├── nginx/
        │   ├── Dockerfile
        │   └── conf/setup.sh
        ├── mariadb/
        │   ├── Dockerfile
        │   └── conf/setup.sh
        ├── wordpress/
        │   ├── Dockerfile
        │   └── conf/setup.sh
        └── bonus/
            ├── redis/Dockerfile
            ├── ftp/{Dockerfile, conf/setup.sh}
            ├── adminer/Dockerfile
            ├── website/{Dockerfile, index.js, package.json, public/}
            └── cadvisor/Dockerfile

Configuration: srcs/.env

This file does not exist in the repository (it's git-ignored, see .gitignore) and must be created manually before the first run, at srcs/.env:

# Domain name your NGINX certificate and WordPress site URL will use
HOST_NAME=aamhamdi.42.fr

# MariaDB
SQL_DB=wordpress
SQL_USER=wp_user
SQL_PASS=change_me

# WordPress admin (username must NOT contain admin/administrator, per subject rules)
WP_USER=some_admin_login
WP_PASS=change_me
WP_MAIL=admin@example.com

# WordPress second user (non-admin)
WP_USER1=second_user
WP_PASS1=change_me
WP_MAIL1=second@example.com

# FTP
FTP_USER=ftpuser
FTP_PASS=change_me

No credential is ever hardcoded in any Dockerfile or entrypoint script — every script reads these from the environment, injected via env_file: .env in docker-compose.yml.

DNS / hosts entry

On any machine that needs to browse the site (the VM itself, or your host laptop if testing from outside the VM), point HOST_NAME at the VM's IP, e.g. in /etc/hosts:

192.168.x.x   aamhamdi.42.fr

2. Building and launching the project

The Makefile at the repo root wraps Docker Compose:

make

This expands to:

mkdir -p /home/aamhamdi/data/mariadb
mkdir -p /home/aamhamdi/data/wordpress
docker-compose -f srcs/docker-compose.yml build
docker-compose -f srcs/docker-compose.yml up
  • The two mkdir -p calls create the host directories backing the named volumes (see §4 below) — they must exist before Compose starts the containers.
  • build builds every service's image from its own Dockerfile (no pre-built images are pulled, aside from the debian:bullseye base).
  • up starts every container, in dependency order (mariadbwordpressnginx, etc., as declared via depends_on in docker-compose.yml).

To stop and remove the containers:

make stop
# equivalent to: docker-compose -f srcs/docker-compose.yml down

Run docker-compose -f srcs/docker-compose.yml up -d directly (instead of through make) if you want detached mode while iterating.

3. Managing containers and volumes

Useful day-to-day commands while developing:

# List running containers and their status
docker ps

# Follow logs for one service (e.g. while debugging WordPress startup)
docker logs -f wordpress
docker logs -f nginx
docker logs -f mariadb

# Get a shell inside a running container
docker exec -it wordpress bash

# Rebuild a single service after editing its Dockerfile/entrypoint
docker-compose -f srcs/docker-compose.yml build wordpress
docker-compose -f srcs/docker-compose.yml up -d wordpress

# Inspect networks and volumes
docker network ls
docker network inspect inception

docker volume ls
docker volume inspect wordpress
docker volume inspect mariadb

Each service container restarts automatically on crash (restart: always in docker-compose.yml), so you generally don't need to manually restart a container unless you changed its image or configuration.

4. Where project data lives and how it persists

Two pieces of state are required to survive container recreation, per the subject:

Named volumeBacking host pathMounted intoContains
mariadb/home/aamhamdi/data/mariadbmariadb:/var/lib/mysqlThe WordPress database
wordpress/home/aamhamdi/data/wordpresswordpress:/var/www/wordpress, and also mounted read-only-in-spirit into nginx and ftpThe WordPress site files (core, themes, plugins, uploads)

These are declared in docker-compose.yml as Docker named volumes using the local driver with driver_opts pointing device: at the fixed host paths above (type: none, o: bind) — so they behave as proper named volumes from Compose's perspective (referenced by name, managed by docker volume), while the underlying data is still physically stored at the exact host location the subject requires, rather than in Docker's default internal storage area.

A third volume, adminer (no device: override — Docker-managed default location), is used purely to share the downloaded adminer.php file between the adminer container (which runs it via PHP-FPM) and nginx (which serves it as static document root for the Adminer vhost on port 8081). It does not hold anything that needs to survive being recreated — it is repopulated on every adminer image build.

If you ever need to fully wipe and reset the project's data:

make stop
docker volume rm wordpress mariadb adminer
sudo rm -rf /home/aamhamdi/data/wordpress /home/aamhamdi/data/mariadb
make

This will trigger a fresh WordPress install (the wordpress entrypoint script checks wp core is-installed and only runs the install sequence when the site isn't already set up).