環境
前提
- OPcache
- キャッシュ有効化
- file_cache_onlyが無効
- lockfile_pathが/tmp
- PHP-FPM
- pidへのファイルパスなし
- Docker
- Read Only mode
方法
opcacheのロックファイルが作成される/tmpにvolumeをマウントします。
docker run -d -p 9000:9000 --read-only -v $(pwd)/tmp:/tmp php:7.3-fpm-alpine3.12
解説
なぜ/tmpにvolumeをマウントさせるのかを説明します。
opcacheは共有メモリにキャッシュするためにロックファイルが必要です。
zend_shared_alloc_create_lock関数内で、mkstempをコールして/tmpにロックファイルを作成します。
作成失敗の場合は、Unable to create lock file
というエラーメッセージを出力後に異常終了します。
ロックファイルの作成関数
void zend_shared_alloc_create_lock(char *lockfile_path)
{
int val;
#ifdef ZTS
zts_lock = tsrm_mutex_alloc();
#endif
snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX);
lock_file = mkstemp(lockfile_name);
fchmod(lock_file, 0666);
if (lock_file == -1) {
zend_accel_error(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
}
val = fcntl(lock_file, F_GETFD, 0);
val |= FD_CLOEXEC;
fcntl(lock_file, F_SETFD, val);
unlink(lockfile_name);
}
zend_shared_alloc_create_lockはzend_shared_alloc_startupからコールされ、実行時設定のlockfile_pathを引数として渡します。
zend_shared_alloc_create_lockの呼び出し元
int zend_shared_alloc_startup(size_t requested_size)
{
/* 省略 */
#ifndef ZEND_WIN32
zend_shared_alloc_create_lock(ZCG(accel_directives).lockfile_path);
#else
zend_shared_alloc_create_lock();
#endif