Discourse에서 사용하는 모든 정적 자산(js, css) 수집 방법

포럼에 CDN을 설정하려고 합니다. 중국이 Fastly와 수많은 CDN 서버를 차단했기 때문에, 포럼 속도를 높이기 위해 이들을 사용할 수 없습니다. 조사 끝에 npm 또는 GitHub 저장소에서 정적 파일을 서빙할 수 있는 Jsdelivr로 눈을 돌렸습니다.

app.yml에서 DISCOURSE_CDN_URL을 사용하여 URL을 설정할 수 있다는 것을 알고 있습니다. 하지만 그 전에 포럼의 모든 정적 파일(js, CSS)을 수집하여 Jsdelivr가 접근할 수 있도록 GitHub에 업로드해야 합니다. 정적 파일은 실제로 Docker 컨테이너 내부에 위치해 있는 것을 확인했습니다:

/var/www/discourse/app/assets

따라서 앱을 다시 빌드할 때마다 이 경로에서 모든 파일을 복사하여 GitHub에 업로드하는 방안을 생각하고 있습니다. 이 아이디어가 작동할 것 같지만, 실제 요청에는 어떻게 얻어야 하는지 모르는 긴 해시 이름이 포함되어 있습니다. 예를 들어,

    ember_jquery.js는
    ember_jquery-8ef4e572f0bf9485e6ef9a35f088729735f82434cf495fbcd5acedefbcddb363.js가 됩니다.

따라서 제 질문은 다음과 같습니다.

  1. 해시 파일 이름을 생성하는 방법은 무엇인가요?
  2. 정적 에셋을 수집하는 다른 방법이 있나요?

파일 콘텐츠의 SHA1 해시입니다. 여기에서 생성됩니다:

사용되는 컴파일된 버전은 /var/www/discourse/public/assets/에 저장됩니다.

app.yml에 스탠사를 추가하면 컨테이너가 다시 빌드된 후 작업을 수행할 수 있습니다. 예를 들어, S3에 업로드하려면 다음과 유사한 것을 사용합니다:

hooks:
  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets

귀하의 경우, 컨테이너가 빌드될 때 컴파일된 에셋을 Github로 푸시하기 위해 실행하는 명령으로 rake 작업을 교체하면 됩니다.

감사합니다, @schleifer. 답변이 매우 유용합니다. 하지만 여전히 몇 가지 추가 질문이 있습니다:

  1. after_assets_precompile과 같은 훅에 대한 문서를 어디서 찾을 수 있나요? Docker 문서와 Discourse GitHub 저장소를 모두 검색해 보았지만 관련 정보를 찾을 수 없습니다. after_code처럼 Discourse에서 이미 설정되어 있는 것인지, 아니면 제가 직접 after_assets_precompile이라는 이름의 훅을 설정해야 하는 것인가요(방법이 어떻게 되나요)?

  2. 제 이해가 맞다면, 의사 코드(pseudocode)는 다음과 같이 보일 것입니다.

     hooks:
       after_assets_precompile:
         - exec:
             cd: $home
             cmd:
               - docker 컨테이너에 진입
               - `/var/www/discourse/public/assets/`로 이동
               - git add, commit 및 Github 저장소에 push
    

감사합니다.

좋은 질문이지만, 딱히 좋은 답변을 드리기 어렵습니다.

컨테이너 내부에서 사용되는 구성 시스템은 다음과 같습니다:

해당 README에는 훅이 일반적으로 어떻게 작동하는지 설명되어 있습니다. 사용할 수 있는 특정 훅은 인스턴스가 어떻게 설정되어 있는지에 따라 달라집니다. 메인 app.yml 파일에는 하나 이상의 템플릿이 포함됩니다. 대부분의 경우, 그중 하나는 web.template.yml입니다:

assets_precompile 훅은 여기서 정의되어 있습니다(작성 시점 기준 [L159] 라인). pups 문서에 따르면, before_assets_precompile과 after_assets_precompile을 사용하여 해당 작업이 완료되기 전후로 다른 명령을 실행할 수 있습니다.

명령어는 docker 컨테이너 내부에서 실행되므로, 이를 위해 별도의 조치는 취할 필요가 없습니다.

cd: 지시문은 /var/www/discourse/public/assets/ 경로로 바로 지정할 수 있으며, cmd의 각 줄은 해당 디렉터리에서 실행됩니다. (경고: cmd 배열의 각 줄은 Makefile과 마찬가지로 별도의 셸에서 실행됩니다.)

빌드 간에 /var/www/discourse/public/assets/의 내용이 유지되는지 확실하지 않으므로, 로컬 git 저장소를 생성하고 매번 강제 푸시(force push)해야 할 수 있습니다. “더 정확한” 해결책은 app.yml에 정의된 다른 볼륨들처럼 app.yml에서 자산 디렉터리를 위한 docker 볼륨을 정의하여 컨테이너 외부에 영구적으로 저장하는 것입니다.

정말 감사합니다. 또한 일부 정적 자산(CSS 등)은 /var/www/discourse/tmp/stylesheet-cache에 저장되는 것을 확인했습니다. 하지만 두 가지 다른 문제가 있습니다:

  1. DISCOURSE_CDN_URL을 설정한 후에도 사용자가 업로드한 아바타와 같은 자산은 CDN을 통해 서빙됩니다. 그러나 사용자가 업로드할 때마다 업로드 자산을 GitHub에 푸시하는 것은 좋은 해결책이 아닙니다.
  2. Discourse가 2_2.png와 같은 user_avatar를 요청할 때, 1) 파일 이름을 분리하고, 2) 몇 가지 검사를 수행하며, 3) 해시를 사용하여 실제 파일 이름을 계산합니다. 2_2.png라는 이름의 파일이 없으므로 사용자 아바타를 서빙하려면 동일한 로직을 직접 구현해야 합니다.

제 최종 해결책은 간단합니다. 1) 이 게시글(Run other websites on the same machine as Discourse)과 유사하게 포럼 앞에 Nginx를 추가했습니다. 2) 위의 경로에서 모든 정적 자산을 수집하여 GitHub에 푸시했습니다. 3) Nginx 설정 파일에 다음과 같은 규칙을 추가했습니다.

location ~/(stylesheets|assets) {
    return 301 https://cdn.jsdelivr.net/gh/my_github/my_repo/$request_uri;
}

다시 한번 감사합니다 @schleifer