기본 그룹www-data 제 컨테이너에서 일반적인 쓰기 가능 경로는 discourse:discourse 소유입니다. tmp/pids 또는 공유 경로에 소유권 불일치가 발생하면, 수동으로 discourse 사용자로 시작할 때는 정상 작동하더라도 www-data로 실행될 때 Sidekiq이 부팅 중에 종료될 수 있습니다.
강제된-L log/sidekiq.log공유 로그에 쓰기 로그 경로는 /shared/log/rails/sidekiq.log으로 향하는 심볼릭 링크입니다. 해당 파일/디렉터리의 소유권/권한이 다르게 재생성되면, Sidekiq은 유용한 로그를 생성하기도 전에 즉시 종료될 수 있습니다.
관련 트리거: 매일 실패하는 logrotate
별개로, logrotate가 매일 다음과 같은 오류로 실패하고 있었습니다:
error: skipping "...log" because parent directory has insecure permissions
Set "su" directive in config file ...
원인은 표준 Debian/Ubuntu 권한 설정이었습니다:
/var/log는 root:adm 소유이며 0775(그룹 쓰기 가능) 권한을 가지고 있습니다.
전역 su 지시문이 설정되지 않으면 logrotate는 로테이션을 거부합니다. 이는 업스트림의 예상된 동작입니다.
매일 logrotate 작업이 실패하던 시점에 /shared/log/rails/ 하위 파일들( sidekiq.log 포함)이 재생성되었으며, 이는 강제된 -L 로깅과 상호작용하여 Sidekiq의 “1s 크래시” 루프에 기여한 것으로 보입니다.
수정 방법 (재빌드 불필요)
logrotate를 수정하여 실패 상태일 때 공유 로그를 건드리지 않도록 합니다 전역 su 지시문을 추가합니다:
# /etc/logrotate.conf (상단)
su root adm
이후 logrotate -v는 0으로 종료되며 더 이상 불안전한 부모 디렉터리 권한을 보고하지 않습니다.
Sidekiq runit 스크립트를 더 견고한 기본값으로 교체합니다 discourse:discourse와 표준 sidekiq.yml로 전환하고, -L log/sidekiq.log를 강제하지 않으면 Sidekiq이 안정적으로 작동합니다:
sv status sidekiq
run: sidekiq: (pid <PID>) <SECONDS>s
즉, 이 이미지에서 Sidekiq는 Unicorn 마스터를 통해 시작되지 않습니다. 런타임 스크립트가 크래시 루프에 빠질 수 있는 runit 서비스입니다.
정확한 코드를
discourse_docker
레포지토리에서 볼 수 없는 이유
**/etc/service/sidekiq/run은 이미지 빌드/부팅 동안 생성되거나 주입되는 런타임 산출물(runtime artifact)**이기 때문에, discourse_docker에 문자 그대로의 파일로 존재하지 않을 수 있다는 점에는 동의합니다. 그러나 위와 같이, 이 공식 이미지에서 실제로 감독되는 활성 서비스임은 분명합니다.
취약성을 유발한 요인 (사실 + 최소한의 추론)
표준 Debian 권한(/var/log = root:adm 0775)으로 인해 logrotate가 매일 실패하는 것도 관찰되었습니다. 전역 su root adm를 추가하기 전까지는 logrotate가 로테이션을 거부했습니다.
logrotate가 실패할 때 /shared/log/rails/ 하위의 파일들, sidekiq.log를 포함하여 재생성되었습니다.
이 이미지의 기본 runit 스크립트는 discourse:www-data를 사용했으며, -L log/sidekiq.log를 /shared/log로 강제했습니다. 이로 인해 Sidekiq는 공유 볼륨 권한 드리프트(perms drift)에 매우 민감해지며, 유용한 로그가 기록되기 전에 즉시 종료될 수 있습니다.
요청 / 제안
위 내용을 고려할 때, 기본 Docker/runit Sidekiq 서비스를 강화하는 방안을 검토해 주실 수 있을까요?
제안하는 기본 설정:
discourse:discourse로 실행 (컨테이너 내부의 일반적인 소유권과 일치),
bundle exec sidekiq -C config/sidekiq.yml을 통해 시작,
공유 -L log/sidekiq.log를 강제하지 않거나 (또는 이를 견고하게 처리).
이렇게 하면 모든 백그라운드/AI 작업을 중단시키는 조용한 down: 1s 크래시 루프를 방지할 수 있습니다.
현재 공식 이미지에서 Sidekiq가 별도의 runit 서비스가 아님을 동의합니다 (/etc/service/sidekiq/ 디렉터리가 없음). 이는 unicorn runit 서비스의 시작 체인에서 시작되며, 이는 사용자의 /etc/service 목록과 일치합니다.
제 보고서는 그것이 독립적인 runit 유닛에 있든 unicorn/run 안에 있든 상관없이, 해당 Sidekiq 시작 경로의 런타임 실패 모드에 관한 것입니다:
제 VPS의 런타임에서 확인된 사실 (공식 Docker, 사고 직전에 재빌드/업그레이드 없음):
백그라운드 작업이 중단되고 AI 응답이 중단되었습니다.
컨테이너의 슈퍼바이저/시작 체인에 의해 시작될 때 Sidekiq은 즉시 크래시 루프(다운: 1초)에 진입했습니다.
discourse 사용자로 bundle exec sidekiq -C config/sidekiq.yml 명령을 통해 수동으로 시작했을 때 프로세스가 유지되고 작업이 처리되었으므로, 앱과 Redis는 정상 상태였습니다.
같은 시점에 logrotate 실패로 인해 /shared/log/rails/sidekiq.log(및 관련 경로)가 다른 권한으로 다시 생성되었습니다. Sidekiq 시작 명령을 안정화한 후(실행: discourse:discourse, 사용: sidekiq.yml, 공유 강제 -L sidekiq.log 회피`), 크래시 루프가 즉시 중단되었습니다.
따라서 이 이미지에서 /etc/service/sidekiq/run 파일이 실제로 존재하지 않을 수 있다는 점에는 동의합니다. 그러나 unicorn runit 서비스에 내장된 Sidekiq 시작 단계는 공유 볼륨 권한/logrotate 변동에 취약하여, 재빌드 없이도 Sidekiq을 조용히 종료시킬 수 있습니다. 이것이 핵심 문제입니다.
제안: 공식 unicorn runit 스크립트(또는 해당 스크립트가 생성되는 위치)에서 Sidekiq 시작 부분을 강화하는 것을 고려해 주십시오: