@@ -873,16 +873,19 @@ finally:
873873<?xml version="1.0"?>
874874<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
875875<fontconfig>
876- <!-- Font directory list -->
876+ <!-- Font directory list (Noto CJK in truetype/noto-cjk and symlinks in noto/) -->
877877 <dir>/usr/share/fonts</dir>
878878 <dir>/usr/share/fonts/truetype</dir>
879879 <dir>/usr/share/fonts/truetype/noto-cjk</dir>
880+ <dir>/usr/share/fonts/noto</dir>
880881 <dir>/usr/share/fonts/opentype</dir>
881882 <dir>/usr/share/fonts/opentype/noto</dir>
882883
883884 <!-- Include conf.d directory for additional configurations -->
884885 <include ignore_missing="yes">conf.d</include>
885886
887+ <!-- Writable cache for containers (no /var/cache) -->
888+ <cachedir>/tmp/fontconfig-cache</cachedir>
886889 <!-- Rescan interval (in seconds) -->
887890 <rescan>
888891 <int>30</int>
@@ -951,12 +954,15 @@ FONTSCONF
951954 echo " Successfully copied $FONT_COUNT font files to $out/usr/share/fonts/truetype/noto-cjk"
952955 fi
953956
954- # Create symbolic links in alternative paths for compatibility with user scripts
955- # This allows scripts that check specific paths (like /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc) to find the fonts
957+ # Symlinks in standard paths so fontconfig and apps find Noto CJK reliably
956958 mkdir -p $out/usr/share/fonts/opentype/noto
959+ mkdir -p $out/usr/share/fonts/noto
960+ find $out/usr/share/fonts/truetype/noto-cjk -maxdepth 1 -type f \( -name "*.ttc" -o -name "*.otf.ttc" \) 2>/dev/null | while read f; do
961+ ln -sf ../../truetype/noto-cjk/$(basename "$f") $out/usr/share/fonts/noto/$(basename "$f") 2>/dev/null || true
962+ done
957963 if [ -f $out/usr/share/fonts/truetype/noto-cjk/NotoSansCJK-VF.otf.ttc ]; then
958964 ln -sf ../../truetype/noto-cjk/NotoSansCJK-VF.otf.ttc $out/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc 2>/dev/null || true
959- echo " Created symlink: /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc "
965+ echo " Created symlinks under /usr/share/fonts/noto and opentype/noto"
960966 fi
961967
962968 # Create fontconfig configuration
@@ -988,58 +994,23 @@ FONTSCONF
988994FONTCONF
989995
990996 # Create matplotlib configuration directory and file at build time
997+ # Use /tmp/.matplotlib so config dir is writable (font cache); /home may be read-only in containers
991998 mkdir -p $out/home/python-user/.matplotlib
999+ mkdir -p $out/tmp/.matplotlib
9921000 cat > $out/home/python-user/.matplotlib/matplotlibrc << 'MATPLOTLIBRC'
9931001font.family: sans-serif
9941002font.sans-serif: Noto Sans CJK JP, Noto Sans CJK TC, Noto Sans CJK SC, Noto Sans CJK KR, DejaVu Sans
9951003axes.unicode_minus: False
9961004MATPLOTLIBRC
1005+ cp $out/home/python-user/.matplotlib/matplotlibrc $out/tmp/.matplotlib/matplotlibrc
9971006
998- # Create font setup script for runtime
1007+ # Font setup at container start: writable dirs, matplotlibrc, font index, permissions for uv/cache
9991008 cat > $out/setup-fonts.sh << 'EOF'
10001009 #!/bin/bash
1001- # Setup Chinese fonts for matplotlib
1002- echo "Setting up Chinese font support..."
1003-
1004- # Ensure user cache directories exist (these can be created in tmpfs)
1005- mkdir -p /home/python-user/.cache/fontconfig 2>/dev/null || true
1006- mkdir -p /home/python-user/.matplotlib 2>/dev/null || true
1007-
1008- # Copy matplotlibrc from Nix store to runtime directory (if it exists)
1009- # The runtime directory is tmpfs, so we need to copy the config file
1010- if [ -f /nix/store/*-docker-setup/home/python-user/.matplotlib/matplotlibrc ]; then
1011- MATPLOTLIBRC_SOURCE=$(find /nix/store -path "*/docker-setup/home/python-user/.matplotlib/matplotlibrc" 2>/dev/null | head -1)
1012- if [ -n "$MATPLOTLIBRC_SOURCE" ]; then
1013- cp "$MATPLOTLIBRC_SOURCE" /home/python-user/.matplotlib/matplotlibrc 2>/dev/null || true
1014- fi
1015- fi
1016-
1017- # Create/update matplotlibrc with correct font names
1018- # Use actual available font names: Noto Sans CJK JP (available) instead of SC (may not be available)
1019- cat > /home/python-user/.matplotlib/matplotlibrc << 'MATPLOTLIBRC'
1020- font.family: sans-serif
1021- font.sans-serif: Noto Sans CJK JP, Noto Sans CJK TC, Noto Sans CJK SC, Noto Sans CJK KR, DejaVu Sans
1022- axes.unicode_minus: False
1023- MATPLOTLIBRC
1024-
1025- # Update font cache (if fontconfig is available)
1026- # Note: Font files are already in /usr/share/fonts/truetype/noto-cjk (copied at build time)
1027- if command -v fc-cache >/dev/null 2>&1; then
1028- fc-cache -fv 2>/dev/null || true
1029- fi
1030-
1031- # Verify font files are accessible
1032- if [ -f /usr/share/fonts/truetype/noto-cjk/NotoSansCJK-VF.otf.ttc ]; then
1033- echo "✓ Noto CJK font files found in /usr/share/fonts/truetype/noto-cjk/"
1034- else
1035- echo "⚠ Warning: Noto CJK font files not found in expected location"
1036- fi
1037-
1038- # Set matplotlib font configuration environment variables
1039- export MPLCONFIGDIR=/home/python-user/.matplotlib
1040- export FONTCONFIG_PATH=/etc/fonts
1041-
1042- # Ensure fonts.conf exists (fontconfig requires it)
1010+ echo "Setting up Chinese font support for matplotlib..."
1011+ mkdir -p /tmp/.matplotlib /tmp/fontconfig-cache /tmp/.cache/fontconfig /tmp/fonts-cache
1012+ chmod -R 0777 /tmp/.matplotlib /tmp/fontconfig-cache /tmp/.cache /tmp/fonts-cache 2>/dev/null || true
1013+ printf '%s\n' 'font.family: sans-serif' 'font.sans-serif: Noto Sans CJK JP, Noto Sans CJK TC, Noto Sans CJK SC, Noto Sans CJK KR, DejaVu Sans' 'axes.unicode_minus: False' > /tmp/.matplotlib/matplotlibrc
10431014 if [ ! -f /etc/fonts/fonts.conf ]; then
10441015 mkdir -p /etc/fonts
10451016 cat > /etc/fonts/fonts.conf << 'FONTSCONF'
@@ -1049,17 +1020,18 @@ MATPLOTLIBRC
10491020 <dir>/usr/share/fonts</dir>
10501021 <dir>/usr/share/fonts/truetype</dir>
10511022 <dir>/usr/share/fonts/truetype/noto-cjk</dir>
1023+ <dir>/usr/share/fonts/noto</dir>
10521024 <dir>/usr/share/fonts/opentype</dir>
10531025 <dir>/usr/share/fonts/opentype/noto</dir>
10541026 <include ignore_missing="yes">conf.d</include>
1055- <rescan>
1056- <int>30</int>
1057- </rescan>
1027+ <cachedir>/tmp/fontconfig-cache</cachedir>
1028+ <rescan><int>30</int></rescan>
10581029</fontconfig>
10591030FONTSCONF
10601031 fi
1061-
1062- echo "Chinese font support configured"
1032+ command -v fc-cache >/dev/null 2>&1 && fc-cache -fv /usr/share/fonts 2>/dev/null || true
1033+ chmod -R 0777 /home/python-user /.local 2>/dev/null || true
1034+ [ -f /usr/share/fonts/truetype/noto-cjk/NotoSansCJK-VF.otf.ttc ] && echo "✓ Noto CJK fonts ready (MPLCONFIGDIR=/tmp/.matplotlib)" || echo "⚠ Noto CJK fonts not found"
10631035 EOF
10641036
10651037 chmod +x $out/setup-fonts.sh
13131285 # Rarely changed items (like system libraries) go in bottom layers
13141286 contents = [
13151287 runtimeEnv # Layer group 1: System Python, libraries (rarely changes)
1316- dockerSetup # Layer group 2: Setup scripts and configs (occasionally changes)
1288+ dockerSetup # Layer group 2: Setup scripts, fonts, configs (occasionally changes)
1289+ pkgs . fontconfig # fc-cache at container start for font index
13171290 pkgs . cacert # Layer group 3: CA certificates (rarely changes)
13181291 ] ;
13191292
@@ -1326,10 +1299,11 @@ in
13261299 set -eu
13271300
13281301 # Ensure runtime directories exist in the layer
1329- mkdir -p tmp tmp/.uv_cache .local/lib/python3.12/site-packages home/python-user app
1302+ mkdir -p tmp tmp/.uv_cache tmp/.matplotlib tmp/fontconfig-cache tmp/.cache/fontconfig .local/lib/python3.12/site-packages home/python-user app
13301303 mkdir -p usr/share/fonts/truetype/noto-cjk
13311304 mkdir -p usr/share/fonts/opentype/noto
13321305 mkdir -p etc/fonts/conf.d
1306+ chmod -R 0777 tmp/.matplotlib tmp/fontconfig-cache tmp/.cache 2>/dev/null || true
13331307
13341308 # Ensure fonts.conf exists (fontconfig requires it)
13351309 if [ ! -f etc/fonts/fonts.conf ]; then
13431317 <dir>/usr/share/fonts/opentype</dir>
13441318 <dir>/usr/share/fonts/opentype/noto</dir>
13451319 <include ignore_missing="yes">conf.d</include>
1320+ <cachedir>/tmp/fontconfig-cache</cachedir>
13461321 <rescan>
13471322 <int>30</int>
13481323 </rescan>
@@ -1397,9 +1372,13 @@ FONTSCONF
13971372 "SSL_CERT_FILE=${ pkgs . cacert } /etc/ssl/certs/ca-bundle.crt"
13981373 "CURL_CA_BUNDLE=${ pkgs . cacert } /etc/ssl/certs/ca-bundle.crt"
13991374 "REQUESTS_CA_BUNDLE=${ pkgs . cacert } /etc/ssl/certs/ca-bundle.crt"
1400- # Font configuration for matplotlib
1375+ # Locale and fonts: support Chinese paths and ensure fontconfig finds config
1376+ "LANG=C.UTF-8"
1377+ "LC_ALL=C.UTF-8"
14011378 "FONTCONFIG_PATH=/etc/fonts"
1402- "MPLCONFIGDIR=/home/python-user/.matplotlib"
1379+ "FONTCONFIG_FILE=/etc/fonts/fonts.conf"
1380+ "MPLCONFIGDIR=/tmp/.matplotlib"
1381+ "XDG_CACHE_HOME=/tmp/.cache"
14031382 # PTY/TUI: terminal type for interactive shells (vim, less, top, etc.)
14041383 "TERM=xterm-256color"
14051384 # Disable dangerous modules
0 commit comments