The “Golden Path” Guide: Installing WriteFreely with Docker (2025 Edition)
This method builds the image directly from the official WriteFreely source code, ensuring you are up-to-date. It also fixes common “split-brain” configuration issues where the app can’t talk to the database.
Prerequisites:
- A server or computer (Linux is best).
dockerandgitinstalled.
Step 1: Create the Directory Structure
We need a clean folder structure. We will use two separate folders for data to avoid file conflicts.
1. Create the main folder
sudo mkdir -p /opt/writefreely
2. Create the data sub-folders
app_data holds your config and keys.
sudo mkdir -p /opt/writefreely/app_data
db_data holds the database files.
sudo mkdir -p /opt/writefreely/db_data
3. Enter the directory
cd /opt/writefreely
Step 2: Get the Official Code
We aren’t downloading a pre-made image; we are downloading the recipe to build it ourselves.
git clone https://github.com/writefreely/writefreely.git
Step 3: Create the Configuration Files
We need two files.
1. The .env file
This configures the Database. Create a file named .env and paste this in. Change the passwords!
# /opt/writefreely/.env
MARIADB_ROOT_PASSWORD=change_this_to_a_strong_root_password
MARIADB_DATABASE=writefreely
MARIADB_USER=writefreely
MARIADB_PASSWORD=change_this_to_a_strong_user_password
2. The docker-compose.yml file
This tells Docker how to run everything. Create a file named docker-compose.yml and paste this exact content:
services:
app:
# Build from the official code we cloned
build:
context: ./writefreely
dockerfile: Dockerfile.prod
image: writefreely-local-prod:latest
container_name: writefreely-app
depends_on:
db:
condition: service_healthy
ports:
- 8080:8080
volumes:
# Map the app_data folder to the container
- ./app_data:/data
restart: unless-stopped
networks:
- writefreely-net
db:
image: mariadb:latest
container_name: writefreely-db
init: true
volumes:
# Map the db_data folder to the container
- ./db_data:/var/lib/mysql
env_file:
- .env
restart: unless-stopped
healthcheck:
test: [“CMD-SHELL”, “mysqladmin ping -h localhost -u $$MARIADB_USER -p$$MARIADB_PASSWORD”]
interval: 30s
timeout: 10s
retries: 5
start_period: 10s
networks:
- writefreely-net
networks:
writefreely-net:
driver: bridge
Step 4: Build the Image
This might take a few minutes. It compiles the latest version of WriteFreely for your machine.
docker compose build app
Step 5: Start the Database
We need the database running before we can configure the app.
docker compose up -d db
Wait!
Run
docker ps -a --format "table {{.Names}}\\t{{.Status}}"
Wait until the status for writefreely-db says (healthy). Do not proceed until it is healthy.
Step 6: Run the Configuration Wizard
This is the most critical step. We need to create a config.ini file that matches your .env file.
docker compose run --rm app writefreely config start
Answer the prompts exactly like this:
- Choose your configuration: Select
Production, behind reverse proxy. - Database setup: Select
MySQL. - Username:
writefreely - Password: (Enter the exact
MARIADB_PASSWORDyou put in your.envfile). - Database name:
writefreely - Host:
db(Important: Typedb, do NOT type localhost). - Port:
3306
Follow the rest of the prompts to name your blog and create your admin user.
Step 7: Final Initialization
Run these commands one by one to finish the setup.
1. Generate encryption keys
docker compose run --rm app writefreely keys generate
2. Create the database tables
docker compose run --rm app writefreely --init-db
Step 8: Launch!
Everything is ready. Start the application.
docker compose up -d
Your blog is now running at http://YOUR_IP:8080.