Skip to content

Commit e151b6b

Browse files
committed
feat: improve CJK font and locale for matplotlib in containers
- setup-fonts.sh: write matplotlibrc with printf (fix nested heredoc), run fc-cache -fv /usr/share/fonts, chmod /home/python-user and /.local - Add LANG=C.UTF-8, LC_ALL=C.UTF-8, FONTCONFIG_FILE to image Env - Add /usr/share/fonts/noto symlinks and fonts.conf dir for Noto CJK - Add pkgs.fontconfig to contents for fc-cache at container start
1 parent 6ab4943 commit e151b6b

1 file changed

Lines changed: 35 additions & 56 deletions

File tree

docker.nix

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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
988994
FONTCONF
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'
9931001
font.family: sans-serif
9941002
font.sans-serif: Noto Sans CJK JP, Noto Sans CJK TC, Noto Sans CJK SC, Noto Sans CJK KR, DejaVu Sans
9951003
axes.unicode_minus: False
9961004
MATPLOTLIBRC
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>
10591030
FONTSCONF
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
@@ -1313,7 +1285,8 @@ in
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
@@ -1343,6 +1317,7 @@ in
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

Comments
 (0)