TLDR:
My final goal is to have a working config for WordPress related services on localhost as a nix declarative container with ability to automatically configure set of plugins and themes.
The whole wp-content
directory from the container should be synced with my local host filesystem.
It should run these services:
- nginx
- phpfpm
- mysql
- wordpress
- traefik ( the subdomain name
.docker.localdev
might be misleading, I don’t use docker in my nix container. I just had this name pre-configured in my system.
THE DETAILS:
I was trying translate this docker-compose to nix declarative container but without usage of docker:
sersion: '3'
services:
mariadb:
image: bitnami/mariadb:latest
volumes:
- 'mariadb_data:/bitnami/mariadb'
restart: always
environment:
- MARIADB_ROOT_PASSWORD=wordpress
- MARIADB_DATABASE=wordpress
- MARIADB_USER=wordpress
- MARIADB_PASSWORD=wordpress
networks:
- web
healthcheck:
test: [ 'CMD', '/opt/bitnami/scripts/mariadb/healthcheck.sh' ]
interval: 15s
timeout: 5s
retries: 6
wordpress:
image: wordpress:latest
# command: -H unix:///var/run/docker.sock
ports:
- 8080:80
expose:
- 8080
security_opt:
- no-new-privileges:true
networks:
- web
depends_on:
- mariadb
restart: always
environment:
- WORDPRESS_DB_HOST=mariadb
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
labels:
- traefik.enable=true
- traefik.docker.network=web
- traefik.http.routers.wp-http.entrypoints=web
- traefik.http.routers.wp-http.rule=Host(`wp.docker.localdev`)
- traefik.http.routers.wp-http.middlewares=wp-https
- traefik.http.middlewares.wp-https.redirectscheme.scheme=https
- traefik.http.routers.wp-https.entrypoints=websecure
- traefik.http.routers.wp-https.rule=Host(`wp.docker.localdev`)
- traefik.http.routers.wp-https.tls=true
# - traefik.http.services.wp.loadbalancer.server.port=8080
volumes:
- ./wp-content:/var/www/html/wp-content
volumes:
db_data:
mariadb_data:
driver: local
networks:
web:
external: true
I am using extra-container, which can run declarative NixOS containers like imperative containers, without system rebuilds, from any folder.
I was fiddling around with nix container config, it partially work for me but i need some advice to fine tune it.
{ pkgs, lib, config, ... }:
let
app = "wpdemo";
socket = "/run/phpfpm/${app}.sock";
domain = "localhost";
dataDir = "/var/www/public";
in
{
containers.wp = {
config = {
networking.firewall.enable = false;
security.acme.defaults.email = "admin@docker.localdev";
networking.firewall.allowedTCPPorts = [ 80 82 ];
services.traefik = {
enable = true;
staticConfigOptions = {
providers.docker = {
exposedByDefault = false;
};
entryPoints.web.address = ":80";
};
dynamicConfigOptions = {
http.routers.wp = {
rule = "Host(`wp.docker.localdev`)";
entryPoints = [ "web" ];
service = "wp-service";
};
http.services.wp-service.loadBalancer.server.port = 82;
};
};
services.phpfpm.pools.${app} = {
user = app;
settings = {
"listen.owner" = "nginx";
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
};
phpEnv."PATH" = lib.makeBinPath [ pkgs.php ];
};
services.mysql = {
enable = true;
package = pkgs.mysql;
};
services.wordpress = {
webserver = "nginx";
sites."wp.docker.localdev" = {
themes =
let
storefrontTheme = pkgs.stdenv.mkDerivation {
name = "storefront-theme";
src = pkgs.fetchurl {
url = "https://downloads.wordpress.org/theme/storefront.4.2.0.zip";
sha256 = "J9q50EhIWflZNhE6gMt4YakFKhIMDORfWwauXHfiQ0A=";
};
nativeBuildInputs = [ pkgs.unzip ];
installPhase = ''
mkdir -p $out; cp -R * $out/
'';
};
in
[ storefrontTheme ];
plugins =
let
woocommercePlugin = pkgs.stdenv.mkDerivation {
name = "woocommerce-plugin";
src = pkgs.fetchurl {
url = "https://downloads.wordpress.org/plugin/woocommerce.7.4.1.zip";
sha256 = "a/I10n+J/mWa55fMsfi54CR2F0FPkDpEjStQiRPSgWY=";
};
nativeBuildInputs = [ pkgs.unzip ];
installPhase = ''
mkdir -p $out; cp -R * $out/
'';
};
in
[ woocommercePlugin ];
extraConfig = ''
define('WP_POST_REVISIONS', 3);
'';
};
};
services.nginx = {
enable = true;
virtualHosts.${domain} = {
listen = [{ addr = "127.0.0.1"; port = 80; }];
serverName = "wp.docker.localdev";
locations."/" = {
root = /var/www/public;
extraConfig = ''
access_log off;
charset utf-8;
etag off;
index index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
}
'';
};
};
};
users.users.${app} = {
isSystemUser = true;
createHome = true;
home = dataDir;
group = app;
};
users.groups.${app} = { };
};
};
}
The problems with this config:
-
The nginx service root
locations."/" = { root = /var/www/public; }
-
Current setup: i created
/var/www/public
on local file system and extracted wordpress manualy there so it copies files from my local system to the container. - Expected setup: Wordpress sholud be downloaded an run inside continer on /var/www/public without any manual steps.
-
services.wordpress downloads
woocomerce
plugin andstorefront
theme to the nix store inside container
Problem : i don’t have idea how to link it to /var/www/public in the container.
- I tried copy or symlink it inside wordpress service
installPhase = ''
mkdir -p $out; cp -R * $out/
mkdir -p ${dataDir}/wp-content/plugins/woocommerce
cp -R $out/* ${dataDir}/wp-content/plugins/woocommerce
''
installPhase = ''
mkdir -p $out; cp -R * $out/
mkdir -p ${dataDir}/wp-content/plugins/woocommerce
ln -s $out/ ${dataDir}/wp-content/plugins/woocommerce
''
got error: mkdir: cannot create directory '/var': Permission denied
i have issues with permissions, how to fix it in a declarative way?
- Current setup: manually added plugins
- Expected setup: wordpress user and db should be crated automatically
-
The
services.mysql
. i tried to add this config to create database automatically, but i couldn’t connect to DB.
services.mysql = {
enable = true;
package = pkgs.mariadb;
initialScript =
pkgs.writeText "initial-script" ''
CREATE USER 'admin'@localhost IDENTIFIED BY 'password';
ALTER USER 'admin'@'localhost' IDENTIFIED BY 'password';
grant all privileges on *.* to 'admin'@localhost identified by 'password';
CREATE DATABASE wordpress;
'';
ensureDatabases = [
"wordpress"
];
ensureUsers = [
{
name = "admin";
ensurePermissions = {
"admin.*" = "ALL PRIVILEGES";
"*.*" = "ALL PRIVILEGES";
};
}
];
};
- Current setup: Create WordPress user and db manually from MySQL CLI
- Expected setup: WordPress user and db should be crated automatically
- sync the contents of wp-content inside container to my local system . i-do-nix suggested my the working solution for this:
containers.abc = {
bindMounts = {
"/path/in/container" = {
hostPath = "/path/on/host";
isReadOnly = true;
};
};
# config = ...
};
However, first i must solve the previous issues. Thank in advance for any tips or suggestions.