這個問題 debug 了快三小時…終於在 gpt 的協助下找到問題

先來描述一下 context

  1. Container 要 Read-only
  2. python 3.12
  3. selenium 用 chormedriver

一直出現這個錯誤

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: probably user data directory is already in use, please specify a unique value for --user-data-dir argument, or don't use --user-data-dir

程式碼

from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from seleniumwire import webdriver
import os

chrome_options = Options()
chrome_options.add_argument("--incognito")
chrome_options.add_argument("--headless=new")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-extensions')
chrome_options.add_argument('--disable-setuid-sandbox')
chrome_options.add_argument("--disable-application-cache")
chrome_options.add_argument("--enable-do-not-track")
chrome_options.add_argument("--disable-popup-blocking")

driver = webdriver.Chrome(options=chrome_options)

一開始的程式好好的沒問題,但因為客戶要求要只能 readonly,但是因為該 pod 還是需要寫 tempfile 所以跟客戶要求只使用 /tmp 做為寫檔的地方,改好了其他 funtion,結果這個重要的爬蟲 function 出了問題

首先直接問 gpt,得到的答案跟 log 字面解釋的一樣

–user-data-dir 的使用上有問題,建議我使用 unique 的資料夾

我最先開始認為,因為是 read-only 的環境,可能 selenium 嘗試寫檔的時候被 block 了
於是我嘗試設定 –user-data-dir 到 /tmp file,並實際執行,結果還是一樣

# Create a temporary directory for the Selenium cache in /tmp
with tempfile.TemporaryDirectory(dir="/tmp") as custom_cache_dir:
    chrome_options.add_argument(f"--user-data-dir={custom_cache_dir}")
    print(custom_cache_dir)

由於一開始是在 aws ecs fargate 上執行,build + deploy 的過程少說都要 5 分鐘以上,相當難測,前後在那邊測試 code 超級惱人時間又被拖很長( 我用 Mac arm 架構,客戶環境 x86, 所以有點難直接在本機端測 ),後來乾脆開了一台 vm 用 docker 直接模擬環境( read-only 建立參考最底下備註)

首先看 log 遇到的第一個錯誤

Cache folder (/root/.cache/selenium) cannot be created: Read-only file system (os error 30)
看來是想寫東西到不能寫的地方
大概與 gpt 對話後就知道該怎麼修正
設定了一個環境變數就解決了

SE_CACHE_PATH=/tmp/selenium_cache

ok 解決掉這個 error 但是標題的問題還是一直存在
在不斷問答測試後才終於發現有兩個關鍵的環境變數也得設定

XDG_CONFIG_HOME=/tmp/xdg_config # default 是 ~/.config
XDG_CACHE_HOME=/tmp/xdg_cache   # default 是 ~/.cache

終於大功告成!!!

總結

在 dockerfile 或是 entrypoint 裡面設定環境變數

ENV SE_CACHE_PATH=/tmp/XXXX  #指定可以寫資料的地方
ENV XDG_CONFIG_HOME=/tmp/XXXX 
ENV XDG_CACHE_HOME=/tmp/XXXX 

備註

local 測試 readonly 方式

docker run --rm --read-only -v tmp-vol:/tmp -it {image} bash

ChatGPT 節錄的筆記


🧠 什麼是 XDG?


📦 XDG 最有名的規範:XDG Base Directory Specification

  • XDG 是一系列 Linux 桌面環境標準的集合
  • 目標是讓不同桌面環境(如 GNOME、KDE、Xfce)之間的軟體能「有一致的資料儲存位置與行為規範
    這是你在使用 XDG_CONFIG_HOMEXDG_CACHE_HOME 所依據的標準。

它定義了使用者應用程式該把以下這些資料存在哪裡:

資料類型 環境變數 預設值 用途
設定檔 (Config) XDG_CONFIG_HOME ~/.config 應用程式偏好設定等
快取檔 (Cache) XDG_CACHE_HOME ~/.cache 可刪除的中間檔案
資料檔 (Data) XDG_DATA_HOME ~/.local/share 長期資料,如使用者資料庫等
執行檔 (Runtime) XDG_RUNTIME_DIR 系統自動指定,如 /run/user/UID 暫時檔案,如 IPC socket

✅ 實際應用

許多知名應用程式都遵守這個標準,包括:

  • Chromium / Google Chrome
  • Firefox
  • Visual Studio Code
  • GNOME / KDE 工具
  • Docker CLI / Podman
  • Git credential helpers

🔧 舉個例子

如果沒設 XDG_CONFIG_HOME,VS Code 的設定會寫在:

~/.config/Code/User/settings.json

但如果你這樣設定:

export XDG_CONFIG_HOME=/tmp/vscode

它就會改寫到:

/tmp/vscode/Code/User/settings.json

🎯 為什麼開發者常常會接觸 XDG?

  • 在 Docker、Lambda、CI/CD 環境中,無法寫入 ~/.config~/.cache
  • 所以會把這些變數改指向 /tmp 或其他可寫目錄,避免程式出錯