최신 버전 빌드 시 오류 발생

안녕하세요. 최신 버전의 Discourse에서 ./installer rebuild web_only를 실행하면 다음과 같은 오류가 발생합니다.

fs.js:114
    throw err;
    ^

Error: ENOENT: no such file or directory, open 'root='/assets',url='/assets/vendor-4681e47c140b5a5bea2bfb1fec89365858288a8ea0c21979c0167ad9b570ee3d.js.map''
    at Object.openSync (fs.js:438:3)
    at Object.writeFileSync (fs.js:1189:35)
    at done (/usr/lib/node_modules/uglify-js/bin/uglifyjs:516:20)
    at cb (/usr/lib/node_modules/uglify-js/bin/uglifyjs:324:39)
    at /usr/lib/node_modules/uglify-js/bin/uglifyjs:391:9
    at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)
rake aborted!
Errno::ENOENT: No such file or directory @ rb_file_s_size - /var/www/discourse/public/assets/vendor-4681e47c140b5a5bea2bfb1fec89365858288a8ea0c21979c0167ad9b570ee3d.js
/var/www/discourse/lib/tasks/assets.rake:268:in `size'
/var/www/discourse/lib/tasks/assets.rake:268:in `block (4 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:159:in `block in concurrent?'
/var/www/discourse/lib/tasks/assets.rake:259:in `block (3 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:250:in `each'
/var/www/discourse/lib/tasks/assets.rake:250:in `block (2 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:159:in `concurrent?'
/var/www/discourse/lib/tasks/assets.rake:247:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => assets:precompile
(See full trace by running task with --trace)
I, [2019-12-11T22:53:15.806396 #18]  INFO -- : Downloading MaxMindDB...
Compressing Javascript and Generating Source Maps



FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake assets:precompile' failed with return #<Process::Status: pid 17151 exit 1>
Location of failure: /pups/lib/pups/exec_command.rb:112:in `spawn'
exec failed with the params {"cd"=>"$home", "hook"=>"assets_precompile", "cmd"=>["su discourse -c 'bundle exec rake assets:precompile'"]}
f565d457b97d7ff12a258b03a456563a5a0e928c707c70e194ef88ba170aaf3a
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one

모든 플러그인을 비활성화했지만 여전히 해결되지 않습니다. 이 문제에 대해 조언해 주실 분 있으신가요?

이전에 다른 곳에서 비슷한 상황을 본 적이 있습니다.

아래 내용을 시도해 보세요.

./launcher cleanup
git pull
./launcher rebuild app

이렇게 해도 해결되지 않으면, 해당 머신의 모든 컨테이너와 이미지를 삭제해 보세요.

@sam 빠른 답변 감사합니다. 말씀하신 방법을 시도해 보겠습니다.

간단한 질문이 있습니다. git pull은 discourse-docker의 최신 버전을 가져오는 것이라고 이해하면 되나요?

일반적으로 discourse-docker와 discourse를 동시에 업그레이드해야 하는가요?

현재 저는 discourse-docker를 git으로 관리하지 않고 있습니다. 대신 서버를 설정할 때 discourse-docker의 특정 리비전(Zip 파일)을 다운로드하고, discourse 배포 시 discourse의 버전을 특정 커밋으로 고정하고 있습니다.

이렇게 하는 이유는 빌드를 재현 가능하게(repeatable) 만들기 위해서입니다. 즉, 서로 다른 두 시점에 동일한 명령어와 설정 + 소스를 실행하면 동일한 산출물이 생성되어야 한다는 원칙입니다. 일반적으로 이는 좋은 관행이며, 지난 수년간 다른 소프트웨어에서 운영 관련 악몽을 겪지 않도록 도와주었습니다. :wink: 이는 알려진 정상적인 설정으로 롤백할 수 있는 능력을 제공하기 때문입니다.

하지만 discourse의 경우, 빌드 과정에서 다양한 소프트웨어의 최신 버전을 가져오려는 경향이 있어 제가 역류에 맞서 싸우고 있는 것 같습니다. 빌드를 재현 가능하게 하려는 제 시도가 오히려 자충수가 되고 있는 건 아닌지 의심이 들기 시작합니다.

정말 그 말에 동의합니다. 이 해킹으로 인해 100% 지원되지 않는 상태에 들어갔네요 :flushed_face:

가장 빠른 시일 내에 git에서 최신 버전으로 업데이트하는 것을 권장합니다.

기존의 Discourse 기반 Docker 이미지는 현재 Discourse와 호환되지 않을 뿐만 아니라, 많은 보안 패치도 누락되어 있습니다.

감사합니다, @sam. 말씀하신 대로 처리했고 이제 새 버전을 빌드할 수 있습니다. 다행히 이건 전부 베타 환경에서 일어난 일이어서 큰 문제는 없었습니다 :slight_smile: 하지만 재현 가능한 빌드를 원한다고 해서 그게 '해커 짓(hackery)'인지는 잘 모르겠네요 :thinking:

제가 여기서 달성하고 싶은 것은 알려진 정상 상태의 버전으로 롤백할 수 있는 기능입니다. 예를 들어 t1 시점에 ./launcher rebuild app을 실행했는데 discourse가 정상적으로 동작한다고 가정해 보겠습니다. 그런 다음 t2 시점에 ./launcher rebuild app을 다시 실행했는데 문제가 발생했습니다. 이전 버전으로 소프트웨어를 되돌리는 방법은 무엇인가요? 빌드가 재현 가능하지 않다는 사실은 받아들일 수 있지만, 알려진 정상 상태로 롤백할 수 있다면 괜찮을 것 같습니다. 런처는 이미 t1 시점에 정상적으로 동작하는 docker 이미지를 빌드했으므로, t2 시점에 빌드된 잘못된 이미지 대신 특정 이미지를 사용하도록 런처를 지정할 수 있을까요?

어떤 아이디어라도 있을까요?

조금 주제에서 벗어난 것 같아 죄송합니다. 원하시면 다시 게시할 수 있습니다.

재현 가능한 빌드를 원하신다면 컨테이너 설정을 통해 discourse 버전을 특정 sha에 고정하고, 모든 플러그인도 마찬가지여야 합니다.

이 경우 discourse의 수정 사항, docker 이미지의 보안 패치 등을 더 이상 받을 수 없게 되지만, 빌드는 상당히 재현 가능해집니다.

apt 의존성의 보안 패치를 받지 않도록 템플릿도 수정하여 관련 사항을 고정해야 할 수 있습니다.

네, 저는 이미 discourse의 버전을 특정 커밋으로 고정했고, 플러그인도 이렇게 처리할 수 있습니다. 하지만 discourse-docker까지 고정하지 않으면, discourse-base는 빌드할 때마다 업데이트되지만 discourse는 업데이트되지 않는 상황이 발생하지 않을까요? 그러면 discourse-base가 discourse보다 앞서게 되어, 역방향으로 비슷한 호환성 문제가 생기지는 않을까요?

혼란스럽습니다. Discourse를 오래된 버전으로 고정해 두었는데, 이 오류는 어떻게 나타났나요?

NGINX에 치명적인 취약점이 있다면, 그걸 수정하고 싶으신가요?

고정된 Discourse 버전을 2.4.0.beta2에서 2.4.0beta8로 변경했을 때 오류가 발생했습니다.

물론 새 빌드를 실행할 때 종속 소프트웨어 시스템의 치명적인 취약점이 수정되기를 원합니다! 정말 멋진 일이죠!

하지만 새 버전이 깨진 경우 롤백할 수 있는 기능도 필요하죠 :slight_smile:

구체적인 예를 들어 보겠습니다.

현재 제 설정 상태가 다음과 같다고 가정해 보겠습니다:

discourse : 2.4.0beta2 (web_only.yml에서 고정됨)

./launcher rebuild web_only를 실행하면 모든 것이 정상 작동합니다.

이제 제 시스템은 다음과 같은 상태가 됩니다:

discourse : 2.4.0beta2
discourse-docker: T1 시점의 LATEST

이제 설정을 다음과 같이 변경합니다:

discourse : 2.4.0beta8 (web_only.yml에서 고정됨)

./launcher rebuild web_only를 실행하면 무언가가 깨집니다.

이제 제 시스템은 다음과 같은 상태가 됩니다:

discourse : 2.4.0beta8
discourse-docker: T2 시점의 LATEST

이제 모든 것을 다시 정상 작동시키기 위해 이전 버전으로 돌아가고 싶습니다. 따라서 Discourse의 고정 버전을 2.4.0beta2로 변경하고 다시 빌드합니다. 그러나 ./launcher rebuild web_only를 실행하면 시스템은 이제 다음과 같은 상태가 됩니다:

discourse : 2.4.0beta2
discourse-docker: T2 시점의 LATEST

Discourse의 고정 버전은 동일하지만, discourse-base(그리고 나머지 discourse-docker, 템플릿, ./launcher 자체 등)의 버전은 이제 다르기 때문에 알려진 정상 상태(known good state)로 롤백하는 것이 아니며, 아예 빌드조차 되지 않을 것이라 우려됩니다.

혹시 제가 너무 뻣뻣하게 생각하고 있는 건지 모르겠습니다. 제가 원하는 것은 업데이트 중 문제가 발생할 경우 안전 상태로 돌아갈 수 있는 기능뿐입니다. 아마도 ./launcher rebuild web_only를 다시 실행하는 것이 여기서 롤백하는 올바른 방법이 아닐 수도 있나요? 제가 배포하는 다른 시스템의 경우, 이전 Docker 이미지를 다시 배포하면 됩니다. Launcher가 이렇게 하도록 지시하는 방법이 있을까요?

음, 여기서는 프로세스를 다시 생각해봐야 할 것 같아. 우리 DB 마이그레이션은 되돌릴 수 없거든.

커밋하지 않고 업그레이드를 테스트하려면 스테이징 샌드박스에서 작업해야 해.

네, DB 마이그레이션을 롤백하는 것이 어렵다는 점은 이해합니다. Discourse는 제 배포 및 배포 관리 전략을 고려하여 설계된 것이 아니죠. 여기서 더 물에 거스를 필요는 없을 것 같습니다.

스테이징 환경이 있으므로, 재현 가능한 빌드와 배포라는 아이디어는 포기하고 스테이징에서 테스트한 후 프로덕션으로 옮길 때 손가락과 발가락을 모두 꼬고 기원하겠습니다.

도움 주셔서 감사합니다 @sam